Skip to content

IAT Destruction & Rebuild

Packers wipe or redirect the Import Address Table and resolve APIs through a custom thunk stub at runtime, so a static dump has no usable imports and must be reconstructed before analysis.

The Import Address Table (IAT) is the array of function pointers the Windows loader fills so a program can call kernel32!CreateFileW and friends. Packers destroy that visibility: after the original code is unpacked they either zero the IAT and re-resolve each API on demand, or point every IAT slot at a custom resolver thunk that looks up the real function only when called. A memory dump taken at the original entry point therefore contains the right code but a broken, unreadable import table, and the dump will not load or analyse correctly until imports are rebuilt.

How it works

Each call site is redirected through a stub that hides the real target. A common pattern stores an obfuscated API identifier and resolves it lazily:

asm
; original:  call dword ptr [IAT_CreateFileW]
; packed:    call resolver_thunk_0042

resolver_thunk_0042:
    push  0xA1B2C3D4         ; obfuscated (dll-hash << 16 | api-hash)
    call  resolve_api        ; walk PEB -> module list -> export table
    jmp   eax                ; tail-jump into the resolved API

resolve_api:                 ; returns the real function address in eax
    ; ... hash each export name, compare, return match ...
    ret

Because the IAT slot now holds a pointer into the packer's own memory (or zero), tools that read the on-disk import directory see nothing usable.

Detection & bypass

  • Static — The Import Directory is tiny, empty, or points outside any named section. PE-bear shows a near-empty imports tab and an IAT RVA that lands in a high-entropy region. A repeated call/jmp eax pattern preceded by a push <constant> is the resolver thunk fingerprint.
  • Dynamic — Run to the OEP (ESP trick, or break after the tail jump out of the stub), then dump the process image while it is fully unpacked. Trace one resolver call to confirm whether slots are filled in place or replaced by thunks; set a breakpoint inside resolve_api to enumerate which APIs are requested.
  • Rebuild — Point Scylla (or ImpREC) at the running process, set the OEP, and run IAT Autosearch followed by Get Imports. Scylla walks the IAT, resolves each pointer back to a module!export, and writes a fresh import table into the dump (Fix Dump). For thunk-redirected IATs, let the resolver run once per slot so the pointers are concrete, then autosearch; otherwise trace the resolver to map each thunk to its API manually.
  • Tools — x64dbg with the Scylla plugin (OEP dump + IAT rebuild), ImpREC (legacy autosearch and thunk repair), and PE-bear (inspecting and validating the rebuilt import directory).
Votes

Comments(0)