Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import struct
- def FileReadDWORD(f, off=0):
- if off != 0:
- f.seek(off)
- return struct.unpack('<I', f.read(4))[0]
- def FileReadWORD(f, off=0):
- if off != 0:
- f.seek(off)
- return struct.unpack('<H', f.read(2))[0]
- class LEParse:
- def __init__(self, filename):
- self.f = open(filename, 'rb')
- self.head = {}
- self.fixups = {}
- self.Pages = []
- def GetLEHeaderOffset(self):
- self.f.seek(0x3C)
- return struct.unpack('<I', self.f.read(4))[0]
- def getPhysAddr(self, VAddr):
- for i in range(len(self.objects)):
- if VAddr >= self.objects[i]['VAddr']:
- if i+1 == len(self.objects):
- break
- if VAddr <= self.objects[i+1]['VAddr']:
- break
- seg = self.objects[i]
- return VAddr-seg['VAddr'] + seg['PAddr']
- def getPaddrPageId(self, PAddr):
- return (PAddr-self.head['DataPageOff'])/self.head['PageSize']
- def ParseHead(self):
- off = self.GetLEHeaderOffset()
- self.f.seek(off)
- if self.f.read(2) != 'LE':
- print '[ERR] invalid file format'
- return 0
- self.head['ByteOrdering'] = FileReadWORD(self.f)
- self.head['WordOrdering'] = FileReadWORD(self.f)
- self.head['Format'] = FileReadDWORD(self.f)
- self.head['CPUType'] = FileReadWORD(self.f)
- self.head['OSType'] = FileReadWORD(self.f)
- self.head['Version'] = FileReadDWORD(self.f)
- self.head['Flags'] = FileReadDWORD(self.f)
- self.head['PageCount'] = FileReadDWORD(self.f)
- self.head['PageSize'] = FileReadDWORD(self.f, off+0x28)
- self.head['PageShift'] = FileReadDWORD(self.f)
- self.head['FixupSize'] = FileReadDWORD(self.f)
- self.head['FixupCksum'] = FileReadDWORD(self.f)
- self.head['LoaderSize'] = FileReadDWORD(self.f)
- self.head['LoaderCksum'] = FileReadDWORD(self.f)
- self.head['ObjectOff'] = FileReadDWORD(self.f)+off
- self.head['ObjectCount'] = FileReadDWORD(self.f)
- self.head['ObjectPage_off'] = FileReadDWORD(self.f)+off
- self.head['ObjectIter_off'] = FileReadDWORD(self.f)
- self.head['ResourceOff'] = FileReadDWORD(self.f)+off
- self.head['ResourceCount'] = FileReadDWORD(self.f)
- self.head['ResNameOff'] = FileReadDWORD(self.f)+off
- self.head['EntryOff'] = FileReadDWORD(self.f)+off
- self.head['ModDirectiveOff'] = FileReadDWORD(self.f)+off
- self.head['ModDirectiveCount'] = FileReadDWORD(self.f)
- self.head['FixupPageOff'] = FileReadDWORD(self.f)+off
- self.head['FixupRecordsoff'] = FileReadDWORD(self.f)+off
- self.head['ImportModuleOff'] = FileReadDWORD(self.f)+off
- self.head['ImportModuleCount'] = FileReadDWORD(self.f)
- self.head['ImportProcOff'] = FileReadDWORD(self.f)+off
- self.head['cksum_off'] = FileReadDWORD(self.f)+off
- self.head['DataPageOff'] = FileReadDWORD(self.f)
- self.head['DataPageCount'] = FileReadDWORD(self.f)
- def ParseObjectTable(self):
- self.f.seek(self.head['ObjectOff'])
- self.objects = []
- for i in range(self.head['ObjectCount']):
- obj = {}
- obj['size'] = FileReadDWORD(self.f)
- obj['VAddr'] = FileReadDWORD(self.f)
- obj['flags'] = FileReadDWORD(self.f)
- #to simplify handling of IDx rebase to 0based array idx
- obj['PT_idx'] = FileReadDWORD(self.f)-1
- obj['PT_count'] = FileReadDWORD(self.f)
- obj['PAddr'] = le.head['DataPageOff'] \
- + obj['PT_idx']*self.head['PageSize']
- obj['Reserved'] = FileReadDWORD(self.f)
- self.objects.append(obj)
- def Parse(self):
- self.ParseHead()
- self.ParseObjectTable()
- self.f.seek(self.head['FixupPageOff'])
- self.fixups['ByPage'] = []
- for i in range(self.head['PageCount']):
- self.fixups['ByPage'].append(FileReadDWORD(self.f)+self.head['FixupRecordsoff'])
- def parseFixupRecords(file, off, count):
- file.seek(off)
- for i in range(count):
- type, flags = struct.unpack('BB', file.read(2))
- print 'type : %d'%type
- print 'flags : %d'%flags
- if type&0x20:
- src, = struct.unpack('B', file.read(1))
- else:
- src, = struct.unpack('<H', file.read(2))
- print 'src off : %04x'%src
- if flags&3 == 0:
- seg, = struct.unpack('B', file.read(1))
- if flags&0x10:
- tgt, = struct.unpack('<I', file.read(4))
- else:
- tgt, = struct.unpack('<H', file.read(2))
- print 'target %d:%08x'%(seg, tgt)
- le = LEParse("C:\\Games\\Bethesda Softworks\\Daggerfall\\FALL.EXE")
- le.Parse()
- target = 0x01809B6
- print "Data base %08x"%le.head['DataPageOff']
- print "segment 3"
- print "\t VAddr : %08x"%le.objects[2]['VAddr']
- print "\t PAddr : %08x"%le.objects[2]['PAddr']
- print "\t page : %d"%le.getPaddrPageId(le.objects[2]['PAddr'])
- print "target :"
- print "\t VAddr : %08x"%target
- target_paddr = le.getPhysAddr(target)
- print "\t PAddr : %08x"%target_paddr
- target_page = le.getPaddrPageId(target_paddr)
- print "\t page : %d"%target_page
- print "\t fixup records for page :"
- print "\t\t start : %08X"%le.fixups['ByPage'][target_page]
- print "\t\t end : %08X"%le.fixups['ByPage'][target_page+1]
- print "Fixups :"
- parseFixupRecords(le.f, le.fixups['ByPage'][target_page], 10)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement