ToolboxToolbox/pefbinary.py

89 lines
2.6 KiB
Python
Executable File

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))