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

22 lines
1.1 KiB
Python

"""Find bounded E8/E9 references to an explicit AMD64 PE code RVA, offline."""
import argparse,re,struct
from pathlib import Path
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--binary',type=Path,required=True)
p.add_argument('--target',type=lambda x:int(x,0),action='append',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' or struct.unpack_from('<H',b,pe+4)[0]!=0x8664:raise ValueError('Expected AMD64 PE')
n=struct.unpack_from('<H',b,pe+6)[0];optional=struct.unpack_from('<H',b,pe+20)[0];found={target:[] for target in a.target}
for i in range(n):
off=pe+24+optional+i*40
virtual,rva,size,raw=struct.unpack_from('<IIII',b,off+8)
if not struct.unpack_from('<I',b,off+36)[0]&0x20000000:continue
section=b[raw:raw+size]
for m in re.finditer(rb'[\xe8\xe9].{4}',section,re.S):
address=rva+m.start()
target=address+5+struct.unpack_from('<i',m[0],1)[0]
if target in found:found[target].append(address)
for target,refs in found.items():
if len(found)>1:print('target',hex(target))
print('\n'.join(hex(x)for x in refs[:128]));print('references',len(refs))