Initial import, far from there

master
haddaway 2012-10-20 15:38:28 -07:00
parent eca5e0475d
commit 0a43947937
31 changed files with 29081 additions and 0 deletions

39
libtoorchat.py Normal file
View File

@ -0,0 +1,39 @@
class ToorChatProtocol():
''' This is a class to allow for easy of use with anything to do with messaging '''
def __init__(self, device):
self.PACKET_START = "\xFF\xDE\xAD\xFF"
self.PACKET_END = "\xFF\xBE\xEF\xFF"
self.device = device
def send_message(cls, message = "", user = None):
''' This is used to send a simple message over the toorchat protocol '''
msg = ToorChatMessage(message, user)
self.device.RFxmit(msg)
@classmethod
def get_packet_start(cls):
return "\xFF\xDE\xAD\xFF"
@classmethod
def get_packet_end(cls):
return "\xFF\xBE\xEF\xFF"
class ToorChatMessage():
''' This is a simple Message object wrapper to make things cleaner '''
def __init__(self, message = "", user = None):
self.start = ToorChatProtocol.get_packet_start()
self.xid = self.get_random_xid()
if user != None:
self.user = user
else:
self.user = "\x00"*32
self.data = message
self.end = ToorChatProtocol.get_packet_end()
def __str__(self):
return self.start + self.xid + self.user + self.data + self.end
def to_string(self):
return self.__str__()

163
rflib/__init__.py Executable file
View File

@ -0,0 +1,163 @@
#!/usr/bin/env ipython
from chipcon_nic import *
RFCAT_START_SPECAN = 0x40
RFCAT_STOP_SPECAN = 0x41
class RfCat(FHSSNIC):
def RFdump(self, msg="Receiving", maxnum=100, timeoutms=1000):
try:
for x in xrange(maxnum):
y, t = self.RFrecv(timeoutms)
print "(%5.3f) %s: %s" % (t, msg, y.encode('hex'))
except ChipconUsbTimeoutException:
pass
def scan(self, basefreq=902e6, inc=250e3, count=104, delaysec=2, drate=38400, lowball=1):
'''
scan for signal over a range of frequencies
'''
self.RFdump("Clearing")
self.lowball(lowball)
self.setMdmDRate(drate)
print "Scanning range: "
while not keystop():
try:
print
for freq in xrange(int(basefreq), int(basefreq+(inc*count)), int(inc)):
print "Scanning for frequency %d..." % freq
self.setFreq(freq)
self.RFdump(timeoutms=delaysec*1000)
if keystop():
break
except KeyboardInterrupt:
print "Please press <enter> to stop"
sys.stdin.read(1)
self.lowballRestore()
def specan(self, basefreq=902e6, inc=250e3, count=104):
freq, delta = self._doSpecAn(basefreq, inc, count)
import rflib.ccspecan as rfspecan
if not hasattr(self, "_qt_app") or self._qt_app is None:
self._qt_app = rfspecan.QtGui.QApplication([])
fhigh = freq + (delta*(count+1))
window = rfspecan.Window(self, freq, fhigh, delta, 0)
window.show()
self._qt_app.exec_()
def _doSpecAn(self, basefreq, inc, count):
'''
store radio config and start sending spectrum analysis data
'''
if count>255:
raise Exception("sorry, only 255 samples per pass... (count)")
self.getRadioConfig()
self._specan_backup_radiocfg = self.radiocfg
self.setFreq(basefreq)
self.setMdmChanSpc(inc)
freq, fbytes = self.getFreq()
delta = self.getMdmChanSpc()
self.send(APP_NIC, RFCAT_START_SPECAN, "%c" % (count) )
return freq, delta
def _stopSpecAn(self):
'''
stop sending rfdata and return radio to original config
'''
self.send(APP_NIC, RFCAT_STOP_SPECAN, '')
self.radiocfg = self._specan_backup_radiocfg
self.setRadioConfig()
def rf_configure(*args, **k2args):
pass
def rf_redirection(self, fdtup):
if len(fdtup)>1:
fd0i, fd0o = fdtup
else:
fd0i, = fdtup
fd0o, = fdtup
fdsock = False # socket or fileio?
if hasattr(fd0i, 'recv'):
fdsock = True
while True:
x,y,z = select.select([fd0i ], [], [], .1)
#if self._pause:
# continue
if fd0i in x:
if fdsock:
data = fd0i.recv(self.max_packet_size)
else:
data = fd0i.read(self.max_packet_size)
if not len(data): # terminated socket
break
self.RFxmit(data)
try:
data = self.RFrecv(0)
if fdsock:
fd0o.sendall(data)
else:
fd0o.write(data)
except ChipconUsbTimeoutException:
pass
def cleanupInteractiveAtExit():
try:
if d.getDebugCodes():
d.setModeIDLE()
pass
except:
pass
def interactive(idx=0, DongleClass=RfCat, intro=''):
global d
import rflib.chipcon_nic as rfnic
import atexit
d = DongleClass(idx=idx)
d.setModeRX() # this puts the dongle into receive mode
atexit.register(cleanupInteractiveAtExit)
gbls = globals()
lcls = locals()
try:
import IPython.Shell
ipsh = IPython.Shell.IPShell(argv=[''], user_ns=lcls, user_global_ns=gbls)
print intro
ipsh.mainloop(intro)
except ImportError, e:
try:
from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
ipsh = TerminalInteractiveShell()
ipsh.user_global_ns.update(gbls)
ipsh.user_global_ns.update(lcls)
ipsh.autocall = 2 # don't require parenthesis around *everything*. be smart!
ipsh.mainloop(intro)
except ImportError, e:
print e
shell = code.InteractiveConsole(gbls)
shell.interact(intro)
if __name__ == "__main__":
idx = 0
if len(sys.argv) > 1:
idx = int(sys.argv.pop())
interactive(idx)

347
rflib/bits.py Normal file
View File

@ -0,0 +1,347 @@
import struct
def shiftString(string, bits):
carry = 0
news = []
for x in xrange(len(string)-1):
newc = ((ord(string[x]) << bits) + (ord(string[x+1]) >> (8-bits))) & 0xff
news.append("%c"%newc)
newc = (ord(string[-1])<<bits) & 0xff
news.append("%c"%newc)
return "".join(news)
def findDword(byts, inverted=False):
possDwords = []
# find the preamble (if any)
while True:
sbyts = byts
pidx = byts.find("\xaa\xaa")
if pidx == -1:
pidx = byts.find("\x55\x55")
byts = shiftString(byts,1)
if pidx == -1:
return possDwords
# chop off the nonsense before the preamble
sbyts = byts[pidx:]
#print "sbyts: %s" % repr(sbyts)
# find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
while (sbyts[0] == '\xaa' and len(sbyts)>2):
sbyts = sbyts[1:]
#print "sbyts: %s" % repr(sbyts)
# now we look at the next 16 bits to narrow the possibilities to 8
# at this point we have no hints at bit-alignment aside from 0xaa vs 0x55
dwbits, = struct.unpack(">H", sbyts[:2])
#print "sbyts: %s" % repr(sbyts)
#print "dwbits: %s" % repr(dwbits)
if len(sbyts)>=3:
bitcnt = 0
# bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
# bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bits1, = struct.unpack(">H", sbyts[:2])
bits1 = bits1 | (ord('\xaa') << 16)
bits1 = bits1 | (ord('\xaa') << 24)
bits1 <<= 8
bits1 |= (ord(sbyts[2]) )
#print "bits: %x" % (bits1)
bit = (5 * 8) - 2 # bytes times bits/byte #FIXME: MAGIC NUMBERS!?
while (bits1 & (3<<bit) == (2<<bit)):
bit -= 2
#print "bit = %d" % bit
bits1 >>= (bit-16)
#while (bits1 & 0x30000 != 0x20000): # now we align the end of the 101010 pattern with the beginning of the dword
# bits1 >>= 2
#print "bits: %x" % (bits1)
for frontbits in xrange((0,1)[inverted], 17, 2):
poss = (bits1 >> frontbits) & 0xffff
if not poss in possDwords:
possDwords.append(poss)
byts = byts[pidx+1:]
return possDwords
def findDwordDoubled(byts):
possDwords = []
# find the preamble (if any)
bitoff = 0
pidx = byts.find("\xaa\xaa")
if pidx == -1:
pidx = byts.find("\55\x55")
bitoff = 1
if pidx == -1:
return []
# chop off the nonsense before the preamble
byts = byts[pidx:]
# find the definite end of the preamble (ie. it may be sooner, but we know this is the end)
while (byts[0] == ('\xaa', '\x55')[bitoff] and len(byts)>2):
byts = byts[1:]
# now we look at the next 16 bits to narrow the possibilities to 8
# at this point we have no hints at bit-alignment
dwbits, = struct.unpack(">H", byts[:2])
if len(byts)>=5:
bitcnt = 0
# bits1 = aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb
# bits2 = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bits1, = struct.unpack(">H", byts[:2])
bits1 = bits1 | (ord(('\xaa','\x55')[bitoff]) << 16)
bits1 = bits1 | (ord(('\xaa','\x55')[bitoff]) << 24)
bits1 <<= 8
bits1 |= (ord(byts[2]) )
bits1 >>= bitoff
bits2, = struct.unpack(">L", byts[:4])
bits2 <<= 8
bits2 |= (ord(byts[4]) )
bits2 >>= bitoff
frontbits = 0
for frontbits in xrange(16, 40, 2): #FIXME: if this doesn't work, try 16, then 18+frontbits
dwb1 = (bits1 >> (frontbits)) & 3
dwb2 = (bits2 >> (frontbits)) & 3
print "\tfrontbits: %d \t\t dwb1: %s dwb2: %s" % (frontbits, bin(bits1 >> (frontbits)), bin(bits2 >> (frontbits)))
if dwb2 != dwb1:
break
# frontbits now represents our unknowns... let's go from the other side now
for tailbits in xrange(16, -1, -2):
dwb1 = (bits1 >> (tailbits)) & 3
dwb2 = (bits2 >> (tailbits)) & 3
print "\ttailbits: %d\t\t dwb1: %s dwb2: %s" % (tailbits, bin(bits1 >> (tailbits)), bin(bits2 >> (tailbits)))
if dwb2 != dwb1:
tailbits += 2
break
# now, if we have a double syncword, iinm, tailbits + frontbits >= 16
print "frontbits: %d\t\t tailbits: %d, bits: %s " % (frontbits, tailbits, bin((bits2>>tailbits & 0xffffffff)))
if (frontbits + tailbits >= 16):
tbits = bits2 >> (tailbits&0xffff)
tbits &= (0xffffffff)
print "tbits: %x" % tbits
poss = tbits&0xffffffff
if poss not in possDwords:
possDwords.append(poss)
else:
pass
# FIXME: what if we *don't* have a double-sync word? then we stop at AAblah or 55blah and take the next word?
possDwords.reverse()
return possDwords
#def test():
def visBits(data):
pass
def getBit(data, bit):
idx = bit / 8
bidx = bit % 8
char = data[idx]
return (ord(char)>>(7-bidx)) & 1
def detectRepeatPatterns(data, size=64, minEntropy=.07):
#FIXME: convert strings to bit arrays before comparing.
c1 = 0
c2 = 0
d1 = 0
p1 = 0
mask = (1<<size) - 1
bitlen = 8*len(data)
while p1 < (bitlen-size-8):
d1 <<= 1
d1 |= getBit(data, p1)
d1 &= mask
#print bin(d1)
if c1 < (size):
p1 += 1
c1 += 1
continue
d2 = 0
p2 = p1+size
while p2 < (bitlen):
d2 <<= 1
d2 |= getBit(data, p2)
d2 &= mask
#print bin(d2)
if c2 < (size):
p2 += 1
c2 += 1
continue
if d1 == d2 and d1 > 0:
s1 = p1 - size
s2 = p2 - size
print "s1: %d\t p1: %d\t " % (s1, p1)
print "s2: %d\t p2: %d\t " % (s2, p2)
# complete the pattern until the numbers differ or meet
while True:
p1 += 1
p2 += 1
#print "s1: %d\t p1: %d\t " % (s1, p1)
#print "s2: %d\t p2: %d\t " % (s2, p2)
if p2 >= bitlen:
break
b1 = getBit(data,p1)
b2 = getBit(data,p2)
if p1 == s2 or b1 != b2:
break
length = p1 - s1
c2 = 0
p2 -= size
bitSection, ent = bitSectString(data, s1, s1+length)
if ent > minEntropy:
print "success:"
print " * bit idx1: %4d (%4d bits) - '%s' %s" % (s1, length, bin(d1), bitSection.encode("hex"))
print " * bit idx2: %4d (%4d bits) - '%s'" % (s2, length, bin(d2))
#else:
# print " * idx1: %d - '%s' * idx2: %d - '%s'" % (p1, d1, p2, d2)
p2 += 1
p1 += 1
def bitSectString(string, startbit, endbit):
'''
bitsects a string... ie. chops out the bits from the middle of the string
returns the new string and the entropy (ratio of 0:1)
'''
ones = 0
zeros = 0
entropy = [zeros, ones]
s = ''
bit = startbit
Bidx = bit / 8
bidx = (bit % 8)
while bit < endbit:
byte1 = ord( string[Bidx] )
try:
byte2 = ord( string[Bidx+1] )
except IndexError:
byte2 = 0
byte = (byte1 << bidx) & 0xff
byte |= (byte2 >> (8-bidx))
#calculate entropy over the byte
for bi in range(8):
b = (byte>>bi) & 1
entropy[b] += 1
bit += 8
Bidx += 1
if bit > endbit:
diff = bit-endbit
mask = ~ ( (1<<diff) - 1 )
byte &= mask
s += chr(byte)
ent = (min(entropy)+1.0) / (max(entropy)+1)
#print "entropy: %f" % ent
return (s, ent)
def genBitArray(string, startbit, endbit):
'''
bitsects a string... ie. chops out the bits from the middle of the string
returns the new string and the entropy (ratio of 0:1)
'''
binStr, ent = bitSectString(string, startbit, endbit)
s = []
for byte in binStr:
byte = ord(byte)
for bitx in range(7, -1, -1):
bit = (byte>>bitx) & 1
s.append(bit)
return (s, ent)
chars_top = [
" ", #000
" ", #001
"^", #010
"/", #011
" ", #100
" ", #101
"\\",#110
"-", #111
]
chars_mid = [
" ", #000
"|", #001
"#", #010
" ", #011
"|", #100
"#", #101
" ", #110
" ", #110
]
chars_bot = [
"-", #000
"/", #001
" ", #010
" ", #011
"\\",#100
"V", #101
" ", #110
" ", #110
]
def reprBitArray(bitAry, width=194):
top = []
mid = []
bot = []
arylen = len(bitAry)
# top line
#FIXME: UGGGGLY and kinda broken.
fraction = 1.0 * arylen/width
expand = [bitAry[int(x*fraction)] for x in xrange(width)]
for bindex in xrange(width):
bits = 0
if bindex>0:
bits += (expand[bindex-1]) << (2)
bits += (expand[bindex]) << (1)
if bindex < width-1:
bits += (expand[bindex+1])
top.append( chars_top[ bits ] )
mid.append( chars_mid[ bits ] )
bot.append( chars_bot[ bits ] )
tops = "".join(top)
mids = "".join(mid)
bots = "".join(bot)
return "\n".join([tops, mids, bots])

2380
rflib/cc1111client.py Normal file

File diff suppressed because it is too large Load Diff

147
rflib/cc111Xhparser.py Normal file
View File

@ -0,0 +1,147 @@
#!/usr/bin/env python
"""
#include<compiler.h>
/* ------------------------------------------------------------------------------------------------
* Interrupt Vectors
* ------------------------------------------------------------------------------------------------
*/
#define RFTXRX_VECTOR 0 /* RF TX done / RX ready */
#define ADC_VECTOR 1 /* ADC End of Conversion */
#define URX0_VECTOR 2 /* USART0 RX Complete */
#define URX1_VECTOR 3 /* USART1 RX Complete */
#define ENC_VECTOR 4 /* AES Encryption/Decryption Complete */
#define ST_VECTOR 5 /* Sleep Timer Compare */
#define P2INT_VECTOR 6 /* Port 2 Inputs */
#define UTX0_VECTOR 7 /* USART0 TX Complete */
#define DMA_VECTOR 8 /* DMA Transfer Complete */
#define T1_VECTOR 9 /* Timer 1 (16-bit) Capture/Compare/Overflow */
#define T2_VECTOR 10 /* Timer 2 (MAC Timer) Overflow */
#define T3_VECTOR 11 /* Timer 3 (8-bit) Capture/Compare/Overflow */
#define T4_VECTOR 12 /* Timer 4 (8-bit) Capture/Compare/Overflow */
#define P0INT_VECTOR 13 /* Port 0 Inputs */
#define UTX1_VECTOR 14 /* USART1 TX Complete */
#define P1INT_VECTOR 15 /* Port 1 Inputs */
#define RF_VECTOR 16 /* RF General Interrupts */
#define WDT_VECTOR 17 /* Watchdog Overflow in Timer Mode */
SFR(P0, 0x80); // Port 0
SBIT(P0_0, 0x80, 0); // Port 0 bit 0
SBIT(P0_1, 0x80, 1); // Port 0 bit 1
SBIT(P0_2, 0x80, 2); // Port 0 bit 2
SBIT(P0_3, 0x80, 3); // Port 0 bit 3
SBIT(P0_4, 0x80, 4); // Port 0 bit 4
SBIT(P0_5, 0x80, 5); // Port 0 bit 5
SBIT(P0_6, 0x80, 6); // Port 0 bit 6
SBIT(P0_7, 0x80, 7); // Port 0 bit 7
SFR(SP, 0x81); // Stack Pointer
SFR(DPL0, 0x82); // Data Pointer 0 Low Byte
SFR(DPH0, 0x83); // Data Pointer 0 High Byte
SFR(DPL1, 0x84); // Data Pointer 1 Low Byte
SFR(DPH1, 0x85); // Data Pointer 1 High Byte
"""
import sys
def parseLines(lines):
defs = {}
incomment = False
for line in lines:
# find single-line comments
slc = line.find("//")
if (slc > -1):
line = line[:slc] + "#" + line[slc+2:]
# find /* */ comments
mlcs = line.find("/*")
mlce = line.find("*/")
if (mlcs>-1):
if (mlce>-1): # both are in this line
if (mlce>mlcs): # they are "together"
if (mlce >= len(line.strip())-3):
line = line[:mlcs] + '#' + line[mlcs+2:mlce]
else:
line = line[:mlcs] + '"""' + line[mlcs+2:mlce] + '"""' + line[mlce+2:]
else: # they are *not* together
line = line[mlce+2:mlcs]
else: # only the beginning is in this line, treat like a single-line comment for now
line = line[:mlcs]
incomment = True
elif incomment: # no mlc-starter found... are we incomment? then ignore until the end of comment
if (mlce>-1):
line = line[mlce+2:]
incomment = False
else:
line = ''
if incomment: # if we're still incomment, this whole line is comment
continue
# chop initial and trailing whitespace
line = line.strip()
# now we can actually parse the line
if (line.startswith("#define ")):
line = line[8:].strip() # peel off any additional spaces after the #define
pieces = line.split(" ", 1)
if len(pieces)<2:
continue
name, value = pieces
if "(" in name:
print >>sys.stderr,("SKIPPING: %s"%(line))
continue # skip adding "function" defines
defs[name.strip()] = value.strip()
elif (line.startswith("SFR(")):
endparen = line.find(")")
if (endparen == -1):
print >>sys.stderr,("ERROR: SFR without end parens: '%s'"%(line))
continue
line = line[4:endparen].strip()
name, value = line.split(",", 1)
defs[name.strip()] = value.strip()
elif (line.startswith("SFRX(")):
endparen = line.find(")")
if (endparen == -1):
print >>sys.stderr,("ERROR: SFRX without end parens: '%s'"%(line))
continue
line = line[5:endparen].strip()
name, value = line.split(",", 1)
defs[name.strip()] = value.strip()
elif (line.startswith("SBIT")):
endparen = line.find(")")
if (endparen == -1):
print >>sys.stderr,("ERROR: SBIT without end parens: '%s'"%(line))
continue
line = line[5:endparen].strip()
name, val1, val2 = line.split(",", 2)
defs[name.strip()] = 1 << (int(val2.strip()))
return defs
if __name__ == '__main__':
defs = {}
defs.update(parseLines(file('../includes/cc1110-ext.h')))
defs.update(parseLines(file('../includes/cc1111.h')))
defs.update(parseLines(file('/usr/share/sdcc/include/mcs51/cc1110.h')))
skeys = defs.keys()
skeys.sort()
out = ["%-30s = %s"%(key,defs[key]) for key in skeys]
trueout = []
for x in out:
try:
compile(x,'stdin','exec')
trueout.append(x)
print(x)
except:
sys.excepthook(*sys.exc_info())

18
rflib/ccrecvdump.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/python
import sys, serial
port = "ACM0"
if len(sys.argv) > 1:
port = sys.argv.pop()
dport = "/dev/tty" + port
print "Opening serial port %s for listening..." % dport
s=serial.Serial(dport, 115200)
counter = 0
while True:
print ("%d: %s" % (counter, repr(s.read(12))))
counter += 1
#sys.stdout.write(s.read(1))
#sys.stdout.flush()

311
rflib/ccspecan.py Executable file
View File

@ -0,0 +1,311 @@
#!/usr/bin/env python
#
# Copyright 2012 atlas
#
# This file was adapted from a part of Project Ubertooth written by Jared Boone
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
import sys
import time
import numpy
import threading
import rflib
import cPickle as pickle
from PySide import QtCore, QtGui
from PySide.QtCore import Qt, QPointF, QLineF
APP_SPECAN = 0x43
SPECAN_QUEUE = 1
class SpecanThread(threading.Thread):
def __init__(self, data, low_frequency, high_frequency, freq_step, delay, new_frame_callback):
threading.Thread.__init__(self)
self.daemon = True
self._data = data
self._delay = delay
self._low_frequency = low_frequency
self._high_frequency = high_frequency
self._freq_step = freq_step
self._new_frame_callback = new_frame_callback
self._stop = False
self._stopped = False
def run(self):
# this is where we pull in the data from the device
#frame_source = self._device.specan(self._low_frequency, self._high_frequency)
num_chans = int((self._high_frequency - self._low_frequency) / self._freq_step)
if type(self._data) == list:
for rssi_values, timestamp in self._data:
rssi_values = [ ((ord(x)^0x80)/2)-88 for x in rssi_values[4:] ]
# since we are not accessing the dongle, we need some sort of delay
time.sleep(self._delay)
frequency_axis = numpy.linspace(self._low_frequency, self._high_frequency, num=len(rssi_values), endpoint=True)
self._new_frame_callback(numpy.copy(frequency_axis), numpy.copy(rssi_values))
if self._stop:
break
else:
while not self._stop:
try:
rssi_values, timestamp = self._data.recv(APP_SPECAN, SPECAN_QUEUE, 10000)
rssi_values = [ ((ord(x)^0x80)/2)-88 for x in rssi_values ]
frequency_axis = numpy.linspace(self._low_frequency, self._high_frequency, num=len(rssi_values), endpoint=True)
self._new_frame_callback(numpy.copy(frequency_axis), numpy.copy(rssi_values))
except:
sys.excepthook(*sys.exc_info())
self._data._stopSpecAn()
def stop(self):
self._stop = True
self.join(3.0)
self._stopped = True
class RenderArea(QtGui.QWidget):
def __init__(self, data, low_freq=2.400e9, high_freq=2.483e9, freq_step=1e6, delay=0, parent=None):
QtGui.QWidget.__init__(self, parent)
self._graph = None
self._reticle = None
self._data = data
self._delay = delay
self._frame = None
self._persisted_frames = None
self._persisted_frames_depth = 350
self._path_max = None
self._low_frequency = low_freq #2.400e9
self._high_frequency = high_freq #2.483e9
self._frequency_step = freq_step #1e6
self._high_dbm = 0.0
self._low_dbm = -100.0
self._thread = SpecanThread(self._data,
self._low_frequency,
self._high_frequency,
self._frequency_step,
self._delay,
self._new_frame)
self._thread.start()
def stop_thread(self):
self._thread.stop()
def _new_graph(self):
self._graph = QtGui.QPixmap(self.width(), self.height())
self._graph.fill(Qt.black)
def _new_reticle(self):
self._reticle = QtGui.QPixmap(self.width(), self.height())
self._reticle.fill(Qt.transparent)
def _new_persisted_frames(self, frequency_bins):
self._persisted_frames = numpy.empty((self._persisted_frames_depth, frequency_bins))
self._persisted_frames.fill(-128 + -54)
self._persisted_frames_next_index = 0
def minimumSizeHint(self):
x_points = round((self._high_frequency - self._low_frequency) / self._frequency_step)
y_points = round(self._high_dbm - self._low_dbm)
return QtCore.QSize(x_points * 4, y_points * 1)
def _new_frame(self, frequency_axis, rssi_values):
#print repr(frequency_axis)
#print repr(rssi_values)
self._frame = (frequency_axis, rssi_values)
if self._persisted_frames is None:
self._new_persisted_frames(len(frequency_axis))
self._persisted_frames[self._persisted_frames_next_index] = rssi_values
self._persisted_frames_next_index = (self._persisted_frames_next_index + 1) % self._persisted_frames.shape[0]
self.update()
def _draw_graph(self):
if self._graph is None:
self._new_graph()
elif self._graph.size() != self.size():
self._new_graph()
painter = QtGui.QPainter(self._graph)
try:
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.fillRect(0, 0, self._graph.width(), self._graph.height(), QtGui.QColor(0, 0, 0, 10))
if self._frame:
frequency_axis, rssi_values = self._frame
path_now = QtGui.QPainterPath()
path_max = QtGui.QPainterPath()
bins = range(len(frequency_axis))
x_axis = self._hz_to_x(frequency_axis)
y_now = self._dbm_to_y(rssi_values)
y_max = self._dbm_to_y(numpy.amax(self._persisted_frames, axis=0))
# TODO: Wrapped Numpy types with float() to support old (<1.0) PySide API in Ubuntu 10.10
path_now.moveTo(float(x_axis[0]), float(y_now[0]))
for i in bins:
path_now.lineTo(float(x_axis[i]), float(y_now[i]))
# TODO: Wrapped Numpy types with float() to support old (<1.0) PySide API in Ubuntu 10.10
path_max.moveTo(float(x_axis[0]), float(y_max[0]))
for i in bins:
path_max.lineTo(float(x_axis[i]), float(y_max[i]))
painter.setPen(Qt.white)
painter.drawPath(path_now)
self._path_max = path_max
finally:
painter.end()
def _draw_reticle(self):
if self._reticle is None or (self._reticle.size() != self.size()):
self._new_reticle()
dbm_lines = [QLineF(self._hz_to_x(self._low_frequency), self._dbm_to_y(dbm),
self._hz_to_x(self._high_frequency), self._dbm_to_y(dbm))
for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0)]
dbm_labels = [(dbm, QPointF(self._hz_to_x(self._low_frequency) + 2, self._dbm_to_y(dbm) - 2))
for dbm in numpy.arange(self._low_dbm, self._high_dbm, 20.0)]
frequency_lines = [QLineF(self._hz_to_x(frequency), self._dbm_to_y(self._high_dbm),
self._hz_to_x(frequency), self._dbm_to_y(self._low_dbm))
for frequency in numpy.arange(self._low_frequency, self._high_frequency, self._frequency_step * 20.0)]
frequency_labels = [(frequency, QPointF(self._hz_to_x(frequency) + 2, self._dbm_to_y(self._high_dbm) + 10))
for frequency in numpy.arange(self._low_frequency, self._high_frequency, self._frequency_step * 10.0)]
painter = QtGui.QPainter(self._reticle)
try:
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(Qt.blue)
# TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10
#painter.drawLines(dbm_lines)
for dbm_line in dbm_lines: painter.drawLine(dbm_line)
# TODO: Removed to support old (<1.0) PySide API in Ubuntu 10.10
#painter.drawLines(frequency_lines)
for frequency_line in frequency_lines: painter.drawLine(frequency_line)
painter.setPen(Qt.white)
for dbm, point in dbm_labels:
painter.drawText(point, '%+.0f' % dbm)
for frequency, point in frequency_labels:
painter.drawText(point, '%.02f' % (frequency / 1e6))
finally:
painter.end()
def paintEvent(self, event):
self._draw_graph()
self._draw_reticle()
painter = QtGui.QPainter(self)
try:
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QPen())
painter.setBrush(QtGui.QBrush())
if self._graph:
painter.drawPixmap(0, 0, self._graph)
if self._path_max:
painter.setPen(Qt.green)
painter.drawPath(self._path_max)
painter.setOpacity(0.5)
if self._reticle:
painter.drawPixmap(0, 0, self._reticle)
finally:
painter.end()
def _hz_to_x(self, frequency_hz):
delta = frequency_hz - self._low_frequency
range = self._high_frequency - self._low_frequency
normalized = delta / range
#print "freq: %s \nlow: %s \nhigh: %s \ndelta: %s \nrange: %s \nnormalized: %s" % (frequency_hz, self._low_frequency, self._high_frequency, delta, range, normalized)
return normalized * self.width()
def _dbm_to_y(self, dbm):
delta = self._high_dbm - dbm
range = self._high_dbm - self._low_dbm
normalized = delta / range
return normalized * self.height()
class Window(QtGui.QWidget):
def __init__(self, data, low_freq, high_freq, spacing, delay=.01, parent=None):
QtGui.QWidget.__init__(self, parent)
self._low_freq = low_freq
self._high_freq = high_freq
self._spacing = spacing
self._data = self._open_data(data)
self.render_area = RenderArea(self._data, low_freq, high_freq, spacing, delay)
main_layout = QtGui.QGridLayout()
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.addWidget(self.render_area, 0, 0)
self.setLayout(main_layout)
self.setWindowTitle("RfCat Spectrum Analyzer (thanks Ubertooth!)")
def sizeHint(self):
return QtCore.QSize(480, 160)
def _open_data(self, data):
if type(data) == str:
if data == '-':
data = rflib.RfCat()
data._debug = 1
freq = int(self._low_freq)
spc = int(self._spacing)
numChans = int((self._high_freq-self._low_freq) / self._spacing)
data._doSpecAn(freq, spc, numChans)
else:
data = pickle.load(file(data,'rb'))
if data is None:
raise Exception('Data not found')
return data
def closeEvent(self, event):
self.render_area.stop_thread()
event.accept()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
f = sys.argv[1]
fbase = eval(sys.argv[2])
fhigh = eval(sys.argv[3])
fdelta = eval(sys.argv[4])
if len(sys.argv) > 5:
delay = eval(sys.argv[5])
else:
delay = .01
window = Window(f, fbase, fhigh, fdelta, delay)
#window = Window('../data.again', 902.0, 928.0, 3e-1)
window.show()
sys.exit(app.exec_())

455
rflib/chipcon_nic.py Normal file
View File

