Complete workflow
Execute in order; for each step's artifact (target/input surface conclusion, fuzz run directory, crash sample, localization evidence) record the evidence path + sha256 (for the evidence preservation method see [[re-triage]] (capability:triage)), for the report to reference.
- Target and input surface identification — first figure out "what to fuzz, where the input enters from" (see Pitfall 1):
- Target form: local file parsing (images/compression/documents/custom formats), network service (listening port receiving packets), library function (parsing API being called), command-line tool (argv/stdin)
- Input surface: fuzz input channel (file / file content / network packet / stdin / argv) and parsing entry function
- Initial reconnaissance:
file/strings/ entropy / checksec ([[re-triage]] (capability:triage)); statically locate the parsing entry ([[re-binary-core]] (capability:decompilation、debugging、memory-dump、elf-parser、pe-parser、macho-parser) foundation, [[re-ghidra]] (capability:decompilation、debugging) decompile to find the main processing function) - Decision: fuzz engine and instrumentation method (source available for instrumentation / source unavailable QEMU mode), see "Decision Tree"
- Coverage-guided fuzzing → [[re-fuzzing]] (capability:
fuzzing) — instrumentation + corpus + get it running:- Source available: AFL++ compiler wrapper + ASAN build (
afl-clang-fast -fsanitize=address); write a harness for library functions; no source-Q(QEMU mode) - Initialize corpus (minimal valid samples,
afl-cmindeduplication),afl-fuzzrun multiple instances (-M main/-S secondary) - Coverage monitoring (afl-cov / afl-whatsup), observe paths growth; add dictionaries / structured input to speed up
- Source available: AFL++ compiler wrapper + ASAN build (
- Crash analysis → [[re-crash-triage]] (capability:
debugging) — handle a crash immediately when it appears:- Deterministic reproduction (rerunning the same input must crash); ASAN report interpretation (heap overflow / out-of-bounds / UAF / double-free)
- Input minimization (afl-tmin / afl-cmin) → minimal PoC
- For non-deterministic crashes use rr to record and replay
- Reverse engineering localization ([[re-binary-core]] (capability:
decompilation、debugging、memory-dump、elf-parser、pe-parser、macho-parser) foundation) — translate the crash into the vulnerability root cause:- [[re-triage]] (capability:
triage): crash input sha256 evidence preservation + target baseline record - [[re-ghidra]] (capability:
decompilation、debugging; or [[re-ida]] (capability:decompilation、debugging) / [[re-radare2]] (capability:decompilation)): for unsymbolized frames in the gdb backtrace, fill in with decompilation (see Pitfall 5); locate the crash function and the input data flow - Confirm: which piece of logic the out-of-bounds/dangling occurs in, whether the input is controllable, whether the path is actually reachable (see Pitfall 3)
- Crash core (process already dead / core dump already exists) → [[re-memdump]] (capability:
memory-dump) analysis
- [[re-triage]] (capability:
- Report:
- Record: crash type, reproduction command, minimal PoC (file + sha256), root cause (function/line/offset), reachability analysis, impact (out-of-bounds read/write, RCE/DoS), fix recommendations
- Output: PoC / crash signature can go into [[re-ioc]] (capabilities:
threat-intel)
When to use which atomic skill (selection tree)
Branch by target input form / current state:
- Local file parsing(input is a file: image/compression/document/custom format parser) → [[re-fuzzing]] (capabilities:
fuzzing) use AFL++(source instrumentation + ASAN; no source-QQEMU mode) - Library functions(target is a library API, such as libpng's
png_read_*, custom parser functions) → [[re-fuzzing]] (capabilities:fuzzing) use libFuzzer(-fsanitize=fuzzer,address+ fuzz target harness), or AFL++ persistent mode harness - Network services(listening port, protocol parsing) → network fuzz: [[re-netcap]] (capabilities:
network-capture) capture real traffic as seeds, write a harness to replay and feed the parsing function (see [[re-fuzzing]] (capabilities:fuzzing) pitfall 5); what is fuzzed is the parser, not the network stack - Existing crash / crash input(no need to rerun fuzz) → directly [[re-crash-triage]] (capabilities:
debugging): deterministic reproduction → minimization → localization - Crash localized, need to read function logic → [[re-binary-core]] (capabilities:
decompilation、debugging、memory-dump、elf-parser、pe-parser、macho-parser) foundation ([[re-ghidra]] (capabilities:decompilation、debugging) / [[re-ida]] (capabilities:decompilation、debugging) / [[re-radare2]] (capabilities:decompilation)) - Crash is a core file(process already dead) → [[re-memdump]] (capabilities:
memory-dump) analyze the core, then reverse as needed - Target has no input parsing (pure algorithm/pure logic) → fuzz is not suitable, symbolic execution is better ([[re-angr]] (capabilities:
symbolic-execution) / [[re-z3]] (capabilities:constraint-solving))
Cross-domain combination
- Foundation [[re-binary-core]]: step 4 reverse localization to pin down the call ([[re-triage]] initial survey and evidence preservation / [[re-ghidra]] decompilation localization / [[re-ida]] / [[re-radare2]]); the static parts of this gateway's ①-⑤ all rest on the foundation skills (spec 2.4: crash sample localization = re-vuln → re-binary-core + re-memdump)
- Crash core → [[re-memdump]]: when the process is already dead / a core dump already exists, crash sample analysis goes through memory dump and core extraction
- CTF pwn → [[re-ctf]]: pwn competition challenges' fuzzing / crash analysis is handed to this gateway; challenge binaries are equally applicable to this gateway's workflow
- Dynamic execution sandbox: both fuzzing / crash reproduction are dynamic execution, by default run inside [[re-sandbox]] ([[re-analyze/platform-tips]] highest principle)
- Network targets: [[re-netcap]] capture packets as seed corpus and to confirm the input surface
- Entry dispatch: this gateway is dispatched by [[re-analyze]] according to trigger words (vulnerability discovery / fuzz / crash analysis), triage is already explicitly wired
- Output: PoC hash / crash signature / vulnerability fingerprint can go into [[re-ioc]]
Common pitfalls and traps
- Start running before the target/input surface is properly identified: Symptom—fuzzing runs for days with zero crashes, or crashes are all in unrelated code; Cause—the input channel/parsing entry point is wrong (e.g., fuzzing a network program as if it were a file parser, so the core parsing logic is never covered); Remedy—Step 1: statically confirm the parsing entry point first ([[re-ghidra]] decompile to find the main handling function), have the harness directly connect to the parsing function, and use [[re-netcap]] to capture real traffic to verify the input surface
- Crashes ≠ vulnerabilities: Symptom—the out-of-bounds/UAF reported by ASAN is in a dead code branch, or the crash is introduced by the harness itself; Cause—the ability of the fuzzer to trigger it does not mean it is actually reachable or exploitable; Remedy—[[re-crash-triage]] Step 4: gdb backtrace + [[re-binary-core]] decompilation to confirm the crash path is actually reachable and the input is controllable; distinguish harness bugs from target bugs
- No instrumentation, no coverage: Symptom—execs skyrocket but paths do not move and new crashes never appear; Cause—the target is not instrumented (release binary, wrong parameters fuzzed an unrelated program); Remedy—[[re-fuzzing]] uses
afl-showmapto verify coverage changes; if there is no source code, switch to-QQEMU mode - Missing crash deduplication: Symptom—tens of thousands of crash files for the same bug flood the analysis; Cause—every mutated input is saved to disk and not distinguished by crash point; Remedy—afl-tmin minimization + merge by ASAN type/backtrace stack (see [[re-crash-triage]])
- Missing symbols make localization difficult: Symptom—gdb
btis all??; Cause—stripped symbols/static linking; Remedy—record the module base address and offset, and use [[re-ghidra]] decompilation to recover frames ([[re-binary-core]] foundation)