mirror of
https://github.com/elliotnunn/ToolboxToolbox.git
synced 2024-11-18 08:09:24 +00:00
89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
|
import struct
|
||
|
|
||
|
class PEF:
|
||
|
MAGIC = b'Joy!'
|
||
|
|
||
|
CONT_HEAD_FMT = '>4s4s4s5I2HI'
|
||
|
CONT_HEAD_LEN = struct.calcsize(CONT_HEAD_FMT)
|
||
|
|
||
|
SEC_HEAD_FMT = '>i5I4B'
|
||
|
SEC_HED_LEN = struct.calcsize(SEC_HEAD_FMT)
|
||
|
|
||
|
@classmethod
|
||
|
def read_from(cls, path):
|
||
|
with open(path, 'rb') as f:
|
||
|
return cls(f.read())
|
||
|
|
||
|
def __init__(self, data):
|
||
|
(magic, fourcc, arch, ver,
|
||
|
timestamp, old_def_ver, old_imp_ver, cur_ver,
|
||
|
sec_count, inst_sec_count, reserv) = struct.unpack_from(self.CONT_HEAD_FMT, data)
|
||
|
|
||
|
sec_earliest = len(data)
|
||
|
sec_latest = 0
|
||
|
|
||
|
self.sections = []
|
||
|
self.sectypes = []
|
||
|
self.headeroffsets = []
|
||
|
|
||
|
self.code = None
|
||
|
|
||
|
for i in range(sec_count):
|
||
|
sh_offset = self.CONT_HEAD_LEN + self.SEC_HED_LEN*i
|
||
|
|
||
|
(sectionName, sectionAddress, execSize,
|
||
|
initSize, rawSize, containerOffset,
|
||
|
regionKind, shareKind, alignment, reserved) = struct.unpack_from(self.SEC_HEAD_FMT, data, sh_offset)
|
||
|
|
||
|
the_sec = data[containerOffset : containerOffset + rawSize]
|
||
|
|
||
|
if regionKind == 0 and execSize == initSize == rawSize:
|
||
|
the_sec = bytearray(the_sec)
|
||
|
self.code = the_sec
|
||
|
|
||
|
self.sections.append(the_sec)
|
||
|
self.sectypes.append(regionKind)
|
||
|
self.headeroffsets.append(sh_offset)
|
||
|
|
||
|
sec_earliest = min(sec_earliest, containerOffset)
|
||
|
sec_latest = max(sec_latest, containerOffset + rawSize)
|
||
|
|
||
|
if any(data[sec_latest:]):
|
||
|
print('nonzero trailing data from', hex(sec_latest), 'to', hex(len(data)), ' ... will cause incorrect output')
|
||
|
|
||
|
self.padmult = 1
|
||
|
while len(data) % (self.padmult * 2) == 0:
|
||
|
self.padmult *= 2
|
||
|
|
||
|
self.header = data[:sec_earliest]
|
||
|
|
||
|
def __bytes__(self):
|
||
|
accum = bytearray(self.header)
|
||
|
|
||
|
for i in range(len(self.sections)):
|
||
|
the_sec = self.sections[i]
|
||
|
hoff = self.headeroffsets[i]
|
||
|
|
||
|
while len(accum) % 16:
|
||
|
accum.append(0)
|
||
|
|
||
|
new_off = len(accum)
|
||
|
new_len = len(the_sec)
|
||
|
|
||
|
accum.extend(the_sec)
|
||
|
|
||
|
struct.pack_into('>I', accum, hoff + 20, new_off)
|
||
|
|
||
|
if the_sec is self.code:
|
||
|
for i in range(8, 20, 4):
|
||
|
struct.pack_into('>I', accum, hoff + i, new_len)
|
||
|
|
||
|
while len(accum) % self.padmult != 0:
|
||
|
accum.extend(b'\x00')
|
||
|
|
||
|
return bytes(accum)
|
||
|
|
||
|
def write_to(self, path):
|
||
|
with open(path, 'wb') as f:
|
||
|
f.write(bytes(self))
|