Skip to main content

Module disasm

Module disasm 

Source
Expand description

Recursive-descent function disassembly over real PE bytes (iced-x86).

Given a function entry VA, we decode instructions and follow the function’s intra-function control flow (conditional branches + their fallthrough, unconditional JMP rel) until every reachable path terminates at a RET / interrupt / undecodable byte. Along the way we harvest, purely from the decoded operands, every fact that lets us catch a rebuild hallucination:

  • direct_calls — targets of CALL rel16/rel32 (the call graph proper)
  • tail_calls — JMP rel leaving the body (a tail call into another fn)
  • indirect_calls/indirect_jumps — counts of register/memory dispatch
  • vcall_slots — displacements of CALL/JMP [reg+0xNN] (vtable slots)
  • iat_calls — absolute targets of CALL [0x00a28xxx] (IAT imports)
  • field_offsets — displacements of [reg+0xNN] accesses (struct fields), excluding ESP/EBP (those are stack locals/args)
  • globals — absolute data addresses referenced as [0x00bXXXXX]
  • imm_addrs — in-image immediates (MOV [esi],0x00a7e38c vtable VAs, function pointers, string-literal addresses)

This is structural ground truth: no decompiler in the loop.

Structs§

CallGraph
CallSite
One direct call site with the argument set-up recovered by a short backward scan of its basic block. ecx/edx are the fastcall/thiscall register args (the receiver lands in ecx); stack is the pushed args in source (left-to-right) order. None/empty means “not recovered in-block”.

Enums§

ArgKind
The recovered “kind” of a single call argument, harvested from the instruction that set it up (a register load or a PUSH). Coarse on purpose — only the distinctions a faithful port must preserve, and only those a short local scan can recover without false positives.

Functions§

analyze
Walk the function at entry and return its facts, sourced purely from bytes.
reg_params
Heuristically determine whether the function at addr takes register parameters in ECX / EDX (i.e. is thiscall/fastcall). Scans the entry block for a READ of the register before any write: thiscall reads ECX (the this), fastcall also reads EDX, cdecl/stdcall read neither. Used to align a caller’s recovered register args to the callee’s actual parameters (so a stray EDX in a caller is not mistaken for an argument to a thiscall callee). Conservative: under-detection just means a position is skipped, never a false mismatch.
resolve_thunk
If addr is a one-instruction thunk (JMP target), return target. Callers often invoke a function through such a thunk (a tail-jump stub, or /OPT:ICF-folded forwarder), so the byte call edge points at the thunk, not the real callee — following it one level lets the call-graph check see the true target.