@ -0,0 +1,455 @@
#!/usr/bin/env ipython
import sys
import usb
import code
import time
import struct
import threading
import re
#from chipcondefs import *
from cc1111client import *
APP_NIC = 0x42
NIC_RECV = 0x1
NIC_XMIT = 0x2
NIC_SET_ID = 0x3
NIC_RFMODE = 0x4
NIC_SET_RECV_LARGE = 0x5
NIC_SET_AES_MODE = 0x6
NIC_GET_AES_MODE = 0x7
NIC_SET_AES_IV = 0x8
NIC_SET_AES_KEY = 0x9
FHSS_SET_CHANNELS = 0x10
FHSS_NEXT_CHANNEL = 0x11
FHSS_CHANGE_CHANNEL = 0x12
FHSS_SET_MAC_THRESHOLD = 0x13
FHSS_GET_MAC_THRESHOLD = 0x14
FHSS_SET_MAC_DATA = 0x15
FHSS_GET_MAC_DATA = 0x16
FHSS_XMIT = 0x17
FHSS_GET_CHANNELS = 0x18
FHSS_SET_STATE = 0x20
FHSS_GET_STATE = 0x21
FHSS_START_SYNC = 0x22
FHSS_START_HOPPING = 0x23
FHSS_STOP_HOPPING = 0x24
FHSS_STATE_NONHOPPING = 0
FHSS_STATE_DISCOVERY = 1
FHSS_STATE_SYNCHING = 2
FHSS_LAST_NONHOPPING_STATE = FHSS_STATE_SYNCHING
FHSS_STATE_SYNCHED = 3
FHSS_STATE_SYNC_MASTER = 4
FHSS_STATE_SYNCINGMASTER = 5
FHSS_LAST_STATE = 5 # used for testing
FHSS_STATES = {}
for key,val in globals().items():
if key.startswith("FHSS_STATE_"):
FHSS_STATES[key] = val
FHSS_STATES[val] = key
T2SETTINGS = {}
T2SETTINGS_24MHz = {
100: (4, 147, 3),
150: (5, 110, 3),
200: (5, 146, 3),
250: (5, 183, 3),
}
T2SETTINGS_26MHz = {
100: (4, 158, 3),
150: (5, 119, 3),
200: (5, 158, 3),
250: (5, 198, 3),
}
TIP = (64,128,256,1024)
def calculateT2(ms, mhz=24):
TICKSPD = [(mhz*1000000/pow(2,x)) for x in range(8)]
ms = 1.0*ms/1000
candidates = []
for tickidx in xrange(8):
for tipidx in range(4):
for PR in xrange(256):
T = 1.0 * PR * TIP[tipidx] / TICKSPD[tickidx]
if abs(T-ms) < .010:
candidates.append((T, tickidx, tipidx, PR))
diff = 1024
best = None
for c in candidates:
if abs(c[0] - ms) < diff:
best = c
diff = abs(c[0] - ms)
return best
#return ms, candidates, best
def invertBits(data):
output = []
ldata = len(data)
off = 0
if ldata&1:
output.append( chr( ord( data[0] ) ^ 0xff) )
off = 1
if ldata&2:
output.append( struct.pack( "<H", struct.unpack( "<H", data[off:off+2] )[0] ^ 0xffff) )
off += 2
#method 1
#for idx in xrange( off, ldata, 4):
# output.append( struct.pack( "<I", struct.unpack( "<I", data[idx:idx+4] )[0] & 0xffff) )
#method2
count = ldata / 4
#print ldata, count
numlist = struct.unpack( "<%dI" % count, data[off:] )
modlist = [ struct.pack("<L", (x^0xffffffff) ) for x in numlist ]
output.extend(modlist)
return ''.join(output)
class FHSSNIC(USBDongle):
def __init__(self, idx=0, debug=False, copyDongle=None):
USBDongle.__init__(self, idx, debug, copyDongle)
def setRfMode(self, rfmode, parms=''):
r = self.send(APP_NIC, NIC_RFMODE, "%c"%rfmode + parms)
def setAESmode(self, aesmode=AES_CRYPTO_DEFAULT):
'''
set AES crypto co-processor mode.
crypto operations on inbound and outbound RF packets are independently supported
as is the type of operation. normally this would be ENCRYPT on outbound and DECRYPT
on inbound.
aesmode is a bitfield. the upper half mirrors the CC1111 standard modes (CBC, ECB etc.),
and the lower half flags whether to encrypt or not on inbound/outbound as well as which
operation to perform:
aesmode[7:4] ENCCS_MODE...
aesmode[3] OUTBOUND 0 == OFF, 1 == ON
aesmode[2] OUTBOUND 0 == Decrypt, 1 == Encrypt
aesmode[1] INBOUND 0 == OFF, 1 == ON
aesmode[0] INBOUND 0 == Decrypt, 1 == Encrypt
the following are defined in chipcondefs.
valid CC1111 modes are:
ENCCS_MODE_CBC
ENCCS_MODE_CBCMAC
ENCCS_MODE_CFB
ENCCS_MODE_CTR
ENCCS_MODE_ECB
ENCCS_MODE_OFB
valid AES operational modes are:
AES_CRYPTO_IN_ON
AES_CRYPTO_IN_OFF
AES_CRYPTO_IN_ENCRYPT
AES_CRYPTO_IN_DECRYPT
AES_CRYPTO_OUT_ON
AES_CRYPTO_OUT_OFF
AES_CRYPTO_OUT_ENCRYPT
AES_CRYPTO_OUT_DECRYPT
aesmode is made up of the appropriate combination of the above.
default is CBC mode, crypto enabled IN and OUT:
(ENCCS_MODE_CBC | AES_CRYPTO_OUT_ON | AES_CRYPTO_OUT_ENCRYPT | AES_CRYPTO_IN_ON | AES_CRYPTO_IN_DECRYPT)
'''
return self.send(APP_NIC, NIC_SET_AES_MODE, "%c"%aesmode)
def getAESmode(self):
'''
get the currently set AES co-processor mode
'''
return self.send(APP_NIC, NIC_GET_AES_MODE, "")
def setAESiv(self, iv= '\0'*16):
'''
set the AES IV. this will persist until the next reboot, but it should be noted that some modes
update the IV automatically with each operation, so care must be taken with the higher level
protocol to ensure lost packets etc. do not cause synchronisation problems. IV must be 128 bits.
'''
return self.send(APP_NIC, NIC_SET_AES_IV, iv)
def setAESkey(self, key= '\0'*16):
'''
set the AES key. this will persist until the next reboot. key must be 128 bits.
'''
return self.send(APP_NIC, NIC_SET_AES_KEY, key)
# set repeat & offset to optionally repeat tx of a section of the data block. repeat of 65535 means 'forever'
def RFxmit(self, data, repeat=0, offset=0):
# calculate wait time
waitlen = len(data)
waitlen += repeat * (len(data) - offset)
wait = USB_TX_WAIT * ((waitlen / RF_MAX_TX_BLOCK) + 1)
self.send(APP_NIC, NIC_XMIT, "%s" % struct.pack("<HHH",len(data),repeat,offset)+data, wait=wait)
# set blocksize to larger than 255 to receive large blocks or 0 to revert to normal
def RFrecv(self, timeout=USB_RX_WAIT, blocksize=None):
if not blocksize == None:
if blocksize > EP5OUT_BUFFER_SIZE:
raise(Exception("Blocksize too large. Maximum %d") % EP5OUT_BUFFER_SIZE)
self.send(APP_NIC, NIC_SET_RECV_LARGE, "%s" % struct.pack("<H",blocksize))
return self.recv(APP_NIC, NIC_RECV, timeout)
def RFlisten(self):
''' just sit and dump packets as they come in
kinda like discover() but without changing any of the communications settings '''
while not keystop():
try:
y, t = self.RFrecv()
print "(%5.3f) Received: %s" % (t, y.encode('hex'))
except ChipconUsbTimeoutException:
pass
except KeyboardInterrupt:
print "Please press <enter> to stop"
sys.stdin.read(1)
def RFcapture(self):
''' dump packets as they come in, but return a list of packets when you exit capture mode.
kinda like discover() but without changing any of the communications settings '''
capture = []
while not keystop():
try:
y, t = self.RFrecv()
print "(%5.3f) Received: %s" % (t, y.encode('hex'))
capture.append((y,t))
except ChipconUsbTimeoutException:
pass
except KeyboardInterrupt:
print "Please press <enter> to stop"
sys.stdin.read(1)
return capture
def FHSSxmit(self, data):
self.send(APP_NIC, FHSS_XMIT, "%c%s" % (len(data)+1, data))
def changeChannel(self, chan):
return self.send(APP_NIC, FHSS_CHANGE_CHANNEL, "%c" % (chan))
def getChannels(self, channels=[]):
return self.send(APP_NIC, FHSS_GET_CHANNELS, '')
def setChannels(self, channels=[]):
chans = ''.join(["%c" % chan for chan in channels])
length = struct.pack("<H", len(chans))
return self.send(APP_NIC, FHSS_SET_CHANNELS, length + chans)
def nextChannel(self):
return self.send(APP_NIC, FHSS_NEXT_CHANNEL, '' )
def startHopping(self):
return self.send(APP_NIC, FHSS_START_HOPPING, '')
def stopHopping(self):
return self.send(APP_NIC, FHSS_STOP_HOPPING, '')
def setMACperiod(self, ms, mhz=24):
val = calculateT2(ms, mhz)
T, tickidx, tipidx, PR = val
print "Setting MAC period to %f secs (%x %x %x)" % (val)
t2ctl = (ord(self.peek(X_T2CTL)) & 0xfc) | (tipidx)
clkcon = (ord(self.peek(X_CLKCON)) & 0xc7) | (tickidx<<3)
self.poke(X_T2PR, chr(PR))
self.poke(X_T2CTL, chr(t2ctl))
self.poke(X_CLKCON, chr(clkcon))
def setMACdata(self, data):
datastr = ''.join([chr(d) for x in data])
return self.send(APP_NIC, FHSS_SET_MAC_DATA, datastr)
def getMACdata(self):
datastr, timestamp = self.send(APP_NIC, FHSS_GET_MAC_DATA, '')
print (repr(datastr))
data = struct.unpack("<BIHHHHHHBBH", datastr)
return data
def reprMACdata(self):
data = self.getMACdata()
return """\
u8 mac_state %x
u32 MAC_threshold %x
u16 NumChannels %x
u16 NumChannelHops %x
u16 curChanIdx %x
u16 tLastStateChange %x
u16 tLastHop %x
u16 desperatelySeeking %x
u8 txMsgIdx %x
u8 txMsgIdxDone %x
u16 synched_chans %x
""" % data
"""
u8 mac_state;
// MAC parameters (FIXME: make this all cc1111fhssmac.c/h?)
u32 g_MAC_threshold; // when the T2 clock as overflowed this many times, change channel
u16 g_NumChannels; // in case of multiple paths through the available channels
u16 g_NumChannelHops; // total number of channels in pattern (>= g_MaxChannels)
u16 g_curChanIdx; // indicates current channel index of the hopping pattern
u16 g_tLastStateChange;
u16 g_tLastHop;
u16 g_desperatelySeeking;
u8 g_txMsgIdx;
"""
def getMACthreshold(self):
return self.send(APP_NIC, FHSS_SET_MAC_THRESHOLD, struct.pack("<I",value))
def setMACthreshold(self, value):
return self.send(APP_NIC, FHSS_SET_MAC_THRESHOLD, struct.pack("<I",value))
def setFHSSstate(self, state):
return self.send(APP_NIC, FHSS_SET_STATE, struct.pack("<I",state))
def getFHSSstate(self):
state = self.send(APP_NIC, FHSS_GET_STATE, '')
#print repr(state)
state = ord(state[0])
return FHSS_STATES[state], state
def mac_SyncCell(self, CellID=0x0000):
return self.send(APP_NIC, FHSS_START_SYNC, struct.pack("<H",CellID))
def setPktAddr(self, addr):
return self.poke(ADDR, chr(addr))
def getPktAddr(self):
return self.peek(ADDR)
def discover(self, lowball=1, debug=None, length=30, IdentSyncWord=False, SyncWordMatchList=None, Search=None, RegExpSearch=None):
'''
discover() sets lowball mode to the mode requested (length too), and begins to dump packets to the screen.
press <enter> to quit, and your radio config will be set back to its original configuration.
lowball - lowball level of choosing (see help on lowball)
debug - sets _debug to this setting if not None.
length - arbitrary length of bytes we want to see per pseudopacket. (should be enough to identify interesting packets, but not too long)
IdentSyncWord - look for preamble in each packet and determine possible sync-words in use
SyncWordMatchList - attempt to find *these* sync words (provide a list)
Search - byte string to search through each received packet for (real bytes, not hex repr)
RegExpSearch - regular expression to search through received bytes (not the hex repr that is printed)
'''
oldebug = self._debug
if IdentSyncWord and lowball <= 1:
print "Entering Discover mode and searching for possible SyncWords..."
if SyncWordMatchList is not None:
print " seeking one of: %s" % repr([hex(x) for x in SyncWordMatchList])
else:
if IdentSyncWord and lowball > 1:
print "-- lowball too high -- ignoring request to IdentSyncWord"
IdentSyncWord = False
print "Entering Discover mode..."
self.lowball(level=lowball, length=length)
if debug is not None:
self._debug = debug
if Search is not None:
print "Search:",repr(Search)
if RegExpSearch is not None:
print "RegExpSearch:",repr(RegExpSearch)
while not keystop():
try:
y, t = self.RFrecv()
yhex = y.encode('hex')
print "(%5.3f) Received: %s" % (t, yhex)
if RegExpSearch is not None:
ynext = y
for loop in range(8):
if (re.Search(RegExpSearch, ynext) is not None):
print " REG EXP SEARCH SUCCESS:",RegExpSearch
ynext = bits.shiftString(ynext, 1)
if Search is not None:
ynext = y
for loop in range(8):
if (Search in ynext):
print " SEARCH SUCCESS:",Search
ynext = bits.shiftString(ynext, 1)
if IdentSyncWord:
if lowball == 1:
y = '\xaa\xaa' + y
poss = bits.findDword(y)
if len(poss):
print " possible Sync Dwords: %s" % repr([hex(x) for x in poss])
if SyncWordMatchList is not None:
for x in poss:
if x in SyncWordMatchList:
print "MATCH WITH KNOWN SYNC WORD:" + hex(x)
except ChipconUsbTimeoutException:
pass
except KeyboardInterrupt:
print "Please press <enter> to stop"
sys.stdin.read(1)
self._debug = oldebug
self.lowballRestore()
print "Exiting Discover mode..."
def testTX(self, data="XYZABCDEFGHIJKL"):
while (sys.stdin not in select.select([sys.stdin],[],[],0)[0]):
time.sleep(.4)
print "transmitting %s" % repr(data)
self.RFxmit(data)
sys.stdin.read(1)
def unittest(dongle):
import cc1111client
cc1111client.unittest(dongle)
print "\nTesting FHSS State set/get"
fhssstate = dongle.getFHSSstate()
print repr(fhssstate)
for stateidx in range(FHSS_LAST_STATE+1):
print repr(dongle.setFHSSstate(stateidx))
print repr(dongle.getFHSSstate())
print repr(dongle.setFHSSstate(fhssstate[1] ))
print repr(dongle.getFHSSstate())
if __name__ == "__main__":
idx = 0
if len(sys.argv) > 1:
idx = int(sys.argv.pop())
d = FHSSNIC(idx=idx)

1516
rflib/chipcondefs.py Normal file

File diff suppressed because it is too large Load Diff

29
toorchat.py Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
import sys
from rflib import *
import rflib.chipcon_nic as rfnic
import atexit
from libtoorchat import *
def banner():
print "******** ToorChat [v 0.1] ********"
def main():
banner()
badge = RfCat(idx=0)
badge.setModeRX()
protocol = ToorChatProtocol(badge)
while True:
try:
msg, timestamp = badge.RFrecv()
print "enter a message"
# send = input("Enter a message")
# protocol.send_message(send)
except ChipconUsbTimeoutException:
pass
if __name__ == '__main__':
main()

286
vstruct/__init__.py Normal file
View File

