re: document pe-sieve IAT failure on packed AGE.EXE; queue Frida import-map
pe-sieve /imp on the running game gave ~17 genuine imports (packer bootstrap + one-per-DLL seed) and 300+ spurious stray-DWORD guesses: the exe ships a zeroed IAT resolved via GetProcAddress, so there is no conventional IAT to rebuild. Do not graft the output. Task B re-scoped to a Frida live import-map (runtime_addr->dll!Func, RVA->name, label the /v2 image); design captured in engine-re.md runbook. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,9 +34,27 @@ Related: `docs/scjump-progression.md` (the SCJUMP decoder that hit this wall), `
|
||||
→ `run_analysis`.
|
||||
- **Load sanity check (AGF-decoder landmark):** at VA `0x474f23`, `CMP word ptr [ESI + 0x4], 0x4d42`
|
||||
(the `BM`/BMP-magic check) confirms the image is correctly based + decoded.
|
||||
- Escalation (unused so far): `bin/pe-sieve32.exe /pid <PID> /imp 3 /dmode 3 /dir <out>` (run from
|
||||
**PowerShell**, not Git Bash — it mangles `/flags`) rebuilds the IAT into a clean PE. Only needed if
|
||||
raw-dump analysis is inadequate; it was fine for reading logic, so we stayed on the raw dump.
|
||||
- IAT reconstruction — **tried, DOESN'T WORK on this binary (2026-07-09):** `bin/pe-sieve32.exe /pid
|
||||
<PID> /imp 3 /dmode 3 /dir build/pe-sieve` (run from **PowerShell**, not Git Bash — it mangles
|
||||
`/flags`) ran fine but the game is packed with a **zeroed IAT** resolved via `GetProcAddress` at load,
|
||||
so there is no conventional import table to rebuild. Of 363 "imports" it emitted, only ~17 are genuine
|
||||
(`in_main:1`): the packer bootstrap (`LoadLibraryA`/`GetProcAddress`/`GetModuleHandleA`/`VirtualAlloc`/
|
||||
`VirtualFree`) + a one-per-DLL seed block at RVA `0x202bfc` (`d3d9.Direct3DCreate9`,
|
||||
`user32.RegisterClassExA`, `gdi32.GetStockObject`, `winmm.timeSetEvent`, `advapi32.RegOpenKeyA`,
|
||||
`shell32.SHGetSpecialFolderPathA`, `oleaut32.Variant*`, `kernel32.RaiseException`, …). The other 300+
|
||||
are stray pointer-shaped DWORDs mis-resolved to "first export at module base" (e.g. `msvcrt._wstrtime_s`
|
||||
30×, `in_main:0`, non-terminated). ⇒ **do not graft pe-sieve output** — grafting the noise would inject
|
||||
wrong import names. The game's hot APIs (`ReadFile`/`CreateFileA`/`timeGetTime`/d3d9 device methods) are
|
||||
`GetProcAddress`-resolved into private pointer tables, invisible to a static IAT scan. Report/dump left
|
||||
at `build/pe-sieve/process_<pid>/` (disposable).
|
||||
|
||||
**→ The right approach (queued, Frida-based; the real "Task B"):** name the dynamically-resolved APIs at
|
||||
their call sites via the LIVE process. (1) Frida-read the loaded modules' export tables → `{runtime_addr
|
||||
→ dll!Func}`; (2) read the engine module's resolved import-pointer storage from the SAME live process,
|
||||
resolve each stored pointer → name, and record **`RVA → name`** (RVAs in the fixed `0x400000` main module
|
||||
are ASLR-stable; only the DLL targets relocate, and we resolve those live); (3) apply the `RVA → name`
|
||||
labels to the `/v2` Ghidra image. All plain-JS Frida reads (no spawn, no patching — anti-tamper-safe).
|
||||
This replaces the pe-sieve step; spec/plan when picked up.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# RE Tooling: Handler Labeling + IAT Reconstruction — Implementation Plan
|
||||
|
||||
> **STATUS (2026-07-09):** **Task A COMPLETE** (committed `97fb1d6` on `feat/re-tooling-handler-labels`) —
|
||||
> whole-image dispatch-handler labeling landed; see the status memory + `docs/engine-re.md` "Materialized +
|
||||
> applied image-wide". **Task B (pe-sieve IAT graft) ABANDONED — the premise fails on this packed binary**
|
||||
> (zeroed IAT, `GetProcAddress`-resolved imports; pe-sieve produced ~17 genuine + 300+ spurious entries).
|
||||
> See `docs/engine-re.md` runbook "IAT reconstruction — tried, DOESN'T WORK". **Task B is re-scoped to a
|
||||
> Frida live import-map** (build `{runtime_addr→dll!Func}` from the live process's module exports, read the
|
||||
> engine's resolved import-pointer storage → `RVA→name`, label the `/v2` image) — that gets its OWN
|
||||
> spec/plan when picked up; the pe-sieve Task B below is retained only as the record of what was tried.
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Eliminate two recurring native-RE taxes — Kelebek VA-drift and unnamed imports — by (A) auto-labeling every opcode dispatch handler in the Ghidra image and (B) grafting reconstructed IAT names onto that same image.
|
||||
|
||||
Reference in New Issue
Block a user