From 23f518f39b3759f0db1c05ee55c68aef62d1013f Mon Sep 17 00:00:00 2001 From: gamer147 Date: Thu, 9 Jul 2026 08:54:08 -0400 Subject: [PATCH] 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) --- docs/engine-re.md | 24 ++++++++++++++++--- ...07-09-re-tooling-handler-labels-and-iat.md | 9 +++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/docs/engine-re.md b/docs/engine-re.md index 1cf79e0..80a5581 100644 --- a/docs/engine-re.md +++ b/docs/engine-re.md @@ -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 /imp 3 /dmode 3 /dir ` (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 + /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_/` (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. --- diff --git a/docs/superpowers/plans/2026-07-09-re-tooling-handler-labels-and-iat.md b/docs/superpowers/plans/2026-07-09-re-tooling-handler-labels-and-iat.md index 430db40..d13a847 100644 --- a/docs/superpowers/plans/2026-07-09-re-tooling-handler-labels-and-iat.md +++ b/docs/superpowers/plans/2026-07-09-re-tooling-handler-labels-and-iat.md @@ -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.