Source code for PE.carve

'''
'''
import sys
import struct

from cStringIO import StringIO
from itertools import izip, cycle

import PE
 
[docs]def xorbytes(data, key): return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
[docs]def xorstatic(data, i): return ''.join( chr( ord(c) ^ i ) for c in data )
mz_xor = [ (xorstatic('MZ', i), xorstatic('PE', i), i) for i in xrange(256) ]
[docs]def carve(pbytes, offset=0): ''' Return a list of (offset, size, xor) tuples of embedded PEs ''' pblen = len(pbytes) todo = [ (pbytes.find(mzx, offset), mzx, pex, i) for mzx,pex,i in mz_xor ] todo = [ (off, mzx, pex, i) for (off,mzx,pex,i) in todo if off != -1 ] while len(todo): off, mzx, pex, i = todo.pop() # The MZ header has one field we will check # e_lfanew is at 0x3c e_lfanew = off + 0x3c if pblen < (e_lfanew + 4): continue newoff = struct.unpack('<I', xorstatic( pbytes[e_lfanew : e_lfanew + 4], i))[0] peoff = off + newoff if pblen < (peoff + 2): continue if pbytes[ peoff : peoff + 2 ] == pex: yield (off, i) nextres = pbytes.find(mzx, off+1) if nextres != -1: todo.append( (nextres, mzx, pex, i) )
[docs]class CarvedPE(PE.PE): def __init__(self, fbytes, offset, xkey): self.carved_offset = offset self.fbytes = fbytes self.xorkey = xkey PE.PE.__init__(self, StringIO())
[docs] def readAtOffset(self, offset, size): offset += self.carved_offset return xorbytes(self.fbytes[offset:offset+size], self.xorkey)
[docs] def getFileSize(self): ret = 0 for sec in self.getSections(): ret = max(ret, sec.PointerToRawData + sec.SizeOfRawData) return ret
if __name__ == '__main__': fbytes = file(sys.argv[1], 'rb').read() for offset, i in carve(fbytes): print 'OFFSET: %d (xor: %d)' % (offset, i) p = CarvedPE(fbytes, offset, chr(i)) print 'SIZE',p.getFileSize()