Complete Workflow
- Environment: probing + preferences (if not entering via [[re-analyze]], do that first, read
RE_*session variables) - Initial survey: [[re-triage]] (capability:
triage) —— file/hash/entropy/strings, confirm file type and architecture - Format parsing: by type, use [[re-format-pe]] (capability:
pe-parser) / [[re-format-elf]] (capability:elf-parser) / [[re-format-macho]] (capability:macho-parser) - Imports/exports: [[re-imports]] (capability:
pe-parser、elf-parser) —— library fingerprints, IAT/symbols, identify what is linked - Decompilation: by
RE_DECOMPILER, use [[re-ghidra]] (capability:decompilation、debugging) / [[re-ida]] (capability:decompilation、debugging) / [[re-radare2]] (capability:decompilation; if not installed → install per the corresponding skill's "Tool Preparation"; Ghidra recommended by default) - Dynamic (on demand, sandbox by default): [[re-gdb]] (capability:
debugging) / [[re-x64dbg]] (capability:debugging) / [[re-lldb]] (capability:debugging; by OS) + [[re-tracing]] (capability:tracing) + [[re-memdump]] (capability:memory-dump) - Output: conclusions / report (by
RE_REPORT)
Analysis Methodology
General analysis methodology applicable to this gateway (user practical experience), pitfalls and traps of each skill reference this.
Entry Analysis
- R1 Entry point ≠ main: EP is the initialization entry, reaching main only through CRT/TLS/loader
- R2 String cross-references take priority over function guessing: key strings → XREF backtracking
- R3 No strings ≠ no logic: encoding/hashing/runtime concatenation/decryption generation, trace usage points
- R4 Abnormal function boundaries → check for decompilation artifacts: hand-written assembly/obfuscation/tail calls/no frame pointer, do not fully trust the decompiler
Call Analysis
- R5 Few calls ≠ simple logic: function pointers/vtables/callbacks/switch jump tables, indirect calls
- R6 Abnormal indirect calls → investigate the source of the function pointer: trace the source of the target address in registers/memory
- R7 Virtual function analysis → find the vtable first: object pointer → vptr → vtable → function set
Memory and Data Structures
- R8 Struct identification: do not only look at field accesses: combine initialization location/lifecycle/multiple usages
- R9 malloc/free track object lifecycle: creation point and release point define the meaning
- R10 Global variables: look for references first, not definitions: the global area has high noise
API/Behavior
- R11 API calls are only results, not logic: analyze parameter sources and call context
- R12 Exception handling may be control flow: SEH/C++ exception/signal handler carry out normal jumps
- R13 The syscall layer is more trustworthy than APIs: when hooking/wrapping/replacing, trace down to the syscall
Obfuscation Analysis
- R14 Control flow flattening → look at the state variable: dispatcher + state variable + case blocks
- R15 High proportion of junk code → do not analyze line by line: find external influence/data flow/real calls
- R16 opaque predicate → verify whether the condition is constant: always-true/always-false determination
Dynamic debugging
- R17 Breakpoint failure → not necessarily not executed: self-modifying code/memory remapping/exception mechanism/anti-debugging bypass
- R18 Single-step exception → check for anti-debugging: trap flag/timing detection/exception handling
- R19 Seeing decrypted data → save it immediately: the next stage may clear it
PE/ELF in depth
- R20 Memory layout is more important than file layout: the mapping state after the loader is the runtime truth
- R21 section names are untrustworthy: look at permissions/entropy/content
- R22 Relocation information affects dump: when addresses are inconsistent, check relocation first
Intelligence and initial reconnaissance
- R23 The three tables first: file (format) → partition entropy (code/data/ciphertext distribution) → strings (both wide and narrow characters must be scanned, packers will convert to wide strings) — complete these three steps before any deep dive, to avoid 80% of directional errors
- R24 Entropy must be sampled by partition: overall 4KB entropy 7.9 ≠ all ciphertext — the entry area 64B entropy 5.6 may be real code; use 64B/1KB window scanning to find plaintext/ciphertext boundaries;high entropy ≠ encryption: it may be compression, VMProtect mutation, or data; before judging encryption, first rule out compression and obfuscation
- R25 The two-sided nature of the import table: (a) an extremely small import table (a few functions) = signal of a packer/dynamic resolution; (b) dead imports: the IAT has stubs but .text has zero call sites = LoadLibrary+GetProcAddress dynamic loading, static import conclusions are invalid (c) import table numbers ≠ API surface: a COM interface (d3d11, etc.) with 1 import hides hundreds of vtable methods behind it; the real call surface is always outside the import table
- R26 Build paths/log function names are the strongest intelligence:
G:\BuildAgent\...\Graphics_Renderer_D3D11.cppleaks the entire renderer architecture;Renderer::CreateAdapter()restore the initialization chain — prioritize over function guessing
Disassembly methods
- R27 Linear disassembly will inevitably drift: a PE code section with embedded jump tables, sequentially decoded from the section header to the middle section, is all garbage; the immunization scheme = byte-by-byte pattern scanning(only recognize FF15/FF25 call/jmp [rip] and 8B/8D mov/lea [rip] patterns, calculate the target address from the raw bytes
next_ip + disp32, do not use the decoder's displacement field) - R28 If the decompiler hangs, decisively downgrade: performing function analysis on ciphertext/obfuscated regions as code will explode exponentially (4 cores take 8 minutes) — limit the analysis scope (-analysisTimeoutPerFile) or switch to a hand-written decoder, do not wait
- R29 Cross-validate tool blind spots: objdump silently skips abnormal section flags (MEM_NOT_PAGED), iced-x86 returns non-raw values for RIP-relative displacement, readelf errors out and stops on forged headers — every tool has blind spots; if two independent tools parse the same data, any inconsistency means there is a problem
- R30 Entry bytes determine authenticity:
e8 xx xx xx xx(call)+0f 05(syscall) looks like code and could also be random coincidence—sequential decoding yields 30 entries, and iffcom/int 88h/ret farclass instructions appear, it is false
Verification
- R31 Static conclusions must be dynamically corroborated: "it runs" != "it is correct" (relocation correctness can only be proven by reading memory slots at runtime); byte-by-byte verification can only prove "the implementation conforms to the specification," not that "the specification is correct"—the dynamic side reads slots from live memory and compares them with the values stored in the file
- R32 Two independent tools parse the same data: addend against the values stored in the file, symbol addresses against nm output, RVA against objdump—any inconsistency means there is a problem; do not trust the output of a single tool
- R33 Dynamic minimally invasive: DLL hijacking proxy (recording the call sequence) > debugger > instrumentation framework; if the target binary can be left unmodified, do not modify it;dynamic analysis always in a sandbox(firejail/bwrap + no network + disposable environment)
Knowledge acquisition
- R34 Check format offsets against specifications, not from memory: field-type knowledge such as the PE32+ data directory at oh+112 (+96 is SizeOfHeapCommit), TEB offsets, etc.—relying on memory is bound to be wrong; the MS specification/ELF gABI is the only authority (for specific values see the domain experience in [[re-format-pe]]/[[re-format-elf]])
- R35 Open-source implementations are the second authority: for TEB layout check Wine winnt.h, for system call semantics check the ReactOS source code—more reliable than blogs, and can be cross-validated
When to use which atomic skill (decision tree)
- Just got a file, do not know what it is → [[re-triage]] (capability:
triage) - Known PE / ELF / Mach-O, need to understand the structure → corresponding format skill
- Need to know which libraries/APIs the program links against → [[re-imports]] (capability:
pe-parser、elf-parser) - Need to understand function logic → one of four decompilers ([[re-ghidra]] (capability:
decompilation、debugging) default; [[re-ida]] (capability:decompilation、debugging) / [[re-radare2]] (capability:decompilation) / [[re-binaryninja]] (capability:decompilation)) - Need to observe runtime behavior and set breakpoints → choose a debugger by OS (Linux [[re-gdb]] (capability:
debugging), Windows [[re-x64dbg]] (capability:debugging) / [[re-windbg]] (capability:debugging), macOS [[re-lldb]] (capability:debugging)) - Need to trace system calls/function calls → [[re-tracing]] (capability:
tracing) - Need to read/dump process memory → [[re-memdump]] (capability:
memory-dump; dumping first by default, see [[re-analyze/platform-tips]]) - Target is a driver/kernel module/rootkit → [[re-kernel]] (capability:
kernel-analysis; with [[re-windbg]] (capability:debugging) kernel debugging) - Target is a hypervisor/VMM/virtualization-detection related → [[re-hypervisor]] (capability:
hypervisor-analysis;VT-x/SVM、VMCS/EPT) - Target is an anti-cheat component (EAC/BattlEye driver, memory verification) → [[re-anti-cheat]] (capability:
kernel-analysis; driver analysis + kernel debugging, note the authorization boundary) - Target has no environment/unpacking assistance and needs emulated execution → [[re-emulation]] (capability:
emulation) - Target is shellcode (a raw code blob with no file format header: extraction/decoding loop/emulated execution) → [[re-shellcode]] (capability:
shellcode-analysis) - Target is a game (Unity/Unreal, CE memory modification) → [[re-game]] (capability:
game-analysis) - Target is a Go binary (language-specific: symbols/string table/goroutine) → [[re-go]] (capability:
lang-runtime-analysis) - Target is a Rust binary (language specialism: symbol demangling/generic expansion/ownership) → [[re-rust]] (capabilities:
lang-runtime-analysis) - Target is C++ (RTTI/exception-table heavy) → [[re-cpp-abi]] (capabilities:
decompilation; RTTI/vtable/exception unwinding) - Target is a Swift artifact ($s mangling characteristics) → [[re-swift]] (capabilities:
lang-runtime-analysis; mangling/witness table/closure capture) - Target is a Zig artifact (no RTTI/exception tables, panic function characteristics) → [[re-zig]] (capabilities:
lang-runtime-analysis; comptime/error paths) - Target is a Nim artifact (NimMain/NimString characteristics) → [[re-nim]] (capabilities:
lang-runtime-analysis; runtime/string structures) - Target is a Haskell/OCaml artifact (GHC RTS/OCaml block characteristics) → [[re-fp-runtime]] (capabilities:
lang-runtime-analysis; closures/data flow) - Patch/N-day comparison (before-after fix/variant correlation) → [[re-variant]] (capabilities:
binary-diffing; function matching/patch diff) - Need to write Ghidra/IDA scripts or plugins (batch annotation/decryption loops/custom format parsing, script → plugin engineering) → [[re-plugin-dev]] (capabilities:
plugin-development) - Suspect packing → switch to [[re-anti-analysis]] (capabilities:
unpack、deobfuscation、evasion-analysis)
Cross-domain combinations
- [[re-mobile]]: mobile app native .so library analysis → this gateway [[re-format-elf]] + [[re-ghidra]] (for the specialism see [[re-android-native]])
- [[re-hypervisor]] / [[re-anti-cheat]]: reverse engineering of hypervisors and anti-cheat drivers is built on this gateway's skills ([[re-kernel]] / [[re-windbg]] kernel debugging)
- [[re-ctf]]: CTF reversing challenges → this gateway's skills as the foundation
- [[re-anti-analysis]]: statically discovered obfuscation/packing → move into the unpacking domain
- [[re-shellcode]]: shellcode payload specialism analysis (extraction/decoding/emulated execution) → use this gateway as the decompilation foundation ([[re-radare2]] / [[re-ghidra]])
- This gateway's skills are referenced by the deep reverse engineering phase of [[re-malware]]
Common pitfalls and traps
- Memory detected as <4GB but Ghidra still chosen → suggest [[re-radare2]]
- strings output is interfered with by encryption/compression → use entropy values (re-triage) to determine whether to unpack first
- Directly read
/proc/<pid>/memmust first check maps (see [[re-analyze/platform-tips]])
Unknown formats and emulated execution
- Unknown/heavily modified formats: let the target's own parser answer, don't do manual archaeology: Symptom—manually writing parsers for heavily modified bytecode/resource/protocol formats, repeatedly misaligning; Cause—the format has been modified by the target vendor, and public documentation is out of step with the implementation; Countermeasure—find a component within the target that can load the format (built-in VM, parsing library), and use it to "compile/load/export" to produce artifacts of the same origin (e.g., use the target's built-in Lua VM to compile its bytecode), reducing format compatibility issues to zero—the generalization of "if it runs, don't reverse it"
- When emulating target functions, first distinguish dependencies: Symptom—calling functions in the emulator reports unmapped memory/out-of-bounds; Cause—the function references the module's static area/global state, exceeding the mapped range; Countermeasure—preferentially choose pure computation functions with no global dependencies (static getters, packers/unpackers) as verification targets; for functions that genuinely need globals, fill in the memory mappings according to the referenced addresses before calling
- Patch-script-style resources: use the target's compilation pipeline to produce isomorphic artifacts: Symptom—bytecode or resources produced by a third-party compiler/bundler fail to load or behave abnormally in the target; Cause—the compiler version/configuration is inconsistent with the target; Countermeasure—prefer using the target's own compilation/bundling capabilities (exported compilation API,
dumpclass functions) to generate patch artifacts - Always parse byte layouts with scripts + assertions: Symptom—manually calculated hex offsets are completely misaligned (magic number length miscounted, field offset off by 1); Cause—eyeballing offsets is unreliable; Countermeasure—use a script to parse the header/fields and add assertion checks; when the parser output contradicts the tool, first verify whether the tool itself is working as expected (aliases/wrappers/parameters may change behavior, e.g., a grep wrapper skips binary content)
- Indirect jump-flattened main function: Symptom—the decompiler only recognizes the CFG at the front of the function and breaks off at the dispatcher; Cause—indirect BR jump table (control-flow flattening); Countermeasure—enumerate the real basic blocks according to the jump table formula
target = (table_entry + fixed_delta), without relying on the default CFG; when the symbol length is much larger than the CFG recognition length, prioritize checking the BR/BLR indirect tables - Per-function XOR string decryptor: Symptom—string scanning only reveals a small number of paths; Cause—the text uses an independent cyclic XOR for each string; Countermeasure—identify the layout of "first N bytes key + following M bytes ciphertext", extract the key/output lengths from the decryptor instructions, and statically replay the algorithm (local constant propagation on the flattened block is enough to recover the indirect targets and string source addresses, without needing to fully de-flatten first)
- Safe extraction of self-extracting archives: Symptom—the unpacked target contains malicious paths; Cause—paths inside the archive can be crafted; Countermeasure—validate each member before writing it out (reject absolute paths,
.., links, device nodes), do not execute directly, and do not trust member paths - Locating compressed payloads: Symptom—searching for compressed streams only by magic number misses some; Cause—magic numbers are not unique/are obfuscated; Countermeasure—perform a full decompression test on candidate offsets (valid-stream verification), not just look at the header (Source: reverse-skill field-journal, MIT)