Source code for PE.cofflib
'''
Some utilities for dealing with COFF .LIB files
'''
import vstruct
from vstruct.defs.pe import *
from vstruct.primitives import *
IMAGE_ARCHIVE_START_SIZE = 8
IMAGE_ARCHIVE_START = '!<arch>\n'
IMAGE_ARCHIVE_END = '`\n'
IMAGE_ARCHIVE_PAD = '\n'
IMAGE_ARCHIVE_LINKER_MEMBER = '/ '
IMAGE_ARCHIVE_LONGNAMES_MEMBER = '// '
IMAGE_ARCHIVE_HEADER_SIZE = 60
[docs]class IMAGE_ARCHIVE_MEMBER(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.MemberHeader = IMAGE_ARCHIVE_MEMBER_HEADER()
[docs] def vsParse(self, bytes, offset=0):
off = vstruct.VStruct.vsParse(self, bytes, offset=offset)
# Use the size that the header says we are...
offset = offset + len(self.MemberHeader) + int( self.MemberHeader.Size )
# two byte aligned
if offset % 2:
offset += 1
return offset
[docs]class IMAGE_ARCHIVE_LINKER1(IMAGE_ARCHIVE_MEMBER):
def __init__(self):
IMAGE_ARCHIVE_MEMBER.__init__(self)
self.NumberOfSymbols = v_uint32(bigend=True)
self.SymbolOffsets = vstruct.VArray()
self.SymbolNames = vstruct.VArray()
[docs] def pcb_NumberOfSymbols(self):
c = self.NumberOfSymbols
print self.MemberHeader.tree()
print 'SYMBOLS',c
self.SymbolOffsets = vstruct.VArray( elems=[ v_uint32(bigend=True) for i in xrange(c) ])
self.SymbolNames = vstruct.VArray( elems=[ v_zstr() for i in xrange(c) ])
[docs]class IMAGE_ARCHIVE_LINKER2(IMAGE_ARCHIVE_MEMBER):
def __init__(self):
IMAGE_ARCHIVE_MEMBER.__init__(self)
self.NumberOfMembers = v_uint32()
self.MemberOffsets = vstruct.VArray()
self.NumberOfSymbols = v_uint32()
self.SymbolIndexes = vstruct.VArray()
self.SymbolNames = vstruct.VArray()
[docs] def pcb_NumberOfMembers(self):
c = self.NumberOfMembers
self.MemberOffsets = vstruct.VArray( elems=[ v_uint32() for i in xrange(c) ] )
[docs] def pcb_NumberOfSymbols(self):
c = self.NumberOfSymbols
self.SymbolIndexes = vstruct.VArray( elems=[ v_uint16() for i in xrange(c) ])
self.SymbolNames = vstruct.VArray( elems=[ v_zstr() for i in xrange(c) ])
IMPORT_SIG = '0000ffff'.decode('hex')
IMPORT_CODE = 0 #Executable code.
IMPORT_DATA = 1 #Data.
IMPORT_CONST = 2 #Specified as CONST in the .def file.
[docs]class IMAGE_ARCHIVE_IMPORT(IMAGE_ARCHIVE_MEMBER):
def __init__(self):
IMAGE_ARCHIVE_MEMBER.__init__(self)
self.Sig1 = v_uint16()
self.Sig2 = v_uint16()
self.Version = v_uint16()
self.Machine = v_uint16()
self.DateTimeStamp = v_uint32()
self.SizeOfData = v_uint32()
self.Ordinal = v_uint16()
self.ImportFlags = v_uint16()
self.ImportName = v_zstr()
self.ImportLibName = v_zstr()
[docs]class IMAGE_COFF_SYMBOL(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.u = vstruct.VUnion()
self.u.Name = v_str(size=8)
self.u.lname = vstruct.VStruct()
self.u.lname.Zeros = v_uint32()
self.u.lname.Offset = v_uint32()
self.Value = v_uint32()
self.SectionNumber = v_uint16()
self.Type = v_uint16()
self.StorageClass = v_uint8()
self.NumberOfAuxSymbols = v_uint8()
self.AuxSymbols = vstruct.VArray()
[docs] def pcb_NumberOfAuxSymbols(self):
a = self.NumberOfAuxSymbols
self.AuxSymbols = vstruct.VArray(elems=[ v_bytes(size=18) for i in xrange(a) ])
[docs]class IMAGE_ARCHIVE_COFF(IMAGE_ARCHIVE_MEMBER):
def __init__(self, bigend=False):
IMAGE_ARCHIVE_MEMBER.__init__(self)
self.FileHeader = IMAGE_FILE_HEADER()
self.SectionHeaders = vstruct.VArray()
self.SectionData = v_bytes()
self.SymbolTable = vstruct.VArray()
[docs]class IMAGE_ARCHIVE(vstruct.VStruct):
def __init__(self):
vstruct.VStruct.__init__(self)
self.Magic = v_bytes(vbytes=IMAGE_ARCHIVE_START)
# A set of image archive names is first...
self.ImageArchiveMembers = vstruct.VArray(elems=(IMAGE_ARCHIVE_LINKER1(), IMAGE_ARCHIVE_LINKER2()))
#self.ImageArchiveMembers = vstruct.VArray()
[docs] def vsParse(self, bytes, offset=0):
blen = len(bytes)
offset = self.vsGetField('Magic').vsParse(bytes, offset=offset,bigend=True)
# Parse the "names" headers
offset = self.vsGetField('ImageArchiveMembers').vsParse(bytes, offset=offset)
while offset < blen:
doff = offset + IMAGE_ARCHIVE_HEADER_SIZE
if bytes.startswith(IMPORT_SIG, doff):
memb = IMAGE_ARCHIVE_IMPORT()
elif bytes.startswith('// ', offset):
# Skip the depricated lib strings crap...
memb = IMAGE_ARCHIVE_MEMBER()
else:
memb = IMAGE_ARCHIVE_COFF()
offset = memb.vsParse(bytes, offset=offset)
if isinstance(memb, IMAGE_ARCHIVE_COFF): print memb.tree()
self.ImageArchiveMembers.vsAddElement(memb)
return offset
[docs]def foo(a, b, idx):
print 'NAME',a.ImageArchiveMembers[1].SymbolNames[idx]
i = a.ImageArchiveMembers[1].SymbolIndexes[idx]
print 'INDEX',i
o = a.ImageArchiveMembers[1].MemberOffsets[i]
print 'OFFSET',o
print 'BYTES',repr(b[o:o+10])
if __name__ == '__main__':
import sys
b = file(sys.argv[1], 'rb').read()
import code
a = IMAGE_ARCHIVE()
#print a.tree()
a.vsParse(b)
print a.tree()
code.interact(local=locals())