Advertisement
Guest User

Hugly&simple Linear Exe parser

a guest
Feb 25th, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.86 KB | None | 0 0
  1. import struct
  2.  
  3. def FileReadDWORD(f, off=0):
  4.     if off != 0:
  5.         f.seek(off)
  6.     return struct.unpack('<I', f.read(4))[0]
  7.    
  8. def FileReadWORD(f, off=0):
  9.     if off != 0:
  10.         f.seek(off)
  11.     return struct.unpack('<H', f.read(2))[0]   
  12.    
  13. class LEParse:
  14.  
  15.     def __init__(self, filename):
  16.         self.f = open(filename, 'rb')
  17.         self.head = {}
  18.         self.fixups = {}
  19.         self.Pages = []
  20.        
  21.     def GetLEHeaderOffset(self):
  22.         self.f.seek(0x3C)
  23.         return struct.unpack('<I', self.f.read(4))[0]
  24.    
  25.     def getPhysAddr(self, VAddr):
  26.         for i in range(len(self.objects)):
  27.             if VAddr >= self.objects[i]['VAddr']:
  28.                 if i+1 == len(self.objects):
  29.                     break
  30.                 if VAddr <= self.objects[i+1]['VAddr']:
  31.                     break
  32.                
  33.         seg = self.objects[i]
  34.         return VAddr-seg['VAddr'] + seg['PAddr']
  35.    
  36.     def getPaddrPageId(self, PAddr):
  37.         return (PAddr-self.head['DataPageOff'])/self.head['PageSize']
  38.    
  39.     def ParseHead(self):
  40.         off = self.GetLEHeaderOffset()
  41.         self.f.seek(off)
  42.         if self.f.read(2) != 'LE':
  43.             print '[ERR] invalid file format'
  44.             return 0
  45.            
  46.         self.head['ByteOrdering'] = FileReadWORD(self.f)
  47.         self.head['WordOrdering'] = FileReadWORD(self.f)
  48.         self.head['Format'] = FileReadDWORD(self.f)
  49.         self.head['CPUType'] = FileReadWORD(self.f)
  50.         self.head['OSType'] = FileReadWORD(self.f)
  51.         self.head['Version'] = FileReadDWORD(self.f)
  52.         self.head['Flags'] = FileReadDWORD(self.f)
  53.         self.head['PageCount'] = FileReadDWORD(self.f)
  54.         self.head['PageSize'] = FileReadDWORD(self.f, off+0x28)
  55.         self.head['PageShift'] = FileReadDWORD(self.f)
  56.        
  57.         self.head['FixupSize'] = FileReadDWORD(self.f)
  58.         self.head['FixupCksum'] = FileReadDWORD(self.f)
  59.        
  60.         self.head['LoaderSize'] = FileReadDWORD(self.f)
  61.         self.head['LoaderCksum'] = FileReadDWORD(self.f)
  62.  
  63.         self.head['ObjectOff'] = FileReadDWORD(self.f)+off
  64.         self.head['ObjectCount'] = FileReadDWORD(self.f)
  65.         self.head['ObjectPage_off'] = FileReadDWORD(self.f)+off
  66.         self.head['ObjectIter_off'] = FileReadDWORD(self.f)
  67.        
  68.         self.head['ResourceOff'] = FileReadDWORD(self.f)+off
  69.         self.head['ResourceCount'] = FileReadDWORD(self.f)
  70.         self.head['ResNameOff'] = FileReadDWORD(self.f)+off
  71.         self.head['EntryOff'] = FileReadDWORD(self.f)+off
  72.         self.head['ModDirectiveOff'] = FileReadDWORD(self.f)+off
  73.         self.head['ModDirectiveCount'] = FileReadDWORD(self.f)
  74.         self.head['FixupPageOff'] = FileReadDWORD(self.f)+off
  75.         self.head['FixupRecordsoff'] = FileReadDWORD(self.f)+off
  76.         self.head['ImportModuleOff'] = FileReadDWORD(self.f)+off
  77.         self.head['ImportModuleCount'] = FileReadDWORD(self.f)
  78.         self.head['ImportProcOff'] = FileReadDWORD(self.f)+off
  79.         self.head['cksum_off'] = FileReadDWORD(self.f)+off
  80.         self.head['DataPageOff'] = FileReadDWORD(self.f)
  81.         self.head['DataPageCount'] = FileReadDWORD(self.f)
  82.    
  83.     def ParseObjectTable(self):
  84.         self.f.seek(self.head['ObjectOff'])
  85.         self.objects = []
  86.         for i in range(self.head['ObjectCount']):
  87.             obj = {}
  88.             obj['size'] = FileReadDWORD(self.f)
  89.             obj['VAddr'] = FileReadDWORD(self.f)
  90.             obj['flags'] = FileReadDWORD(self.f)
  91.             #to simplify handling of IDx rebase to 0based array idx
  92.             obj['PT_idx'] = FileReadDWORD(self.f)-1
  93.             obj['PT_count'] = FileReadDWORD(self.f)
  94.             obj['PAddr'] = le.head['DataPageOff'] \
  95.                          + obj['PT_idx']*self.head['PageSize']
  96.             obj['Reserved'] = FileReadDWORD(self.f)
  97.             self.objects.append(obj)
  98.            
  99.     def Parse(self):
  100.         self.ParseHead()
  101.         self.ParseObjectTable()
  102.        
  103.         self.f.seek(self.head['FixupPageOff'])
  104.         self.fixups['ByPage'] = []
  105.         for i in range(self.head['PageCount']):
  106.             self.fixups['ByPage'].append(FileReadDWORD(self.f)+self.head['FixupRecordsoff'])
  107.        
  108.            
  109.  
  110. def parseFixupRecords(file, off, count):
  111.     file.seek(off)
  112.     for i in range(count):
  113.         type, flags = struct.unpack('BB', file.read(2))
  114.         print 'type : %d'%type
  115.         print 'flags : %d'%flags
  116.         if type&0x20:
  117.             src, = struct.unpack('B', file.read(1))
  118.         else:
  119.             src, = struct.unpack('<H', file.read(2))
  120.         print 'src off : %04x'%src
  121.         if flags&3 == 0:
  122.             seg, = struct.unpack('B', file.read(1))
  123.             if flags&0x10:
  124.                 tgt, = struct.unpack('<I', file.read(4))
  125.             else:
  126.                 tgt, = struct.unpack('<H', file.read(2))
  127.         print 'target %d:%08x'%(seg, tgt)
  128.    
  129.        
  130. le = LEParse("C:\\Games\\Bethesda Softworks\\Daggerfall\\FALL.EXE")
  131. le.Parse()
  132. target = 0x01809B6
  133.  
  134. print "Data base %08x"%le.head['DataPageOff']
  135. print "segment 3"
  136. print "\t VAddr : %08x"%le.objects[2]['VAddr']
  137. print "\t PAddr : %08x"%le.objects[2]['PAddr']
  138. print "\t page : %d"%le.getPaddrPageId(le.objects[2]['PAddr'])
  139.  
  140. print "target :"
  141. print "\t VAddr : %08x"%target
  142. target_paddr = le.getPhysAddr(target)
  143. print "\t PAddr : %08x"%target_paddr
  144. target_page = le.getPaddrPageId(target_paddr)
  145. print "\t page : %d"%target_page
  146. print "\t fixup records for page :"
  147. print "\t\t start : %08X"%le.fixups['ByPage'][target_page]
  148. print "\t\t end : %08X"%le.fixups['ByPage'][target_page+1]
  149.  
  150. print "Fixups :"
  151. parseFixupRecords(le.f, le.fixups['ByPage'][target_page], 10)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement