#!/usr/bin/env python3 """ make_pe.py - build a small, valid, benign PE32 test fixture. Stdlib only. The binary imports a handful of Windows APIs that triage heuristics care about (injection, network, anti-debug, persistence) and embeds indicator strings, then simply calls ExitProcess(0). It is deterministic (fixed timestamp) so hashes are stable across runs. Usage: python3 make_pe.py out/invoice_2024.exe """ import struct import sys IMAGE_BASE = 0x400000 SEC_ALIGN, FILE_ALIGN = 0x1000, 0x200 TIMESTAMP = 1704067200 # 2024-01-01T00:00:00Z IMPORTS = { b"KERNEL32.dll": [b"ExitProcess", b"VirtualAllocEx", b"WriteProcessMemory", b"CreateRemoteThread", b"OpenProcess", b"IsDebuggerPresent", b"GetTempPathA", b"CreateProcessA"], b"WININET.dll": [b"InternetOpenA", b"InternetOpenUrlA", b"InternetReadFile"], b"ADVAPI32.dll": [b"RegCreateKeyExA", b"RegSetValueExA"], } ASCII_STRINGS = [ b"http://update-cdn.example.test/gate.php", b"Mozilla/4.0 (compatible; MSIE 6.0; TestUA/1.0)", b"Global\\TestFixtureMutex_9f2a", b"Software\\Microsoft\\Windows\\CurrentVersion\\Run", b"WinUpdate", b"C:\\Users\\Public\\svc.exe", b"203.0.113.5", b"D:\\build\\fixture\\Release\\invoice.pdb", b"BENIGN TEST FIXTURE - this program only calls ExitProcess(0)", ] WIDE_STRINGS = ["cmd.exe /c ping -n 3 127.0.0.1 & del \"%s\"", "\\\\.\\pipe\\testfixture"] def align(n, a): return (n + a - 1) // a * a def build_rdata(rdata_rva): """Return (bytes, iat_rva_of_ExitProcess, import_dir_rva, import_dir_size).""" buf = bytearray() n_dlls = len(IMPORTS) idt_size = 20 * (n_dlls + 1) buf += b"\0" * idt_size # import directory table, patched later thunks = {} # dll -> (ilt_off, iat_off) for dll, funcs in IMPORTS.items(): ilt_off = len(buf); buf += b"\0" * (4 * (len(funcs) + 1)) iat_off = len(buf); buf += b"\0" * (4 * (len(funcs) + 1)) thunks[dll] = (ilt_off, iat_off) name_offs = {} for dll, funcs in IMPORTS.items(): for i, f in enumerate(funcs): if len(buf) % 2: buf += b"\0" name_offs[(dll, f)] = len(buf) buf += struct.pack(" 1 else "invoice_2024.exe" data = build() assert data[:2] == b"MZ" and data[0x80:0x84] == b"PE\0\0" with open(out, "wb") as f: f.write(data) print(f"wrote {out} ({len(data)} bytes)") if __name__ == "__main__": main()