@ -0,0 +1,286 @@
import struct
from StringIO import StringIO
import vstruct.primitives as vs_prims
def isVstructType(x):
return isinstance(x, vs_prims.v_base)
class VStruct(vs_prims.v_base):
def __init__(self, bigend=False):
# A tiny bit of evil...
object.__setattr__(self, "_vs_values", {})
vs_prims.v_base.__init__(self)
self._vs_name = self.__class__.__name__
self._vs_fields = []
self._vs_field_align = False # To toggle visual studio style packing
self._vs_padnum = 0
self._vs_fmtbase = '<'
if bigend:
self._vs_fmtbase = '>'
def vsGetClassPath(self):
'''
Return the entire class name (including module path).
'''
return '%s.%s' % (self.__module__, self._vs_name)
def vsParse(self, bytes, offset=0):
"""
For all the primitives contained within, allow them
an opportunity to parse the given data and return the
total offset...
"""
plist = self.vsGetPrims()
fmt = self.vsGetFormat()
size = struct.calcsize(fmt)
vals = struct.unpack(fmt, bytes[offset:offset+size])
for i in range(len(plist)):
plist[i].vsSetParsedValue(vals[i])
def vsEmit(self):
"""
Get back the byte sequence associated with this structure.
"""
fmt = self.vsGetFormat()
r = []
for p in self.vsGetPrims():
r.append(p.vsGetFmtValue())
return struct.pack(fmt, *r)
def vsGetFormat(self):
"""
Return the format specifier which would then be used
"""
# Unpack everything little endian, let vsParseValue deal...
ret = self._vs_fmtbase
for p in self.vsGetPrims():
ret += p.vsGetFormat()
return ret
def vsIsPrim(self):
return False
def vsGetFields(self):
ret = []
for fname in self._vs_fields:
fobj = self._vs_values.get(fname)
ret.append((fname,fobj))
return ret
def vsGetField(self, name):
x = self._vs_values.get(name)
if x == None:
raise Exception("Invalid field: %s" % name)
return x
def vsHasField(self, name):
return self._vs_values.get(name) != None
def vsSetField(self, name, value):
if isVstructType(value):
self._vs_values[name] = value
return
x = self._vs_values.get(name)
return x.vsSetValue(value)
# FIXME implement more arithmetic for structs...
def __ixor__(self, other):
for name,value in other._vs_values.items():
self._vs_values[name] ^= value
return self
def vsAddField(self, name, value):
if not isVstructType(value):
raise Exception("Added fields MUST be vstruct types!")
# Do optional field alignment...
if self._vs_field_align:
# If it's a primitive, all is well, if not, pad to size of
# the first element of the VStruct/VArray...
if value.vsIsPrim():
align = len(value)
else:
fname = value._vs_fields[0]
align = len(value._vs_values.get(fname))
delta = len(self) % align
if delta != 0:
print "PADDING %s by %d" % (name,align-delta)
pname = "_pad%d" % self._vs_padnum
self._vs_padnum += 1
self._vs_fields.append(pname)
self._vs_values[pname] = vs_prims.v_bytes(align-delta)
self._vs_fields.append(name)
self._vs_values[name] = value
def vsGetPrims(self):
"""
return an order'd list of the primitive fields in this
structure definition. This is recursive and will return
the sub fields of all nested structures.
"""
ret = []
for name, field in self.vsGetFields():
if field.vsIsPrim():
ret.append(field)
else:
ret.extend(field.vsGetPrims())
return ret
def vsGetTypeName(self):
return self._vs_name
def vsGetOffset(self, name):
"""
Return the offset of a member.
"""
offset = 0
for fname in self._vs_fields:
if name == fname:
return offset
x = self._vs_values.get(fname)
offset += len(x)
raise Exception("Invalid Field Specified!")
def vsGetPrintInfo(self, offset=0, indent=0, top=True):
ret = []
if top:
ret.append((offset, indent, self._vs_name, self))
indent += 1
for fname in self._vs_fields:
x = self._vs_values.get(fname)
off = offset + self.vsGetOffset(fname)
if isinstance(x, VStruct):
ret.append((off, indent, fname, x))
ret.extend(x.vsGetPrintInfo(offset=off, indent=indent, top=False))
else:
ret.append((off, indent, fname, x))
return ret
def __len__(self):
fmt = self.vsGetFormat()
return struct.calcsize(fmt)
def __getattr__(self, name):
# Gotta do this for pickle issues...
vsvals = self.__dict__.get("_vs_values")
if vsvals == None:
vsvals = {}
self.__dict__["_vs_values"] = vsvals
r = vsvals.get(name)
if r is None:
raise AttributeError(name)
if isinstance(r, vs_prims.v_prim):
return r.vsGetValue()
return r
def __setattr__(self, name, value):
# If we have this field, asign to it
x = self._vs_values.get(name, None)
if x != None:
return self.vsSetField(name, value)
# If it's a vstruct type, create a new field
if isVstructType(value):
return self.vsAddField(name, value)
# Fail over to standard object attribute behavior
return object.__setattr__(self, name, value)
def __iter__(self):
# Our iteration returns name,field pairs
ret = []
for name in self._vs_fields:
ret.append((name, self._vs_values.get(name)))
return iter(ret)
def __repr__(self):
return self._vs_name
def tree(self, va=0, reprmax=None):
ret = ""
for off, indent, name, field in self.vsGetPrintInfo():
rstr = field.vsGetTypeName()
if isinstance(field, vs_prims.v_number):
val = field.vsGetValue()
rstr = '0x%.8x (%d)' % (val,val)
elif isinstance(field, vs_prims.v_prim):
rstr = repr(field)
if reprmax != None and len(rstr) > reprmax:
rstr = rstr[:reprmax] + '...'
ret += "%.8x (%.2d)%s %s: %s\n" % (va+off, len(field), " "*(indent*2),name,rstr)
return ret
class VArray(VStruct):
def __init__(self, elems=()):
VStruct.__init__(self)
for e in elems:
self.vsAddElement(e)
def vsAddElement(self, elem):
"""
Used to add elements to an array
"""
idx = len(self._vs_fields)
self.vsAddField("%d" % idx, elem)
def __getitem__(self, index):
return self.vsGetField("%d" % index)
#FIXME slice asignment
def resolve(impmod, nameparts):
"""
Resolve the given (potentially nested) object
from within a module.
"""
if not nameparts:
return None
m = impmod
for nname in nameparts:
m = getattr(m, nname, None)
if m == None:
break
return m
# NOTE: Gotta import this *after* VStruct/VSArray defined
import vstruct.defs as vs_defs
def getStructure(sname):
"""
Return an instance of the specified structure. The
structure name may be a definition that was added with
addStructure() or a python path (ie. win32.TEB) of a
definition from within vstruct.defs.
"""
x = resolve(vs_defs, sname.split("."))
if x != None:
return x()
return None
def getModuleNames():
return [x for x in dir(vs_defs) if not x.startswith("__")]
def getStructNames(modname):
ret = []
mod = resolve(vs_defs, modname)
if mod == None:
return ret
for n in dir(mod):
x = getattr(mod, n)
if issubclass(x, VStruct):
ret.append(n)
return ret

249
vstruct/builder.py Normal file
View File

@ -0,0 +1,249 @@
'''
VStruct builder! Used to serialize structure definitions etc...
'''
import types
import inspect
import vstruct
import vstruct.primitives as vs_prim
prim_types = [ None,
vs_prim.v_uint8,
vs_prim.v_uint16,
None,
vs_prim.v_uint32,
None, None, None,
vs_prim.v_uint64
]
# VStruct Field Flags
VSFF_ARRAY = 1
VSFF_POINTER = 2
class VStructConstructor:
def __init__(self, builder, vsname):
self.builder = builder
self.vsname = vsname
def __call__(self, *args, **kwargs):
return self.builder.buildVStruct(self.vsname)
class VStructBuilder:
def __init__(self, defs=(), enums=()):
self._vs_defs = {}
self._vs_enums = {}
self._vs_namespaces = {}
for vsdef in defs:
self.addVStructDef(vsdef)
for enum in enums:
self.addVStructEnumeration(enum)
def __getattr__(self, name):
ns = self._vs_namespaces.get(name)
if ns != None:
return ns
vsdef = self._vs_defs.get(name)
if vsdef != None:
return VStructConstructor(self, name)
raise AttributeError, name
def addVStructEnumeration(self, enum):
self._vs_enums[enum[0]] = enum
def addVStructNamespace(self, name, builder):
self._vs_namespaces[name] = builder
def getVStructNamespaces(self):
return self._vs_namespaces.items()
def getVStructNamespaceNames(self):
return self._vs_namespaces.keys()
def hasVStructNamespace(self, namespace):
return self._vs_namespaces.get(namespace, None) != None
def getVStructNames(self, namespace=None):
if namespace == None:
return self._vs_defs.keys()
nsmod = self._vs_namespaces.get(namespace)
ret = []
for name in dir(nsmod):
nobj = getattr(nsmod, name)
if not inspect.isclass(nobj):
continue
if issubclass(nobj, vstruct.VStruct):
ret.append(name)
return ret
def addVStructDef(self, vsdef):
vsname = vsdef[0]
self._vs_defs[vsname] = vsdef
def buildVStruct(self, vsname):
# Check for a namespace
parts = vsname.split('.', 1)
if len(parts) == 2:
ns = self._vs_namespaces.get(parts[0])
if ns == None:
raise Exception('Namespace %s is not present! (need symbols?)' % parts[0])
# If a module gets added as a namespace, assume it has a class def...
if isinstance(ns, types.ModuleType):
cls = getattr(ns, parts[1])
if cls == None:
raise Exception('Unknown VStruct Definition: %s' % vsname)
return cls()
return ns.buildVStruct(parts[1])
vsdef = self._vs_defs.get(vsname)
if vsdef == None:
raise Exception('Unknown VStruct Definition: %s' % vsname)
vsname, vssize, vskids = vsdef
vs = vstruct.VStruct()
vs._vs_name = vsname
for fname, foffset, fsize, ftypename, fflags in vskids:
if fflags & VSFF_POINTER:
# FIXME support pointers with types!
if fsize == 4:
fieldval = vs_prim.v_ptr32()
elif fsize == 8:
fieldval = vs_prim.v_ptr64()
else:
raise Exception('Invalid Pointer Width: %d' % fsize)
elif fflags & VSFF_ARRAY:
if ftypename != None:
fieldval = vstruct.VArray()
while len(fieldval) < fsize:
fieldval.vsAddElement( self.buildVStruct(ftypename) )
else:
# FIXME actually handle arrays!
fieldval = vs_prim.v_bytes(size=fsize)
elif ftypename == None:
if fsize not in [1,2,4,8]:
#print 'Primitive Field Size: %d' % fsize
fieldval = v_bytes(size=fsize)
else:
fieldval = prim_types[fsize]()
else:
fieldval = self.buildVStruct(ftypename)
cursize = len(vs)
if foffset < cursize:
#print 'FIXME handle unions, overlaps, etc...'
continue
if foffset > cursize:
setattr(vs, '_pad%.4x' % foffset, vs_prim.v_bytes(size=(foffset-cursize)))
setattr(vs, fname, fieldval)
return vs
def genVStructPyCode(self):
ret = 'import vstruct\n'
ret += 'from vstruct.primitives import *'
ret += '\n\n'
for ename, esize, ekids in self._vs_enums.values():
ret += '%s = v_enum()\n' % ename
for kname, kval in ekids:
ret += '%s.%s = %d\n' % (ename,kname,kval)
ret += '\n\n'
for vsname, vsize, vskids in self._vs_defs.values():
ret += 'class %s(vstruct.VStruct):\n' % vsname
ret += ' def __init__(self):\n'
ret += ' vstruct.VStruct.__init__(self)\n'
offset = 0
for fname, foffset, fsize, ftypename, fflags in vskids:
if foffset < offset:
continue
if foffset > offset:
ret += ' self._pad%.4x = v_bytes(size=%d)\n' % (foffset, foffset-offset)
offset += (foffset - offset)
if fflags & VSFF_POINTER:
if fsize == 4:
fconst = 'v_ptr32()'
elif fsize == 8:
fconst = 'v_ptr64()'
else:
fconst = 'v_bytes(size=%d) # FIXME should be pointer!' % fsize
elif fflags & VSFF_ARRAY:
if ftypename != None:
'[ %s() for i in xrange( %d / len(%s())) ]' % (ftypename, fsize, ftypename)
else:
fconst = 'v_bytes(size=%d) # FIXME Unknown Array Type' % fsize
elif ftypename == None:
if fsize == 1:
fconst = 'v_uint8()'
elif fsize == 2:
fconst = 'v_uint16()'
elif fsize == 4:
fconst = 'v_uint32()'
elif fsize == 8:
fconst = 'v_uint64()'
else:
fconst = 'v_bytes(size=%d)' % fsize
else:
fconst = '%s()' % ftypename
ret += ' self.%s = %s\n' % (fname, fconst)
offset += fsize
ret += '\n\n'
return ret
if __name__ == '__main__':
# Parse windows structures from dll symbols...
import os
import sys
import platform
from pprint import pprint
import PE
import vtrace.platforms.win32 as vt_win32
p = PE.PE(file(sys.argv[1], 'rb'))
baseaddr = p.IMAGE_NT_HEADERS.OptionalHeader.ImageBase
osmajor = p.IMAGE_NT_HEADERS.OptionalHeader.MajorOperatingSystemVersion
osminor = p.IMAGE_NT_HEADERS.OptionalHeader.MinorOperatingSystemVersion
machine = p.IMAGE_NT_HEADERS.FileHeader.Machine
archname = PE.machine_names.get(machine)
parser = vt_win32.Win32SymbolParser(0xffffffff, sys.argv[1], baseaddr)
parser.parse()
t = parser._sym_types.values()
e = parser._sym_enums.values()
builder = VStructBuilder(defs=t, enums=e)
print '# Version: %d.%d' % (osmajor, osminor)
print '# Architecture: %s' % archname
print builder.genVStructPyCode()

6
vstruct/defs/__init__.py Normal file
View File

@ -0,0 +1,6 @@
# Import all local structure modules
import elf
import pe
import win32

162
vstruct/defs/elf.py Normal file
View File

