Files
GaCy-GO/tools/find_pe_displacement.py
2026-10-28 18:54:43 +07:00

38 lines
1.2 KiB
Python

"""Offline candidates for a caller-selected 32-bit code displacement.
Results are byte matches, not proven instructions; disassemble their bounded
functions before making any call or interpretation.
"""
import argparse
import struct
from pathlib import Path
p = argparse.ArgumentParser(description=__doc__)
p.add_argument('--binary', type=Path, required=True)
p.add_argument('--value', type=lambda s: int(s, 0), required=True)
a = p.parse_args()
b = a.binary.read_bytes()
pe = struct.unpack_from('<I', b, 0x3c)[0]
if b[:2] != b'MZ' or b[pe:pe+4] != b'PE\0\0':
raise SystemExit('Expected PE image')
count = struct.unpack_from('<H', b, pe+6)[0]
optional = struct.unpack_from('<H', b, pe+20)[0]
needle = struct.pack('<I', a.value)
found = 0
for i in range(count):
at = pe+24+optional+i*40
_, rva, size, raw = struct.unpack_from('<IIII', b, at+8)
if not struct.unpack_from('<I', b, at+36)[0] & 0x20000000:
continue
pos = raw
while True:
pos = b.find(needle, pos, raw+size)
if pos < 0:
break
print(hex(rva+pos-raw))
found += 1
if found >= 128:
raise SystemExit('Candidate bound reached')
pos += 1
print('candidates', found)