re(frida): write import-map.json (in-table matches; singletons set aside)
248 module-resident core imports at the RVA 0x16f000 rebuilt IAT (kernel32/user32/gdi32/winmm/advapi32/ole/oleaut/version/ntdll); 29 singletons set aside. Anchors confirmed: ReadFile/CreateFileA/ SetFilePointer + timeGetTime@0x16f3d4 (=DAT_0056f3d4). d3d9/shell32 etc. are heap-resolved (out of dump) — expected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
tools/frida/map_imports_full.py
Normal file
43
tools/frida/map_imports_full.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Task 2 of the frida import-map slice: write build/import-map.json from the live scan.
|
||||
|
||||
Splits the pointer matches into (a) those inside a contiguous in-module import-table run
|
||||
(>= min_run) -> auto-apply, written to build/import-map.json; and (b) isolated singletons
|
||||
(more likely a coincidental DWORD) -> build/import-map-singletons.json for review, NOT
|
||||
auto-applied. Invoked by `map_imports.py` default mode (no --recon).
|
||||
|
||||
See docs/superpowers/plans/2026-07-09-frida-import-map.md (Task 2) and the design spec.
|
||||
"""
|
||||
import json
|
||||
|
||||
from map_imports import BUILD, build_export_index, cluster_runs, collect, scan_pointer_matches
|
||||
|
||||
|
||||
def select_table_matches(matches, runs, min_run=3):
|
||||
"""Split [(rva,val,name)] by whether each RVA falls in a contiguous run of >= min_run.
|
||||
|
||||
Returns (table, singles) as {hex_rva: 'dll!func'} dicts.
|
||||
"""
|
||||
run_rvas = set()
|
||||
for start, count in runs:
|
||||
if count >= min_run:
|
||||
run_rvas.update(start + i * 4 for i in range(count))
|
||||
table = {hex(r): n for r, _, n in matches if r in run_rvas}
|
||||
singles = {hex(r): n for r, _, n in matches if r not in run_rvas}
|
||||
return table, singles
|
||||
|
||||
|
||||
def build():
|
||||
exports, base, mem = collect()
|
||||
idx = build_export_index(exports)
|
||||
matches = scan_pointer_matches(mem, base, idx)
|
||||
runs = cluster_runs([r for r, _, _ in matches])
|
||||
table, singles = select_table_matches(matches, runs)
|
||||
(BUILD / "import-map.json").write_text(json.dumps(table, indent=2) + "\n", encoding="utf-8")
|
||||
(BUILD / "import-map-singletons.json").write_text(json.dumps(singles, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"wrote {len(table)} table imports -> build/import-map.json; "
|
||||
f"{len(singles)} singletons -> build/import-map-singletons.json (review, not applied)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
build()
|
||||
@@ -58,12 +58,22 @@ def test_cluster_runs_groups_contiguous():
|
||||
"cluster groups contiguous aligned runs, isolates singleton")
|
||||
|
||||
|
||||
def test_select_table_matches_splits_runs_from_singletons():
|
||||
from map_imports_full import select_table_matches
|
||||
matches = [(0x100, 0, "a!f"), (0x104, 0, "b!g"), (0x108, 0, "c!h"), (0x200, 0, "d!i")]
|
||||
runs = [(0x100, 3), (0x200, 1)]
|
||||
table, singles = select_table_matches(matches, runs, min_run=3)
|
||||
check(set(table) == {"0x100", "0x104", "0x108"} and set(singles) == {"0x200"},
|
||||
"run members auto-apply; singleton set aside")
|
||||
|
||||
|
||||
def main():
|
||||
test_export_index_canonicalizes()
|
||||
test_export_index_first_name_wins_and_skips_zero()
|
||||
test_scan_matches_little_endian_aligned()
|
||||
test_scan_ignores_unaligned()
|
||||
test_cluster_runs_groups_contiguous()
|
||||
test_select_table_matches_splits_runs_from_singletons()
|
||||
print("FAILURES:", len(FAILS))
|
||||
return 1 if FAILS else 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user