mirror of
https://github.com/elliotnunn/ToolboxToolbox.git
synced 2024-09-24 13:57:03 +00:00
72 lines
1.9 KiB
Python
Executable File
72 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# MacOS apps, extensions etc often keep their PEF (Portable Executable
|
|
# Format) binaries (also called Code Fragments) in the data fork, with
|
|
# offsets in a 'cfrg' resource in the resource fork. This scheme allows
|
|
# the Code Fragment Manager to map that file directly into memory (when VM
|
|
# is on) instead of using the Resource Manager to load it into a Memory
|
|
# Manager heap. But when multiple PEFs are concatenated into the DF,
|
|
# patchpef (https://github.com/elliotnunn/patchpef) cannot be used to
|
|
# mangle them. This script moves the PEFs to 'ndrv' resources (type
|
|
# doesn't really matter) and updates the 'cfrg' accordingly. The original
|
|
# PEFs are zeroed out in the data fork, so if everything has gone
|
|
# correctly, the data fork should be all zeroes.
|
|
|
|
# USAGE: MovePEFsToResources.py SRCFILE DESTFILE
|
|
|
|
from sys import argv
|
|
from subprocess import run
|
|
|
|
oln, fn = argv[1:]
|
|
|
|
run(['rm', '-f', fn])
|
|
run(['cp', oln, fn])
|
|
|
|
with open(fn, 'rb') as f:
|
|
df = bytearray(f.read())
|
|
|
|
run(['zcp', fn+'//cfrg/0', '/tmp/mycfrg'])
|
|
|
|
with open('/tmp/mycfrg', 'rb') as f:
|
|
cfrg = bytearray(f.read())
|
|
|
|
pwpc_locs = []
|
|
start = 0
|
|
while True:
|
|
found = cfrg.find(b'pwpc', start)
|
|
if found == -1: break
|
|
pwpc_locs.append(found)
|
|
start = found + 4
|
|
|
|
for i, p in enumerate(pwpc_locs):
|
|
where = cfrg[p+0x14+3]
|
|
if where != 1: continue
|
|
|
|
rsrcnum = i+13000
|
|
|
|
start = int.from_bytes(cfrg[p+0x18:p+0x1c], 'big')
|
|
size = int.from_bytes(cfrg[p+0x1c:p+0x20], 'big')
|
|
nlen = cfrg[p+0x2a]
|
|
name = cfrg[p+0x2b:p+0x2b+nlen].decode('ascii')
|
|
|
|
pef = df[start:start+size]
|
|
|
|
with open('/tmp/thispef', 'wb') as f:
|
|
f.write(pef)
|
|
|
|
run(['zcp', '/tmp/thispef', '%s//ndrv/%d/%s/sysheap/locked' % (fn, rsrcnum, name)])
|
|
|
|
df[start:start+size] = bytes(size)
|
|
|
|
cfrg[p+0x14+3] = 2
|
|
cfrg[p+0x18:p+0x1c] = b'ndrv'
|
|
cfrg[p+0x1c:p+0x20] = rsrcnum.to_bytes(4, 'big', signed=True)
|
|
|
|
with open(fn, 'wb') as f:
|
|
f.write(df)
|
|
|
|
with open('/tmp/mycfrg', 'wb') as f:
|
|
f.write(cfrg)
|
|
|
|
run(['zcp', '/tmp/mycfrg', fn+'//cfrg/0'])
|