chore: initial commit — recon artifacts + design spec + Phase 1 plan
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""Scan a binary blob for MZ markers, validate as PE, dump each as separate file."""
|
||||
import struct, sys, pathlib
|
||||
|
||||
blob_path = pathlib.Path(sys.argv[1])
|
||||
out_dir = pathlib.Path(sys.argv[2])
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
data = blob_path.read_bytes()
|
||||
|
||||
def pe_total_size(buf, off):
|
||||
"""Compute size of PE image at offset using section table."""
|
||||
# MZ at off; PE header offset at off+0x3C
|
||||
if off + 0x40 > len(buf):
|
||||
return None
|
||||
pe_off = struct.unpack_from("<I", buf, off + 0x3C)[0]
|
||||
pe_start = off + pe_off
|
||||
if pe_start + 24 > len(buf) or buf[pe_start:pe_start+4] != b"PE\x00\x00":
|
||||
return None
|
||||
num_sections = struct.unpack_from("<H", buf, pe_start + 6)[0]
|
||||
optional_header_size = struct.unpack_from("<H", buf, pe_start + 20)[0]
|
||||
sections_start = pe_start + 24 + optional_header_size
|
||||
last_end = sections_start + num_sections * 40
|
||||
for i in range(num_sections):
|
||||
s = sections_start + i * 40
|
||||
raw_size = struct.unpack_from("<I", buf, s + 16)[0]
|
||||
raw_off = struct.unpack_from("<I", buf, s + 20)[0]
|
||||
end = off + raw_off + raw_size
|
||||
last_end = max(last_end, end)
|
||||
return last_end - off
|
||||
|
||||
i = 0
|
||||
n = 0
|
||||
while True:
|
||||
j = data.find(b"MZ", i)
|
||||
if j == -1:
|
||||
break
|
||||
sz = pe_total_size(data, j)
|
||||
if sz and 4096 < sz < 5_000_000:
|
||||
out = out_dir / f"plain_{j:08x}.dll"
|
||||
out.write_bytes(data[j:j+sz])
|
||||
print(f"[ok] offset=0x{j:08x} size={sz} -> {out.name}")
|
||||
n += 1
|
||||
i = j + sz
|
||||
else:
|
||||
i = j + 2
|
||||
|
||||
print(f"\nExtracted {n} plain PE files into {out_dir}")
|
||||
Reference in New Issue
Block a user