m1n1/proxyclient/macho.py
Hector Martin 7c2dace0b0 chainload.py: Cleanup, move Mach-O loader to macho.py
Signed-off-by: Hector Martin <marcan@marcan.st>
2021-05-01 15:16:02 +09:00

47 lines
1.9 KiB
Python

#!/usr/bin/env python3
from tgtypes import *
from utils import *
class MachO:
def __init__(self, data):
self.data = data
self.obj = MachOFile.parse(data)
self.load_info()
def load_info(self):
self.vmin, self.vmax = (1 << 64), 0
self.entry = None
for cmd in self.obj.cmds:
if cmd.cmd == MachOLoadCmdType.SEGMENT_64:
self.vmin = min(self.vmin, cmd.args.vmaddr)
self.vmax = max(self.vmax, cmd.args.vmaddr + cmd.args.vmsize)
elif cmd.cmd == MachOLoadCmdType.UNIXTHREAD:
self.entry = cmd.args[0].data.pc
def prepare_image(self):
memory_size = self.vmax - self.vmin
image = bytearray(memory_size)
for cmdi, cmd in enumerate(self.obj.cmds):
is_m1n1 = None
if cmd.cmd == MachOLoadCmdType.SEGMENT_64:
if is_m1n1 is None:
is_m1n1 = cmd.args.segname == "_HDR"
dest = cmd.args.vmaddr - self.vmin
end = min(len(self.data), cmd.args.fileoff + cmd.args.filesize)
size = end - cmd.args.fileoff
print(f"LOAD: {cmd.args.segname} {size} bytes from {cmd.args.fileoff:x} to {dest:x}")
image[dest:dest + size] = self.data[cmd.args.fileoff:end]
if cmd.args.vmsize > size:
clearsize = cmd.args.vmsize - size
if cmd.args.segname == "PYLD":
print("SKIP: %d bytes from 0x%x to 0x%x" % (clearsize, dest + size, dest + size + clearsize))
memory_size -= clearsize - 4 # leave a payload end marker
image = image[:memory_size]
else:
print("ZERO: %d bytes from 0x%x to 0x%x" % (clearsize, dest + size, dest + size + clearsize))
image[dest + size:dest + cmd.args.vmsize] = bytes(clearsize)
return image