@ -0,0 +1,162 @@
import vstruct
from vstruct.primitives import *
EI_NIDENT = 4
EI_PADLEN = 7
class Elf32(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.e_ident = v_bytes(EI_NIDENT)
self.e_class = v_uint8()
self.e_data = v_uint8()
self.e_fileversion = v_uint8()
self.e_osabi = v_uint8()
self.e_abiversio = v_uint8()
self.e_pad = v_bytes(EI_PADLEN)
self.e_type = v_uint16()
self.e_machine = v_uint16()
self.e_version = v_uint32()
self.e_entry = v_uint32()
self.e_phoff = v_uint32()
self.e_shoff = v_uint32()
self.e_flags = v_uint32()
self.e_ehsize = v_uint16()
self.e_phentsize = v_uint16()
self.e_phnum = v_uint16()
self.e_shentsize = v_uint16()
self.e_shnum = v_uint16()
self.e_shstrndx = v_uint16()
class Elf32Section(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.sh_name = v_uint32()
self.sh_type = v_uint32()
self.sh_flags = v_uint32()
self.sh_addr = v_uint32()
self.sh_offset = v_uint32()
self.sh_size = v_uint32()
self.sh_link = v_uint32()
self.sh_info = v_uint32()
self.sh_addralign = v_uint32()
self.sh_entsize = v_uint32()
class Elf32Pheader(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.p_type = v_uint32()
self.p_offset = v_uint32()
self.p_vaddr = v_uint32()
self.p_paddr = v_uint32()
self.p_filesz = v_uint32()
self.p_memsz = v_uint32()
self.p_flags = v_uint32()
self.p_align = v_uint32()
class Elf32Reloc(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.r_offset = v_ptr32()
self.r_info = v_uint32()
class Elf32Reloca(Elf32Reloc):
def __init__(self):
Elf32Reloc.__init__(self)
self.r_addend = v_uint32()
class Elf32Symbol(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.st_name = v_uint32()
self.st_value = v_uint32()
self.st_size = v_uint32()
self.st_info = v_uint8()
self.st_other = v_uint8()
self.st_shndx = v_uint16()
class Elf32Dynamic(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.d_tag = v_uint32()
self.d_value = v_uint32()
class Elf64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.e_ident = v_bytes(EI_NIDENT)
self.e_class = v_uint8()
self.e_data = v_uint8()
self.e_fileversion = v_uint8()
self.e_osabi = v_uint8()
self.e_abiversio = v_uint8()
self.e_pad = v_bytes(EI_PADLEN)
self.e_type = v_uint16()
self.e_machine = v_uint16()
self.e_version = v_uint32()
self.e_entry = v_uint64()
self.e_phoff = v_uint64()
self.e_shoff = v_uint64()
self.e_flags = v_uint32()
self.e_ehsize = v_uint16()
self.e_phentsize = v_uint16()
self.e_phnum = v_uint16()
self.e_shentsize = v_uint16()
self.e_shnum = v_uint16()
self.e_shstrndx = v_uint16()
class Elf64Section(Elf32Section):
def __init__(self):
vstruct.VStruct.__init__(self)
self.sh_name = v_uint32()
self.sh_type = v_uint32()
self.sh_flags = v_uint64()
self.sh_addr = v_uint64()
self.sh_offset = v_uint64()
self.sh_size = v_uint64()
self.sh_link = v_uint32()
self.sh_info = v_uint32()
self.sh_addralign = v_uint64()
self.sh_entsize = v_uint64()
class Elf64Pheader(Elf32Pheader):
def __init__(self):
vstruct.VStruct.__init__(self)
self.p_type = v_uint32()
self.p_flags = v_uint32()
self.p_offset = v_uint64()
self.p_vaddr = v_uint64()
self.p_paddr = v_uint64()
self.p_filesz = v_uint64()
self.p_memsz = v_uint64()
self.p_align = v_uint64()
class Elf64Reloc(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.r_offset = v_ptr64()
self.r_info = v_uint64()
class Elf64Reloca(Elf64Reloc):
def __init__(self):
#Elf64Reloc.__init__(self)
vstruct.VStruct.__init__(self)
self.r_offset = v_uint64()
self.r_info = v_uint64()
self.r_addend = v_uint64()
class Elf64Symbol(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.st_name = v_uint32()
self.st_info = v_uint8()
self.st_other = v_uint8()
self.st_shndx = v_uint16()
self.st_value = v_uint64()
self.st_size = v_uint64()
class Elf64Dynamic(Elf32Dynamic):
pass

209
vstruct/defs/kdcom.py Normal file
View File

@ -0,0 +1,209 @@
"""
Initial module with supporting structures for windows
kernel serial debugging.
"""
import vstruct
from vstruct.primitives import *
# Main packet magic bytes and such
BREAKIN_PACKET = 0x62626262
BREAKIN_PACKET_BYTE = 0x62
PACKET_LEADER = 0x30303030
PACKET_LEADER_BYTE = 0x30
CONTROL_PACKET_LEADER = 0x69696969
CONTROL_PACKET_LEADER_BYTE = 0x69
PACKET_TRAILING_BYTE = 0xAA
pkt_magic_names = {
BREAKIN_PACKET:"Break Packet",
PACKET_LEADER:"Packet",
CONTROL_PACKET_LEADER:"Control Packet",
}
# Primary "packet types"
PACKET_TYPE_UNUSED = 0
PACKET_TYPE_KD_STATE_CHANGE32 = 1
PACKET_TYPE_KD_STATE_MANIPULATE = 2
PACKET_TYPE_KD_DEBUG_IO = 3
PACKET_TYPE_KD_ACKNOWLEDGE = 4
PACKET_TYPE_KD_RESEND = 5
PACKET_TYPE_KD_RESET = 6
PACKET_TYPE_KD_STATE_CHANGE64 = 7
PACKET_TYPE_KD_POLL_BREAKIN = 8
PACKET_TYPE_KD_TRACE_IO = 9
PACKET_TYPE_KD_CONTROL_REQUEST = 10
PACKET_TYPE_KD_FILE_IO = 11
PACKET_TYPE_MAX = 12
pkt_type_names = {
PACKET_TYPE_UNUSED:"Unused",
PACKET_TYPE_KD_STATE_CHANGE32:"State Change32",
PACKET_TYPE_KD_STATE_MANIPULATE:"Manipulate",
PACKET_TYPE_KD_DEBUG_IO:"Debug IO",
PACKET_TYPE_KD_ACKNOWLEDGE:"Ack",
PACKET_TYPE_KD_RESEND:"Resend",
PACKET_TYPE_KD_RESET:"Reset",
PACKET_TYPE_KD_STATE_CHANGE64:"State Change64",
PACKET_TYPE_KD_POLL_BREAKIN:"Breakin",
PACKET_TYPE_KD_TRACE_IO:"Trace IO",
PACKET_TYPE_KD_CONTROL_REQUEST:"Control Request",
PACKET_TYPE_KD_FILE_IO:"File IO",
PACKET_TYPE_MAX:"Max",
}
# Wait State Change Types
DbgKdMinimumStateChange = 0x00003030
DbgKdExceptionStateChange = 0x00003030
DbgKdLoadSymbolsStateChange = 0x00003031
DbgKdCommandStringStateChange = 0x00003032
DbgKdMaximumStateChange = 0x00003033
pkt_sub_wait_state_change = {
DbgKdMinimumStateChange:"DbgKdMinimumStateChange",
DbgKdExceptionStateChange:"DbgKdExceptionStateChange",
DbgKdLoadSymbolsStateChange:"DbgKdLoadSymbolsStateChange",
DbgKdCommandStringStateChange:"DbgKdCommandStringStateChange",
DbgKdMaximumStateChange:"DbgKdMaximumStateChange",
}
# Manipulate Types
DbgKdMinimumManipulate = 0x00003130
DbgKdReadVirtualMemoryApi = 0x00003130
DbgKdWriteVirtualMemoryApi = 0x00003131
DbgKdGetContextApi = 0x00003132
DbgKdSetContextApi = 0x00003133
DbgKdWriteBreakPointApi = 0x00003134
DbgKdRestoreBreakPointApi = 0x00003135
DbgKdContinueApi = 0x00003136
DbgKdReadControlSpaceApi = 0x00003137
DbgKdWriteControlSpaceApi = 0x00003138
DbgKdReadIoSpaceApi = 0x00003139
DbgKdWriteIoSpaceApi = 0x0000313A
DbgKdRebootApi = 0x0000313B
DbgKdContinueApi2 = 0x0000313C
DbgKdReadPhysicalMemoryApi = 0x0000313D
DbgKdWritePhysicalMemoryApi = 0x0000313E
DbgKdQuerySpecialCallsApi = 0x0000313F
DbgKdSetSpecialCallApi = 0x00003140
DbgKdClearSpecialCallsApi = 0x00003141
DbgKdSetInternalBreakPointApi = 0x00003142
DbgKdGetInternalBreakPointApi = 0x00003143
DbgKdReadIoSpaceExtendedApi = 0x00003144
DbgKdWriteIoSpaceExtendedApi = 0x00003145
DbgKdGetVersionApi = 0x00003146
DbgKdWriteBreakPointExApi = 0x00003147
DbgKdRestoreBreakPointExApi = 0x00003148
DbgKdCauseBugCheckApi = 0x00003149
DbgKdSwitchProcessor = 0x00003150
DbgKdPageInApi = 0x00003151
DbgKdReadMachineSpecificRegister = 0x00003152
DbgKdWriteMachineSpecificRegister = 0x00003153
OldVlm1 = 0x00003154
OldVlm2 = 0x00003155
DbgKdSearchMemoryApi = 0x00003156
DbgKdGetBusDataApi = 0x00003157
DbgKdSetBusDataApi = 0x00003158
DbgKdCheckLowMemoryApi = 0x00003159
DbgKdClearAllInternalBreakpointsApi = 0x0000315A
DbgKdFillMemoryApi = 0x0000315B
DbgKdQueryMemoryApi = 0x0000315C
DbgKdSwitchPartition = 0x0000315D
DbgKdMaximumManipulate = 0x0000315E
pkt_sub_manipulate = {
DbgKdMinimumManipulate:"DbgKdMinimumManipulate",
DbgKdReadVirtualMemoryApi:"DbgKdReadVirtualMemoryApi",
DbgKdWriteVirtualMemoryApi:"DbgKdWriteVirtualMemoryApi",
DbgKdGetContextApi:"DbgKdGetContextApi",
DbgKdSetContextApi:"DbgKdSetContextApi",
DbgKdWriteBreakPointApi:"DbgKdWriteBreakPointApi",
DbgKdRestoreBreakPointApi:"DbgKdRestoreBreakPointApi",
DbgKdContinueApi:"DbgKdContinueApi",
DbgKdReadControlSpaceApi:"DbgKdReadControlSpaceApi",
DbgKdWriteControlSpaceApi:"DbgKdWriteControlSpaceApi",
DbgKdReadIoSpaceApi:"DbgKdReadIoSpaceApi",
DbgKdWriteIoSpaceApi:"DbgKdWriteIoSpaceApi",
DbgKdRebootApi:"DbgKdRebootApi",
DbgKdContinueApi2:"DbgKdContinueApi2",
DbgKdReadPhysicalMemoryApi:"DbgKdReadPhysicalMemoryApi",
DbgKdWritePhysicalMemoryApi:"DbgKdWritePhysicalMemoryApi",
DbgKdQuerySpecialCallsApi:"DbgKdQuerySpecialCallsApi",
DbgKdSetSpecialCallApi:"DbgKdSetSpecialCallApi",
DbgKdClearSpecialCallsApi:"DbgKdClearSpecialCallsApi",
DbgKdSetInternalBreakPointApi:"DbgKdSetInternalBreakPointApi",
DbgKdGetInternalBreakPointApi:"DbgKdGetInternalBreakPointApi",
DbgKdReadIoSpaceExtendedApi:"DbgKdReadIoSpaceExtendedApi",
DbgKdWriteIoSpaceExtendedApi:"DbgKdWriteIoSpaceExtendedApi",
DbgKdGetVersionApi:"DbgKdGetVersionApi",
DbgKdWriteBreakPointExApi:"DbgKdWriteBreakPointExApi",
DbgKdRestoreBreakPointExApi:"DbgKdRestoreBreakPointExApi",
DbgKdCauseBugCheckApi:"DbgKdCauseBugCheckApi",
DbgKdSwitchProcessor:"DbgKdSwitchProcessor",
DbgKdPageInApi:"DbgKdPageInApi",
DbgKdReadMachineSpecificRegister:"DbgKdReadMachineSpecificRegister",
DbgKdWriteMachineSpecificRegister:"DbgKdWriteMachineSpecificRegister",
OldVlm1:"OldVlm1",
OldVlm2:"OldVlm2",
DbgKdSearchMemoryApi:"DbgKdSearchMemoryApi",
DbgKdGetBusDataApi:"DbgKdGetBusDataApi",
DbgKdSetBusDataApi:"DbgKdSetBusDataApi",
DbgKdCheckLowMemoryApi:"DbgKdCheckLowMemoryApi",
DbgKdClearAllInternalBreakpointsApi:"DbgKdClearAllInternalBreakpointsApi",
DbgKdFillMemoryApi:"DbgKdFillMemoryApi",
DbgKdQueryMemoryApi:"DbgKdQueryMemoryApi",
DbgKdSwitchPartition:"DbgKdSwitchPartition",
DbgKdMaximumManipulate:"DbgKdMaximumManipulate",
}
# Debug I/O Types
DbgKdPrintStringApi = 0x00003230
DbgKdGetStringApi = 0x00003231
# Control Report Flags
REPORT_INCLUDES_SEGS = 0x0001
REPORT_INCLUDES_CS = 0x0002
# Protocol Versions
DBGKD_64BIT_PROTOCOL_VERSION1 = 5
DBGKD_64BIT_PROTOCOL_VERSION2 = 6
# Query Memory Address Spaces
DBGKD_QUERY_MEMORY_VIRTUAL = 0
DBGKD_QUERY_MEMORY_PROCESS = 0
DBGKD_QUERY_MEMORY_SESSION = 1
DBGKD_QUERY_MEMORY_KERNEL = 2
# Query Memory Flags
DBGKD_QUERY_MEMORY_READ = 0x01
DBGKD_QUERY_MEMORY_WRITE = 0x02
DBGKD_QUERY_MEMORY_EXECUTE = 0x04
DBGKD_QUERY_MEMORY_FIXED = 0x08
ULONG = v_uint32
ULONG64 = v_uint64
BOOLEAN = v_uint32
class DBGKD_LOAD_SYMBOLS64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self._vs_field_align = True
self.PathNameLength = v_uint32()
self.BaseOfDll = v_uint64()
self.ProcessId = v_uint64()
self.CheckSum = v_uint32()
self.SizeOfImage = v_uint32()
#self.UnloadSymbols = v_uint8()
self.UnloadSymbols = v_uint32() # HACK must be 32 bit aligned
class DBGKD_WAIT_STATE_CHANGE64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self._vs_field_align = True
self.NewState = v_uint32()
self.ProcessorLevel = v_uint16()
self.Processor = v_uint16()
self.NumberProcessors = v_uint32()
self.Thread = v_uint64()
self.ProgramCounter = v_uint64()

View File

@ -0,0 +1,12 @@
'''
Structure definitions for the OSX MachO binary format.
'''
import vstruct
import vstruct.primitives as vs_prim
from vstruct.defs.macho.const import *
from vstruct.defs.macho.fat import *
from vstruct.defs.macho.loader import *

128
vstruct/defs/macho/const.py Normal file
View File

@ -0,0 +1,128 @@
# Fat Defines...
FAT_MAGIC = 0xcafebabe
FAT_CIGAM = 0xbebafec #NXSwapLong(FAT_MAGIC)
MH_MAGIC = 0xfeedface # the mach magic number
MH_CIGAM = 0xcefaedfe # NXSwapInt(MH_MAGIC)
MH_MAGIC_64 = 0xfeedfacf # the 64-bit mach magic number
MH_CIGAM_64 = 0xcffaedfe # NXSwapInt(MH_MAGIC_64)
MH_OBJECT = 0x1 # relocatable object file
MH_EXECUTE = 0x2 # demand paged executable file
MH_FVMLIB = 0x3 # fixed VM shared library file
MH_CORE = 0x4 # core file
MH_PRELOAD = 0x5 # preloaded executable file
MH_DYLIB = 0x6 # dynamically bound shared library
MH_DYLINKER = 0x7 # dynamic link editor
MH_BUNDLE = 0x8 # dynamically bound bundle file
MH_DYLIB_STUB = 0x9 # shared library stub for static
MH_DSYM = 0xa # companion file with only debug
MH_NOUNDEFS = 0x1 # the object file has no undefinedreferences
MH_INCRLINK = 0x2 # the object file is the output of anincremental link against a base fileand can't be link edited again
MH_DYLDLINK = 0x4 # the object file is input for thedynamic linker and can't be staticlylink edited again
MH_BINDATLOAD = 0x8 # the object file's undefinedreferences are bound by the dynamiclinker when loaded.
MH_PREBOUND = 0x10 # the file has its dynamic undefinedreferences prebound.
MH_SPLIT_SEGS = 0x20 # the file has its read-only andread-write segments split
MH_LAZY_INIT = 0x40 # the shared library init routine isto be run lazily via catching memoryfaults to its writeable segments(obsolete)
MH_TWOLEVEL = 0x80 # the image is using two-level namespace bindings
MH_FORCE_FLAT = 0x100 # the executable is forcing all imagesto use flat name space bindings
MH_NOMULTIDEFS = 0x200 # this umbrella guarantees no multipledefintions of symbols in itssub-images so the two-level namespacehints can always be used.
MH_NOFIXPREBINDING = 0x400 # do not have dyld notify theprebinding agent about thisexecutable
MH_PREBINDABLE = 0x800 # the binary is not prebound but canhave its prebinding redone. only usedwhen MH_PREBOUND is not set.
MH_ALLMODSBOUND = 0x1000 # this binary binds toall two-level namespace modules ofits dependent libraries. only usedwhen MH_PREBINDABLE and MH_TWOLEVELare both set.
MH_CANONICAL = 0x4000 # the binary has been canonicalizedvia the unprebind operation
MH_WEAK_DEFINES = 0x8000 # the final linked image containsexternal weak symbols
MH_BINDS_TO_WEAK = 0x10000 # the final linked image usesweak symbols
MH_ROOT_SAFE = 0x40000 # When this bit is set, the binarydeclares it is safe for use inprocesses with uid zero
MH_SETUID_SAFE = 0x80000 # When this bit is set, the binarydeclares it is safe for use inprocesses when issetugid() is true
MH_NO_REEXPORTED_DYLIBS = 0x100000 # When this bit is set on a dylib,the static linker does not need toexamine dependent dylibs to seeif any are re-exported
MH_PIE = 0x200000 # When this bit is set, the OS willload the main executable at arandom address. Only used inMH_EXECUTE filetypes.
# Constants for the cmd field of all load commands, the type
LC_REQ_DYLD = 0x80000000 # When this bit is set, the OS willload the main executable at arandom address. Only used inMH_EXECUTE filetypes.
LC_SEGMENT = 0x1 # segment of this file to be mapped
LC_SYMTAB = 0x2 # link-edit stab symbol table info
LC_SYMSEG = 0x3 # link-edit gdb symbol table info (obsolete)
LC_THREAD = 0x4 # thread
LC_UNIXTHREAD = 0x5 # unix thread (includes a stack)
LC_LOADFVMLIB = 0x6 # load a specified fixed VM shared library
LC_IDFVMLIB = 0x7 # fixed VM shared library identification
LC_IDENT = 0x8 # object identification info (obsolete)
LC_FVMFILE = 0x9 # fixed VM file inclusion (internal use)
LC_PREPAGE = 0xa # prepage command (internal use)
LC_DYSYMTAB = 0xb # dynamic link-edit symbol table info
LC_LOAD_DYLIB = 0xc # load a dynamically linked shared library
LC_ID_DYLIB = 0xd # dynamically linked shared lib ident
LC_LOAD_DYLINKER = 0xe # load a dynamic linker
LC_ID_DYLINKER = 0xf # dynamic linker identification
LC_PREBOUND_DYLIB = 0x10 # modules prebound for a dynamically
LC_ROUTINES = 0x11 # image routines
LC_SUB_FRAMEWORK = 0x12 # sub framework
LC_SUB_UMBRELLA = 0x13 # sub umbrella
LC_SUB_CLIENT = 0x14 # sub client
LC_SUB_LIBRARY = 0x15 # sub library
LC_TWOLEVEL_HINTS = 0x16 # two-level namespace lookup hints
LC_PREBIND_CKSUM = 0x17 # prebind checksum
LC_SEGMENT_64 = 0x19 # 64-bit segment of this file to bemapped
LC_ROUTINES_64 = 0x1a # 64-bit image routines
LC_UUID = 0x1b # the uuid
LC_CODE_SIGNATURE = 0x1d # local of code signature
LC_SEGMENT_SPLIT_INFO = 0x1e # local of info to split segments
LC_LAZY_LOAD_DYLIB = 0x20 # delay load of dylib until first use
LC_ENCRYPTION_INFO = 0x21 # encrypted segment information
SG_HIGHVM = 0x1 # the file contents for this segment is forthe high part of the VM space, the low partis zero filled (for stacks in core files)
SG_FVMLIB = 0x2 # this segment is the VM that is allocated bya fixed VM library, for overlap checking inthe link editor
SG_NORELOC = 0x4 # this segment has nothing that was relocatedin it and nothing relocated to it, that isit maybe safely replaced without relocation
SG_PROTECTED_VERSION_1 = 0x8 # This segment is protected. If thesegment starts at file offset 0, thefirst page of the segment is notprotected. All other pages of thesegment are protected.
SECTION_TYPE = 0x000000ff # 256 section types
SECTION_ATTRIBUTES = 0xffffff00 # 24 section attributes
S_REGULAR = 0x0 # regular section
S_ZEROFILL = 0x1 # zero fill on demand section
S_CSTRING_LITERALS = 0x2 # section with only literal C strings
S_4BYTE_LITERALS = 0x3 # section with only 4 byte literals
S_8BYTE_LITERALS = 0x4 # section with only 8 byte literals
S_LITERAL_POINTERS = 0x5 # section with only pointers to
S_NON_LAZY_SYMBOL_POINTERS = 0x6 # section with only non-lazysymbol pointers
S_LAZY_SYMBOL_POINTERS = 0x7 # section with only lazy symbolpointers
S_SYMBOL_STUBS = 0x8 # section with only symbolstubs, byte size of stub inthe reserved2 field
S_MOD_INIT_FUNC_POINTERS = 0x9 # section with only functionpointers for initialization
S_MOD_TERM_FUNC_POINTERS = 0xa # section with only functionpointers for termination
S_COALESCED = 0xb # section contains symbols thatare to be coalesced
S_GB_ZEROFILL = 0xc # zero fill on demand section(that can be larger than 4gigabytes)
S_INTERPOSING = 0xd # section with only pairs offunction pointers forinterposing
S_16BYTE_LITERALS = 0xe # section with only 16 byteliterals
S_DTRACE_DOF = 0xf # section containsDTrace Object Format
S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10 # section with only lazysymbol pointers to lazyloaded dylibs
SECTION_ATTRIBUTES_USR = 0xff000000 # User setable attributes
S_ATTR_PURE_INSTRUCTIONS = 0x80000000 # section contains only truemachine instructions
S_ATTR_NO_TOC = 0x40000000 # section contains coalescedsymbols that are not to bein a ranlib table ofcontents
S_ATTR_STRIP_STATIC_SYMS = 0x20000000 # ok to strip static symbolsin this section in fileswith the MH_DYLDLINK flag
S_ATTR_NO_DEAD_STRIP = 0x10000000 # no dead stripping
S_ATTR_LIVE_SUPPORT = 0x08000000 # blocks are live if theyreference live blocks
S_ATTR_SELF_MODIFYING_CODE = 0x04000000 # Used with i386 code stubswritten on by dyld
S_ATTR_DEBUG = 0x02000000 # a debug section
SECTION_ATTRIBUTES_SYS = 0x00ffff00 # system setable attributes
S_ATTR_SOME_INSTRUCTIONS = 0x00000400 # section contains somemachine instructions
S_ATTR_EXT_RELOC = 0x00000200 # section has externalrelocation entries
S_ATTR_LOC_RELOC = 0x00000100 # section has localrelocation entries
INDIRECT_SYMBOL_LOCAL = 0x80000000 # section has localrelocation entries
INDIRECT_SYMBOL_ABS = 0x40000000 # section has localrelocation entries
CPU_TYPE_ANY = -1
CPU_TYPE_VAX = 1
CPU_TYPE_MC680 = 6
CPU_TYPE_X86 = 7
CPU_TYPE_X86_64 = 0x01000007
#CPU_TYPE_MIPS ((cpu_type_t) 8) */
#CPU_TYPE_MC98000 ((cpu_type_t) 10)
#CPU_TYPE_HPPA ((cpu_type_t) 11)
#CPU_TYPE_ARM ((cpu_type_t) 12)
#CPU_TYPE_MC88000 ((cpu_type_t) 13)
#CPU_TYPE_SPARC ((cpu_type_t) 14)
#CPU_TYPE_I860 ((cpu_type_t) 15)
#CPU_TYPE_ALPHA ((cpu_type_t) 16) */
#CPU_TYPE_POWERPC ((cpu_type_t) 18)
#CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)

19
vstruct/defs/macho/fat.py Normal file
View File

@ -0,0 +1,19 @@
import vstruct
import vstruct.primitives as vs_prim
class fat_header(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self, bigend=True)
self.magic = vs_prim.v_uint32()
self.nfat_arch = vs_prim.v_uint32()
class fat_arch(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self, bigend=True)
self.cputype = vs_prim.v_uint32() # cpu specifier (int) */
self.cpusubtype = vs_prim.v_uint32() # machine specifier (int) */
self.offset = vs_prim.v_uint32() # file offset to this object file */
self.size = vs_prim.v_uint32() # size of this object file */
self.align = vs_prim.v_uint32() # alignment as a power of 2 */

View File

@ -0,0 +1,425 @@
import vstruct
import vstruct.primitives as vs_prim
vm_prot_t = vs_prim.v_uint32
cpu_type_t = vs_prim.v_uint32
cpu_subtype_t = vs_prim.v_uint32
lc_str = vs_prim.v_uint32
class mach_header(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.magic = vs_prim.v_uint32() # mach magic number identifier
self.cputype = cpu_type_t() # cpu specifier
self.cpusubtype = cpu_subtype_t() # machine specifier
self.filetype = vs_prim.v_uint32() # type of file
self.ncmds = vs_prim.v_uint32() # number of load commands
self.sizeofcmds = vs_prim.v_uint32() # the size of all the load commands
self.flags = vs_prim.v_uint32() # flags
class mach_header_64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.magic = vs_prim.v_uint32() # mach magic number identifier
self.cputype = cpu_type_t() # cpu specifier
self.cpusubtype = cpu_subtype_t() # machine specifier
self.filetype = vs_prim.v_uint32() # type of file
self.ncmds = vs_prim.v_uint32() # number of load commands
self.sizeofcmds = vs_prim.v_uint32() # the size of all the load commands
self.flags = vs_prim.v_uint32() # flags
self.reserved = vs_prim.v_uint32() # reserved
class load_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # type of load command
self.cmdsize = vs_prim.v_uint32() # total size of command in bytes
class segment_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SEGMENT
self.cmdsize = vs_prim.v_uint32() # includes sizeof section structs
self.segname[16] = vs_prim.v_uint8() # segment name
self.vmaddr = vs_prim.v_uint32() # memory address of this segment
self.vmsize = vs_prim.v_uint32() # memory size of this segment
self.fileoff = vs_prim.v_uint32() # file offset of this segment
self.filesize = vs_prim.v_uint32() # amount to map from the file
self.maxprot = vm_prot_t() # maximum VM protection
self.initprot = vm_prot_t() # initial VM protection
self.nsects = vs_prim.v_uint32() # number of sections in segment
self.flags = vs_prim.v_uint32() # flags
class segment_command_64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SEGMENT_64
self.cmdsize = vs_prim.v_uint32() # includes sizeof section_64 structs
self.segname[16] = vs_prim.v_uint8() # segment name
self.vmaddr = vs_prim.v_uint64() # memory address of this segment
self.vmsize = vs_prim.v_uint64() # memory size of this segment
self.fileoff = vs_prim.v_uint64() # file offset of this segment
self.filesize = vs_prim.v_uint64() # amount to map from the file
self.maxprot = vm_prot_t() # maximum VM protection
self.initprot = vm_prot_t() # initial VM protection
self.nsects = vs_prim.v_uint32() # number of sections in segment
self.flags = vs_prim.v_uint32() # flags
class section(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.sectname[16] = vs_prim.v_uint8() # name of this section
self.segname[16] = vs_prim.v_uint8() # segment this section goes in
self.addr = vs_prim.v_uint32() # memory address of this section
self.size = vs_prim.v_uint32() # size in bytes of this section
self.offset = vs_prim.v_uint32() # file offset of this section
self.align = vs_prim.v_uint32() # section alignment (power of 2)
self.reloff = vs_prim.v_uint32() # file offset of relocation entries
self.nreloc = vs_prim.v_uint32() # number of relocation entries
self.flags = vs_prim.v_uint32() # flags (section type and attributes)
self.reserved1 = vs_prim.v_uint32() # reserved (for offset or index)
self.reserved2 = vs_prim.v_uint32() # reserved (for count or sizeof)
class section_64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.sectname[16] = vs_prim.v_uint8() # name of this section
self.segname[16] = vs_prim.v_uint8() # segment this section goes in
self.addr = vs_prim.v_uint64() # memory address of this section
self.size = vs_prim.v_uint64() # size in bytes of this section
self.offset = vs_prim.v_uint32() # file offset of this section
self.align = vs_prim.v_uint32() # section alignment (power of 2)
self.reloff = vs_prim.v_uint32() # file offset of relocation entries
self.nreloc = vs_prim.v_uint32() # number of relocation entries
self.flags = vs_prim.v_uint32() # flags (section type and attributes)
self.reserved1 = vs_prim.v_uint32() # reserved (for offset or index)
self.reserved2 = vs_prim.v_uint32() # reserved (for count or sizeof)
self.reserved3 = vs_prim.v_uint32() # reserved
class fvmlib(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.name = lc_str() # library's target pathname
self.minor_version = vs_prim.v_uint32() # library's minor version number
self.header_addr = vs_prim.v_uint32() # library's header address
class fvmlib_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_IDFVMLIB or LC_LOADFVMLIB
self.cmdsize = vs_prim.v_uint32() # includes pathname string
self.fvmlib = fvmlib() # the library identification
class dylib(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.name = lc_str() # library's path name
self.timestamp = vs_prim.v_uint32() # library's build time stamp
self.current_version = vs_prim.v_uint32() # library's current version number
self.compatibility_version = vs_prim.v_uint32() # library's compatibility vers number
class dylib_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, LC_REEXPORT_DYLIB
self.cmdsize = vs_prim.v_uint32() # includes pathname string
self.dylib = dylib() # the library identification
class sub_framework_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SUB_FRAMEWORK
self.cmdsize = vs_prim.v_uint32() # includes umbrella string
self.umbrella = lc_str() # the umbrella framework name
class sub_client_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SUB_CLIENT
self.cmdsize = vs_prim.v_uint32() # includes client string
self.client = lc_str() # the client name
class sub_umbrella_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SUB_UMBRELLA
self.cmdsize = vs_prim.v_uint32() # includes sub_umbrella string
self.sub_umbrella = lc_str() # the sub_umbrella framework name
class sub_library_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SUB_LIBRARY
self.cmdsize = vs_prim.v_uint32() # includes sub_library string
self.sub_library = lc_str() # the sub_library name
class prebound_dylib_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_PREBOUND_DYLIB
self.cmdsize = vs_prim.v_uint32() # includes strings
self.name = lc_str() # library's path name
self.nmodules = vs_prim.v_uint32() # number of modules in library
self.linked_modules = lc_str() # bit vector of linked modules
class dylinker_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_ID_DYLINKER or LC_LOAD_DYLINKER
self.cmdsize = vs_prim.v_uint32() # includes pathname string
self.name = lc_str() # dynamic linker's path name
class thread_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_THREAD or LC_UNIXTHREAD
self.cmdsize = vs_prim.v_uint32() # total size of this command
class routines_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_ROUTINES
self.cmdsize = vs_prim.v_uint32() # total size of this command
self.init_address = vs_prim.v_uint32() # address of initialization routine
self.init_module = vs_prim.v_uint32() # index into the module table that
self.reserved1 = vs_prim.vs_prim.v_uint32()
self.reserved2 = vs_prim.vs_prim.v_uint32()
self.reserved3 = vs_prim.vs_prim.v_uint32()
self.reserved4 = vs_prim.vs_prim.v_uint32()
self.reserved5 = vs_prim.vs_prim.v_uint32()
self.reserved6 = vs_prim.vs_prim.v_uint32()
class routines_command_64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_ROUTINES_64
self.cmdsize = vs_prim.v_uint32() # total size of this command
self.init_address = vs_prim.v_uint64() # address of initialization routine
self.init_module = vs_prim.v_uint64() # index into the module table that
self.reserved1 = vs_prim.vs_prim.v_uint64()
self.reserved2 = vs_prim.vs_prim.v_uint64()
self.reserved3 = vs_prim.vs_prim.v_uint64()
self.reserved4 = vs_prim.vs_prim.v_uint64()
self.reserved5 = vs_prim.vs_prim.v_uint64()
self.reserved6 = vs_prim.vs_prim.v_uint64()
class symtab_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SYMTAB
self.cmdsize = vs_prim.v_uint32() # sizeof(struct symtab_command)
self.symoff = vs_prim.v_uint32() # symbol table offset
self.nsyms = vs_prim.v_uint32() # number of symbol table entries
self.stroff = vs_prim.v_uint32() # string table offset
self.strsize = vs_prim.v_uint32() # string table size in bytes
class dysymtab_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_DYSYMTAB
self.cmdsize = vs_prim.v_uint32() # sizeof(struct dysymtab_command)
self.ilocalsym = vs_prim.v_uint32() # index to local symbols
self.nlocalsym = vs_prim.v_uint32() # number of local symbols
self.iextdefsym = vs_prim.v_uint32() # index to externally defined symbols
self.nextdefsym = vs_prim.v_uint32() # number of externally defined symbols
self.iundefsym = vs_prim.v_uint32() # index to undefined symbols
self.nundefsym = vs_prim.v_uint32() # number of undefined symbols
self.tocoff = vs_prim.v_uint32() # file offset to table of contents
self.ntoc = vs_prim.v_uint32() # number of entries in table of contents
self.modtaboff = vs_prim.v_uint32() # file offset to module table
self.nmodtab = vs_prim.v_uint32() # number of module table entries
self.extrefsymoff = vs_prim.v_uint32() # offset to referenced symbol table
self.nextrefsyms = vs_prim.v_uint32() # number of referenced symbol table entries
self.indirectsymoff = vs_prim.v_uint32() # file offset to the indirect symbol table
self.nindirectsyms = vs_prim.v_uint32() # number of indirect symbol table entries
self.extreloff = vs_prim.v_uint32() # offset to external relocation entries
self.nextrel = vs_prim.v_uint32() # number of external relocation entries
self.locreloff = vs_prim.v_uint32() # offset to local relocation entries
self.nlocrel = vs_prim.v_uint32() # number of local relocation entries
class dylib_table_of_contents(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.symbol_index = vs_prim.v_uint32() # the defined external symbol (index into the symbol table)
self.module_index = vs_prim.v_uint32() # index into the module table this symbol is defined in
class dylib_module(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.module_name = vs_prim.v_uint32() # the module name (index into string table)
self.iextdefsym = vs_prim.v_uint32() # index into externally defined symbols
self.nextdefsym = vs_prim.v_uint32() # number of externally defined symbols
self.irefsym = vs_prim.v_uint32() # index into reference symbol table
self.nrefsym = vs_prim.v_uint32() # number of reference symbol table entries
self.ilocalsym = vs_prim.v_uint32() # index into symbols for local symbols
self.nlocalsym = vs_prim.v_uint32() # number of local symbols
self.iextrel = vs_prim.v_uint32() # index into external relocation entries
self.nextrel = vs_prim.v_uint32() # number of external relocation entries
self.iinit_iterm = vs_prim.v_uint32() # low 16 bits are the index into the init section, high 16 bits are the index into the term section
self.ninit_nterm = vs_prim.v_uint32() # low 16 bits are the number of init section entries, high 16 bits are the number of term section entries
self.objc_module_info_addr = vs_prim.v_uint32() # the (__OBJC,__module_info) section
self.objc_module_info_size = vs_prim.v_uint32() # the (__OBJC,__module_info) section
class dylib_module_64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.module_name = vs_prim.v_uint32() # the module name (index into string table)
self.iextdefsym = vs_prim.v_uint32() # index into externally defined symbols
self.nextdefsym = vs_prim.v_uint32() # number of externally defined symbols
self.irefsym = vs_prim.v_uint32() # index into reference symbol table
self.nrefsym = vs_prim.v_uint32() # number of reference symbol table entries
self.ilocalsym = vs_prim.v_uint32() # index into symbols for local symbols
self.nlocalsym = vs_prim.v_uint32() # number of local symbols
self.iextrel = vs_prim.v_uint32() # index into external relocation entries
self.nextrel = vs_prim.v_uint32() # number of external relocation entries
self.iinit_iterm = vs_prim.v_uint32() # low 16 bits are the index into the init section, high 16 bits are the index into the term section
self.ninit_nterm = vs_prim.v_uint32() # low 16 bits are the number of init section entries, high 16 bits are the number of term section entries
self.objc_module_info_size = vs_prim.v_uint32() # the (__OBJC,__module_info) section
self.objc_module_info_addr = vs_prim.v_uint64() # the (__OBJC,__module_info) section
class dylib_reference(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.flags = vs_prim.v_uint32() # flags to indicate the type of reference
class twolevel_hints_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_TWOLEVEL_HINTS
self.cmdsize = vs_prim.v_uint32() # sizeof(struct twolevel_hints_command)
self.offset = vs_prim.v_uint32() # offset to the hint table
self.nhints = vs_prim.v_uint32() # number of hints in the hint table
class twolevel_hint(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.itoc = vs_prim.v_uint32() # index into the table of contents
class prebind_cksum_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_PREBIND_CKSUM
self.cmdsize = vs_prim.v_uint32() # sizeof(struct prebind_cksum_command)
self.cksum = vs_prim.v_uint32() # the check sum or zero
class uuid_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_UUID
self.cmdsize = vs_prim.v_uint32() # sizeof(struct uuid_command)
self.uuid[16] = vs_prim.v_uint8() # the 128-bit uuid
class rpath_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_RPATH
self.cmdsize = vs_prim.v_uint32() # includes string
self.path = lc_str() # path to add to run path
class linkedit_data_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO
self.cmdsize = vs_prim.v_uint32() # sizeof(struct linkedit_data_command)
self.dataoff = vs_prim.v_uint32() # file offset of data in __LINKEDIT segment
self.datasize = vs_prim.v_uint32() # file size of data in __LINKEDIT segment
class encryption_info_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_ENCRYPTION_INFO
self.cmdsize = vs_prim.v_uint32() # sizeof(struct encryption_info_command)
self.cryptoff = vs_prim.v_uint32() # file offset of encrypted range
self.cryptsize = vs_prim.v_uint32() # file size of encrypted range
self.cryptid = vs_prim.v_uint32() # which enryption system, 0 means not-encrypted yet
class symseg_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_SYMSEG
self.cmdsize = vs_prim.v_uint32() # sizeof(struct symseg_command)
self.offset = vs_prim.v_uint32() # symbol segment offset
self.size = vs_prim.v_uint32() # symbol segment size in bytes
class ident_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_IDENT
self.cmdsize = vs_prim.v_uint32() # strings that follow this command
class fvmfile_command(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.cmd = vs_prim.v_uint32() # LC_FVMFILE
self.cmdsize = vs_prim.v_uint32() # includes pathname string
self.name = lc_str() # files pathname
self.header_addr = vs_prim.v_uint32() # files virtual address

218
vstruct/defs/pe.py Normal file
View File

@ -0,0 +1,218 @@
import vstruct
from vstruct.primitives import *
class IMAGE_BASE_RELOCATION(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.VirtualAddress = v_uint32()
self.SizeOfBlock = v_uint32()
class IMAGE_DATA_DIRECTORY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.VirtualAddress = v_uint32()
self.Size = v_uint32()
class IMAGE_DOS_HEADER(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.e_magic = v_uint16()
self.e_cblp = v_uint16()
self.e_cp = v_uint16()
self.e_crlc = v_uint16()
self.e_cparhdr = v_uint16()
self.e_minalloc = v_uint16()
self.e_maxalloc = v_uint16()
self.e_ss = v_uint16()
self.e_sp = v_uint16()
self.e_csum = v_uint16()
self.e_ip = v_uint16()
self.e_cs = v_uint16()
self.e_lfarlc = v_uint16()
self.e_ovno = v_uint16()
self.e_res = vstruct.VArray([v_uint16() for i in range(4)])
self.e_oemid = v_uint16()
self.e_oeminfo = v_uint16()
self.e_res2 = vstruct.VArray([v_uint16() for i in range(10)])
self.e_lfanew = v_uint32()
class IMAGE_EXPORT_DIRECTORY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Characteristics = v_uint32()
self.TimeDateStamp = v_uint32()
self.MajorVersion = v_uint16()
self.MinorVersion = v_uint16()
self.Name = v_uint32()
self.Base = v_uint32()
self.NumberOfFunctions = v_uint32()
self.NumberOfNames = v_uint32()
self.AddressOfFunctions = v_uint32()
self.AddressOfNames = v_uint32()
self.AddressOfOrdinals = v_uint32()
class IMAGE_FILE_HEADER(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Machine = v_uint16()
self.NumberOfSections = v_uint16()
self.TimeDateStamp = v_uint32()
self.PointerToSymbolTable = v_uint32()
self.NumberOfSymbols = v_uint32()
self.SizeOfOptionalHeader = v_uint16()
self.Ccharacteristics = v_uint16()
class IMAGE_IMPORT_DIRECTORY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.OriginalFirstThunk = v_uint32()
self.TimeDateStamp = v_uint32()
self.ForwarderChain = v_uint32()
self.Name = v_uint32()
self.FirstThunk = v_uint32()
class IMAGE_LOAD_CONFIG_DIRECTORY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Size = v_uint32()
self.TimeDateStamp = v_uint32()
self.MajorVersion = v_uint16()
self.MinorVersion = v_uint16()
self.GlobalFlagsClear = v_uint32()
self.GlobalFlagsSet = v_uint32()
self.CriticalSectionDefaultTimeout = v_uint32()
self.DeCommitFreeBlockThreshold = v_uint32()
self.DeCommitTotalFreeThreshold = v_uint32()
self.LockPrefixTable = v_uint32()
self.MaximumAllocationSize = v_uint32()
self.VirtualMemoryThreshold = v_uint32()
self.ProcessHeapFlags = v_uint32()
self.ProcessAffinityMask = v_uint32()
self.CSDVersion = v_uint16()
self.Reserved1 = v_uint16()
self.EditList = v_uint32()
self.SecurityCookie = v_uint32()
self.SEHandlerTable = v_uint32()
self.SEHandlerCount = v_uint32()
class IMAGE_NT_HEADERS(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Signature = v_bytes(4)
self.FileHeader = IMAGE_FILE_HEADER()
self.OptionalHeader = IMAGE_OPTIONAL_HEADER()
class IMAGE_NT_HEADERS64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Signature = v_bytes(4)
self.FileHeader = IMAGE_FILE_HEADER()
self.OptionalHeader = IMAGE_OPTIONAL_HEADER64()
class IMAGE_OPTIONAL_HEADER(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Magic = v_bytes(2)
self.MajorLinkerVersion = v_uint8()
self.MinorLinkerVersion = v_uint8()
self.SizeOfCode = v_uint32()
self.SizeOfInitializedData = v_uint32()
self.SizeOfUninitializedData = v_uint32()
self.AddressOfEntryPoint = v_uint32()
self.BaseOfCode = v_uint32()
self.BaseOfData = v_uint32()
self.ImageBase = v_uint32()
self.SectionAlignment = v_uint32()
self.FileAlignment = v_uint32()
self.MajorOperatingSystemVersion = v_uint16()
self.MinorOperatingSystemVersion = v_uint16()
self.MajorImageVersion = v_uint16()
self.MinorImageVersion = v_uint16()
self.MajorSubsystemVersion = v_uint16()
self.MinorSubsystemVersion = v_uint16()
self.Win32VersionValue = v_uint32()
self.SizeOfImage = v_uint32()
self.SizeOfHeaders = v_uint32()
self.CheckSum = v_uint32()
self.Subsystem = v_uint16()
self.DllCharacteristics = v_uint16()
self.SizeOfStackReserve = v_uint32()
self.SizeOfStackCommit = v_uint32()
self.SizeOfHeapReserve = v_uint32()
self.SizeOfHeapCommit = v_uint32()
self.LoaderFlags = v_uint32()
self.NumberOfRvaAndSizes = v_uint32()
self.DataDirectory = vstruct.VArray([IMAGE_DATA_DIRECTORY() for i in range(16)])
class IMAGE_OPTIONAL_HEADER64(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Magic = v_bytes(2)
self.MajorLinkerVersion = v_uint8()
self.MinorLinkerVersion = v_uint8()
self.SizeOfCode = v_uint32()
self.SizeOfInitializedData = v_uint32()
self.SizeOfUninitializedData = v_uint32()
self.AddressOfEntryPoint = v_uint32()
self.BaseOfCode = v_uint32()
self.ImageBase = v_uint64()
self.SectionAlignment = v_uint32()
self.FileAlignment = v_uint32()
self.MajorOperatingSystemVersion = v_uint16()
self.MinorOperatingSystemVersion = v_uint16()
self.MajorImageVersion = v_uint16()
self.MinorImageVersion = v_uint16()
self.MajorSubsystemVersion = v_uint16()
self.MinorSubsystemVersion = v_uint16()
self.Win32VersionValue = v_uint32()
self.SizeOfImage = v_uint32()
self.SizeOfHeaders = v_uint32()
self.CheckSum = v_uint32()
self.Subsystem = v_uint16()
self.DllCharacteristics = v_uint16()
self.SizeOfStackReserve = v_uint64()
self.SizeOfStackCommit = v_uint64()
self.SizeOfHeapReserve = v_uint64()
self.SizeOfHeapCommit = v_uint64()
self.LoaderFlags = v_uint32()
self.NumberOfRvaAndSizes = v_uint32()
self.DataDirectory = vstruct.VArray([IMAGE_DATA_DIRECTORY() for i in range(16)])
class IMAGE_RESOURCE_DIRECTORY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Characteristics = v_uint32()
self.TimeDateStamp = v_uint32()
self.MajorVersion = v_uint16()
self.MinorVersion = v_uint16()
self.NumberOfNamedEntries = v_uint16()
self.NumberOfIdEntries = v_uint16()
class IMAGE_SECTION_HEADER(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Name = v_str(8)
self.VirtualSize = v_uint32()
self.VirtualAddress = v_uint32()
self.SizeOfRawData = v_uint32()
self.PointerToRawData = v_uint32()
self.PointerToRelocations = v_uint32()
self.PointerToLineNumbers = v_uint32()
self.NumberOfRelocations = v_uint16()
self.NumberOfLineNumbers = v_uint16()
self.Characteristics = v_uint32()
class IMAGE_RUNTIME_FUNCTION_ENTRY(vstruct.VStruct):
"""
Used in the .pdata section of a PE32+ for all non
leaf functions.
"""
def __init__(self):
vstruct.VStruct.__init__(self)
self.BeginAddress = v_uint32()
self.EndAddress = v_uint32()
self.UnwindInfoAddress = v_uint32()

231
vstruct/defs/win32.py Normal file
View File

@ -0,0 +1,231 @@
# FIXME this is named wrong!
import vstruct
from vstruct.primitives import *
class CLIENT_ID(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.UniqueProcess = v_ptr()
self.UniqueThread = v_ptr()
class EXCEPTION_RECORD(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.ExceptionCode = v_uint32()
self.ExceptionFlags = v_uint32()
self.ExceptionRecord = v_ptr()
self.ExceptionAddress = v_ptr()
self.NumberParameters = v_uint32()
class EXCEPTION_REGISTRATION(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.prev = v_ptr()
self.handler = v_ptr()
class HEAP(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Entry = HEAP_ENTRY()
self.Signature = v_uint32()
self.Flags = v_uint32()
self.ForceFlags = v_uint32()
self.VirtualMemoryThreshold = v_uint32()
self.SegmentReserve = v_uint32()
self.SegmentCommit = v_uint32()
self.DeCommitFreeBlockThreshold = v_uint32()
self.DeCommitTotalFreeThreshold = v_uint32()
self.TotalFreeSize = v_uint32()
self.MaximumAllocationSize = v_uint32()
self.ProcessHeapsListIndex = v_uint16()
self.HeaderValidateLength = v_uint16()
self.HeaderValidateCopy = v_ptr()
self.NextAvailableTagIndex = v_uint16()
self.MaximumTagIndex = v_uint16()
self.TagEntries = v_ptr()
self.UCRSegments = v_ptr()
self.UnusedUnCommittedRanges = v_ptr()
self.AlignRound = v_uint32()
self.AlignMask = v_uint32()
self.VirtualAllocBlocks = ListEntry()
self.Segments = vstruct.VArray([v_uint32() for i in range(64)])
self.u = vstruct.VArray([v_uint8() for i in range(16)])
self.u2 = vstruct.VArray([v_uint8() for i in range(2)])
self.AllocatorBackTraceIndex = v_uint16()
self.NonDedicatedListLength = v_uint32()
self.LargeBlocksIndex = v_ptr()
self.PseudoTagEntries = v_ptr()
self.FreeLists = vstruct.VArray([ListEntry() for i in range(128)])
self.LockVariable = v_uint32()
self.CommitRoutine = v_ptr()
self.FrontEndHeap = v_ptr()
self.FrontEndHeapLockCount = v_uint16()
self.FrontEndHeapType = v_uint8()
self.LastSegmentIndex = v_uint8()
class HEAP_SEGMENT(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Entry = HEAP_ENTRY()
self.SegmentSignature = v_uint32()
self.SegmentFlags = v_uint32()
self.Heap = v_ptr()
self.LargestUncommitedRange = v_uint32()
self.BaseAddress = v_ptr()
self.NumberOfPages = v_uint32()
self.FirstEntry = v_ptr()
self.LastValidEntry = v_ptr()
self.NumberOfUnCommittedPages = v_uint32()
self.NumberOfUnCommittedRanges = v_uint32()
self.UncommittedRanges = v_ptr()
self.SegmentAllocatorBackTraceIndex = v_uint16()
self.Reserved = v_uint16()
self.LastEntryInSegment = v_ptr()
class HEAP_ENTRY(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Size = v_uint16()
self.PrevSize = v_uint16()
self.SegmentIndex = v_uint8()
self.Flags = v_uint8()
self.Unused = v_uint8()
self.TagIndex = v_uint8()
class ListEntry(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Flink = v_ptr()
self.Blink = v_ptr()
class NT_TIB(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.ExceptionList = v_ptr()
self.StackBase = v_ptr()
self.StackLimit = v_ptr()
self.SubSystemTib = v_ptr()
self.FiberData = v_ptr()
#x.Version = v_ptr() # This is a union field
self.ArbitraryUserPtr = v_ptr()
self.Self = v_ptr()
class PEB(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.InheritedAddressSpace = v_uint8()
self.ReadImageFileExecOptions = v_uint8()
self.BeingDebugged = v_uint8()
self.SpareBool = v_uint8()
self.Mutant = v_ptr()
self.ImageBaseAddress = v_ptr()
self.Ldr = v_ptr()
self.ProcessParameters = v_ptr()
self.SubSystemData = v_ptr()
self.ProcessHeap = v_ptr()
self.FastPebLock = v_ptr()
self.FastPebLockRoutine = v_ptr()
self.FastPebUnlockRoutine = v_ptr()
self.EnvironmentUpdateCount = v_uint32()
self.KernelCallbackTable = v_ptr()
self.SystemReserved = v_uint32()
self.AtlThunkSListPtr32 = v_ptr()
self.FreeList = v_ptr()
self.TlsExpansionCounter = v_uint32()
self.TlsBitmap = v_ptr()
self.TlsBitmapBits = vstruct.VArray([v_uint32() for i in range(2)])
self.ReadOnlySharedMemoryBase = v_ptr()
self.ReadOnlySharedMemoryHeap = v_ptr()
self.ReadOnlyStaticServerData = v_ptr()
self.AnsiCodePageData = v_ptr()
self.OemCodePageData = v_ptr()
self.UnicodeCaseTableData = v_ptr()
self.NumberOfProcessors = v_uint32()
self.NtGlobalFlag = v_uint64()
self.CriticalSectionTimeout = v_uint64()
self.HeapSegmentReserve = v_uint32()
self.HeapSegmentCommit = v_uint32()
self.HeapDeCommitTotalFreeThreshold = v_uint32()
self.HeapDeCommitFreeBlockThreshold = v_uint32()
self.NumberOfHeaps = v_uint32()
self.MaximumNumberOfHeaps = v_uint32()
self.ProcessHeaps = v_ptr()
self.GdiSharedHandleTable = v_ptr()
self.ProcessStarterHelper = v_ptr()
self.GdiDCAttributeList = v_uint32()
self.LoaderLock = v_ptr()
self.OSMajorVersion = v_uint32()
self.OSMinorVersion = v_uint32()
self.OSBuildNumber = v_uint16()
self.OSCSDVersion = v_uint16()
self.OSPlatformId = v_uint32()
self.ImageSubsystem = v_uint32()
self.ImageSubsystemMajorVersion = v_uint32()
self.ImageSubsystemMinorVersion = v_uint32()
self.ImageProcessAffinityMask = v_uint32()
self.GdiHandleBuffer = vstruct.VArray([v_ptr() for i in range(34)])
self.PostProcessInitRoutine = v_ptr()
self.TlsExpansionBitmap = v_ptr()
self.TlsExpansionBitmapBits = vstruct.VArray([v_uint32() for i in range(32)])
self.SessionId = v_uint32()
self.AppCompatFlags = v_uint64()
self.AppCompatFlagsUser = v_uint64()
self.pShimData = v_ptr()
self.AppCompatInfo = v_ptr()
self.CSDVersion = v_ptr()
self.UNKNOWN = v_uint32()
self.ActivationContextData = v_ptr()
self.ProcessAssemblyStorageMap = v_ptr()
self.SystemDefaultActivationContextData = v_ptr()
self.SystemAssemblyStorageMap = v_ptr()
self.MinimumStackCommit = v_uint32()
class SEH3_SCOPETABLE(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.EnclosingLevel = v_int32()
self.FilterFunction = v_ptr()
self.HandlerFunction = v_ptr()
class SEH4_SCOPETABLE(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.GSCookieOffset = v_int32()
self.GSCookieXOROffset = v_int32()
self.EHCookieOffset = v_int32()
self.EHCookieXOROffset = v_int32()
self.EnclosingLevel = v_int32()
self.FilterFunction = v_ptr()
self.HandlerFunction = v_ptr()
class TEB(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.TIB = NT_TIB()
self.EnvironmentPointer = v_ptr()
self.ClientId = CLIENT_ID()
self.ActiveRpcHandle = v_ptr()
self.ThreadLocalStorage = v_ptr()
self.ProcessEnvironmentBlock = v_ptr()
self.LastErrorValue = v_uint32()
self.CountOfOwnedCriticalSections = v_uint32()
self.CsrClientThread = v_ptr()
self.Win32ThreadInfo = v_ptr()
self.User32Reserved = vstruct.VArray([v_uint32() for i in range(26)])
self.UserReserved = vstruct.VArray([v_uint32() for i in range(5)])
self.WOW32Reserved = v_ptr()
self.CurrentLocale = v_uint32()
self.FpSoftwareStatusRegister = v_uint32()
class CLSID(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.uuid = GUID()
class IID(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.uuid = GUID()

View File

@ -0,0 +1,36 @@
'''
The pre-made windows structure defs (extracted from pdb syms)
'''
import envi
import ctypes
import platform
def isSysWow64():
k32 = ctypes.windll.kernel32
if not hasattr(k32, 'IsWow64Process'):
return False
ret = ctypes.c_ulong(0)
myproc = ctypes.c_size_t(-1)
if not k32.IsWow64Process(myproc, ctypes.addressof(ret)):
return False
return bool(ret.value)
def getCurrentDef(normname):
bname, wver, stuff, whichkern = platform.win32_ver()
wvertup = wver.split('.')
arch = envi.getCurrentArch()
if isSysWow64():
arch = 'wow64'
modname = 'vstruct.defs.windows.win_%s_%s_%s.%s' % (wvertup[0], wvertup[1], arch, normname)
try:
mod = __import__(modname, {}, {}, 1)
except ImportError, e:
mod = None
return mod
if __name__ == '__main__':
print getCurrentDef('ntdll')

View File

@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

354
vstruct/primitives.py Normal file
View File

@ -0,0 +1,354 @@
import struct
class v_enum: pass
class v_base(object):
def __init__(self):
self._vs_meta = {}
def vsGetMeta(self, name, defval=None):
return self._vs_meta.get(name, defval)
def vsSetMeta(self, name, value):
self._vs_meta[name] = value
# Sub-classes (primitive base, or VStruct must have these
def vsParse(self, bytes): return NotImplemented
def vsGetFormat(self): return NotImplemented
def vsIsPrim(self): return NotImplemented
def vsGetTypeName(self): return NotImplemented
class v_prim(v_base):
def __init__(self):
v_base.__init__(self)
# Used by base len(),vsGetFormat, etc...
self._vs_value = None
self._vs_length = None
self._vs_fmt = None
def vsIsPrim(self):
return True
def vsGetTypeName(self):
return self.__class__.__name__
def vsParse(self, bytes):
"""
Parser for primitives which assumes we are
calling parse directly.
"""
fmt = "<%s" % self.vsGetFormat()
val = struct.unpack(fmt, bytes)[0]
self.vsSetParsedValue(val)
def vsSetParsedValue(self, value):
"""
Primitives will be assigned their values by a parser
which chops data up with struct format strings. This
method will be called by parsers to assign the value
of a primitive from a struct.unpack call.
"""
self._vs_value = value
def vsGetFmtValue(self):
"""
The emit function uses this to ask each primitive for the
object to be put into the struct pack sequence.
Most objects just return their value...
"""
return self._vs_value
def vsGetValue(self):
"""
Get the type specific value for this field.
(Used by the structure dereference method to return
a python native for the field by name)
"""
return self._vs_value
def vsSetValue(self, value):
"""
Set the type specific value for this field.
"""
self._vs_value = value
def vsGetFormat(self):
return self._vs_fmt
def __repr__(self):
return repr(self.vsGetValue())
def __len__(self):
return self._vs_length
def __str__(self):
return str(self.vsGetValue())
class v_number(v_prim):
def __init__(self, value=0, swapend=False):
v_prim.__init__(self)
self._vs_swapend = swapend
self._vs_length = struct.calcsize(self.vsGetFormat())
self.vsSetValue(value)
def vsSetValue(self, value):
"""
Assure that the value is long() able for all numeric types.
"""
self._vs_value = long(value)
def vsSetParsedValue(self, value):
# We were parsed N endian. Switch if needed.
if self._vs_swapend:
oval = value
value = 0
for i in range(self._vs_length):
value = value << 8
value += (oval >> (8*i)) & 0xff
self.vsSetValue(value)
def vsGetFormat(self):
return self.__class__._vs_fmt
def __int__(self):
return int(self._vs_value)
def __long__(self):
return long(self._vs_value)
##################################################################
# Implement the number API
def __add__(self, other): return long(self) + long(other)
def __sub__(self, other): return long(self) - long(other)
def __mul__(self, other): return long(self) * long(other)
def __div__(self, other): return long(self) / long(other)
def __floordiv__(self, other): return long(self) // long(other)
def __mod__(self, other): return long(self) % long(other)
def __divmod__(self, other): return divmod(long(self), long(other))
def __pow__(self, other, modulo=None): return pow(long(self), long(other), modulo)
def __lshift__(self, other): return long(self) << long(other)
def __rshift__(self, other): return long(self) >> long(other)
def __and__(self, other): return long(self) & long(other)
def __xor__(self, other): return long(self) ^ long(other)
def __or__(self, other): return long(self) | long(other)
# Operator swapped variants
def __radd__(self, other): return long(other) + long(self)
def __rsub__(self, other): return long(other) - long(self)
def __rmul__(self, other): return long(other) * long(self)
def __rdiv__(self, other): return long(other) / long(self)
def __rfloordiv__(self, other): return long(other) // long(self)
def __rmod__(self, other): return long(other) % long(self)
def __rdivmod__(self, other): return divmod(long(other), long(self))
def __rpow__(self, other, modulo=None): return pow(long(other), long(self), modulo)
def __rlshift__(self, other): return long(other) << long(self)
def __rrshift__(self, other): return long(other) >> long(self)
def __rand__(self, other): return long(other) & long(self)
def __rxor__(self, other): return long(other) ^ long(self)
def __ror__(self, other): return long(other) | long(self)
# Inplace variants
def __iadd__(self, other): self.vsSetValue(self+other); return self
def __isub__(self, other): self.vsSetValue(self - other); return self
def __imul__(self, other): self.vsSetValue(self*other); return self
def __idiv__(self, other): self.vsSetValue(self/other); return self
def __ifloordiv__(self, other): self.vsSetValue(self // other); return self
def __imod__(self, other): self.vsSetValue(self % other); return self
def __ipow__(self, other, modulo=None): self.vsSetValue(pow(self, other, modulo)); return self
def __ilshift__(self, other): self.vsSetValue(self << other); return self
def __irshift__(self, other): self.vsSetValue(self >> other); return self
def __iand__(self, other): self.vsSetValue(self & other); return self
def __ixor__(self, other): self.vsSetValue(self ^ other); return self
def __ior__(self, other): self.vsSetValue(self | other); return self
# operator helpers
def __neg__(self): return -(long(self))
def __pos__(self): return +(long(self))
def __abs__(self): return abs(long(self))
def __invert__(self): return ~(long(self))
# index use helper
def __index__(self): return long(self)
def __coerce__(self, other):
try:
return long(self),long(other)
except Exception, e:
return NotImplemented
# Print helpers
def __hex__(self): return hex(long(self))
def __oct__(self): return oct(long(self))
class v_uint8(v_number):
_vs_builder = True
_vs_fmt = "B"
class v_uint16(v_number):
_vs_builder = True
_vs_fmt = "H"
class v_uint32(v_number):
_vs_builder = True
_vs_fmt = "L"
class v_uint64(v_number):
_vs_builder = True
_vs_fmt = "Q"
class v_int8(v_number):
_vs_builder = True
_vs_fmt = "b"
class v_int16(v_number):
_vs_builder = True
_vs_fmt = "h"
class v_int32(v_number):
_vs_builder = True
_vs_fmt = "l"
class v_int64(v_number):
_vs_builder = True
_vs_fmt = "q"
pointersize = struct.calcsize("P")
class v_size_t(v_number):
_vs_builder = True
if pointersize == 4:
_vs_fmt = "L"
else:
_vs_fmt = "Q"
def __repr__(self):
return "0x%.8x" % self._vs_value
class v_ptr(v_size_t):
pass
class v_ptr32(v_ptr):
_vs_builder = True
_vs_fmt = "L"
class v_ptr64(v_ptr):
_vs_builder = True
_vs_fmt = "Q"
class v_bytes(v_prim):
_vs_builder = True
def __init__(self, size=0, vbytes=None):
v_prim.__init__(self)
if vbytes == None:
vbytes = '\x00' * size
self._vs_length = len(vbytes)
self._vs_value = vbytes
def vsGetFormat(self):
return "%ds" % len(self)
def __repr__(self):
return self._vs_value.encode('hex')
class v_str(v_prim):
'''
A string placeholder class which will automagically return
up to a null terminator (and will keep it's size by null
padding when assigned to)
'''
_vs_builder = True
def __init__(self, size=4, val=''):
v_prim.__init__(self)
self._vs_length = size
self._vs_value = val.ljust(size, '\x00')
def vsGetValue(self):
val = v_prim.vsGetValue(self)
return val.split("\x00")[0]
def vsSetValue(self, val):
realval = val.ljust(len(self), '\x00')
v_prim.vsSetValue(self, realval)
def vsGetFormat(self):
return "%ds" % len(self)
def __len__(self):
return len(self._vs_value)
class v_wstr(v_str):
'''
Unicode variant of the above string class
NOTE: the size paramater is in WCHARs!
'''
_vs_builder = True
def __init__(self, size=4, encode='utf-16le', val=''):
v_prim.__init__(self)
b = val.ljust(size, '\x00').encode(encode)
self._vs_length = len(b)
self._vs_value = b
self._vs_encode = encode
def vsGetValue(self):
val = v_prim.vsGetValue(self)
val = val.decode(self._vs_encode)
return val.split("\x00")[0]
def vsSetValue(self, val):
rbytes = val.encode(self._vs_encode)
rbytes = rbytes.ljust(len(self), '\x00')
v_prim.vsSetValue(self, rbytes)
def vsGetFormat(self):
return "%ds" % len(self)
def __len__(self):
return len(self._vs_value)
class GUID(v_prim):
_vs_builder = True
def __init__(self, guidstr=None):
"""
Construct a new GUID primitive. You may specify a GUID string in the
constructor to populate initial values.
"""
v_prim.__init__(self)
self._vs_length = 16
self._vs_value = "\x00" * 16
self._vs_fmt = "16s"
self._guid_fields = (0,0,0,0,0,0,0,0,0,0,0)
if guidstr != None:
self._parseGuidStr(guidstr)
def _parseGuidStr(self, gstr):
gstr = gstr.replace("{","")
gstr = gstr.replace("}","")
gstr = gstr.replace("-","")
bytes = gstr.decode("hex")
# Totally cheating... ;)
self._guid_fields = struct.unpack(">LHH8B", bytes)
def vsSetValue(self, bytes):
self._guid_fields = struct.unpack("<LHH8B", bytes)
def vsGetValue(self):
return struck.pack("<LHH8B", *self._guid_fields)
def __repr__(self):
base = "{%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}"
return base % self._guid_fields