Binary Exploitation Technique
Decision engine for converting a confirmed memory-corruption primitive into reproducible, mitigation-aware controlled impact. Finding the bug is upstream (reversing-technique, fuzzing-technique, source-review-technique); this technique decides how to weaponize it, which strategy fits the mitigation set, and what proves it. Concrete per-technique recipes live in offensive-ctf/pwn-ctf/references; primitive-construction depth lives in offensive-coding/*-dev. This skill is the methodology that routes between them.
When this technique applies
- You control PC/return target/indirect call target, or can corrupt heap metadata, an object/vtable pointer, or an allocator-linked structure.
- You have an attacker-influenced crash and must separate "crash only" from "exploitable under constraints".
- You need a mitigation-aware plan before investing in a chain.
If you do not yet have a repeatable, attacker-influenced primitive, stay in bug discovery and improve primitive quality first.
Boundary
- Input: a confirmed primitive from
reversing-technique (crash/RE), fuzzing-technique (repro), or source-review-technique.
- Output: a reproducible impact proof; hand a stable session to
post-exploit-technique.
- Not here: CVE/PoC initial access on services/web ->
vuln-exploit-technique; static/dynamic analysis and crash discovery -> reversing-technique; writing the primitive at code depth (allocator internals, gadget policy, FILE structs, shellcode bytes) -> offensive-coding/*-dev; CTF-scoped triage/time-boxing -> offensive-ctf/pwn-ctf.
Primitive qualification
Classify the best proven primitive before selecting a technique.
| Primitive |
Typical source |
Immediate value |
| PC control |
stack overwrite, function pointer, handler confusion |
direct control-flow steering |
| Stack pivot |
constrained return overwrite |
enables chain execution |
| Arbitrary read |
OOB read, type confusion |
leak base addresses/secrets |
| Arbitrary write |
heap poisoning, UAF, index bug |
overwrite function/hook/state |
| Partial overwrite |
off-by-one, truncation |
targeted corruption under constraints |
| Data-only corruption |
auth/config flags, object fields |
privilege/logic impact, no code exec |
Prove one primitive fully before chaining two uncertain ones. Model repeatability: read every branch of a state guard (is_set, initialized, done, idx == fav) — the already-set/else branch often still performs the gated read/write/free, so an apparently one-shot primitive is a repeatable R/W loop. Confirm which branch runs on the second invocation before declaring a path dead.
Reproduction discipline
Fix and record for every stage: binary hash, loader path, dependency/libc versions, argv/input/protocol framing, relevant env vars and cwd, mitigation state, debugger settings. Run a reliability loop before escalation: ~10 runs to validate a candidate primitive, 30+ for final proof. An input-only reproduction is the only proof a primitive works — a gdb set/hand-painted register or memory value is not a delivered primitive, and a cooked-mode PTY mangles 0x0a/0x7f/0x11/0x13 in pointer payloads, so drive local dev over a pipe or the live socket.
Mitigation-aware strategy selection
Inventory protections first (checksec, module headers, loader settings): NX/DEP, ASLR/PIE, stack canary, RELRO, CFG/CET (Windows/hardware), allocator hardening (safe-linking/tcache guards). Then choose a compatible path:
- No executable-memory path -> control-flow reuse (ROP/JOP/SROP/call chain).
- No stable control-flow path -> data-only impact if the objective permits.
- ASLR/PIE unresolved -> prioritize a leak/oracle stage before the final chain.
- Hardware CET/IBT or Windows CFG active -> prefer valid call targets or data-only state corruption; do NOT confuse hardware CET with compiler-emitted userland SafeStack/CFI/software-shadow-stack, which come apart leak-free (route to
safestack-cfi-shadowstack.md).
- Full RELRO + strict CFI -> non-GOT writable targets, loader-assisted resolution, or bounded data-only impact.
- Arbitrary write + libc leak, weak gadget surface -> check an FSOP path (does
exit/fclose/flush run on a path you control?).
Reproduce the remote, not your dev box: kernel, RLIMIT_STACK, and libc differences move mmap adjacencies and mitigation reachability. Do not issue an impossibility/"dead vector" verdict from a dev-box or WSL layout — prove it with a failing live test or a length-sweep against the target.
Leak -> control -> impact ladder
Build in stages; each stage depends only on prior validated primitives.
- Stage A (disclosure/oracle): obtain one dependable anchor (module/libc/PIE base, canary, pointer class, token). Skip only when addresses are already deterministic.
- Stage B (control upgrade): constrained primitive -> robust primitive (constrained write -> arbitrary write; PC control -> pivot -> chain).
- Stage C (impact): minimal, lowest-noise, reversible proof tied to authorized scope.
Per-stage evidence packet: trigger input; observed register/memory transition; expected vs observed; failure mode and fallback. Drive to end-to-end execution early, then fix the latest fault (x/i $pc, rsp & 0xf, faulting field) — alignment (movaps), resolver-vs-call stack parity, and controlled bytes overlapping a lock/pointer/terminator surface only in a full run.
Crash-triage to exploitation handoff
From a raw crash: (1) identify the faulting instruction and operand semantics; (2) verify attacker influence over the operand/target pointer; (3) classify the bug family (overflow/UAF/type confusion/index/format string); (4) confirm the crash is deterministic under the same input; (5) isolate the candidate path and discard non-deterministic branches. If determinism fails, return to primitive improvement before payload engineering.
Route to the right depth
Match the dominant primitive to its canonical concrete recipe and exploit-development home. Load the narrowest that fits; do not re-derive what these already document.
| Family / signal |
Concrete recipes (offensive-ctf/pwn-ctf/references/) |
Exploit-dev design (offensive-coding/) |
| Stack overflow, saved-RIP, partial return, ROP assembly |
overflow.md, rop.md |
stack-exploitation-dev, rop-development-dev |
| Heap: UAF/double-free/overlap, tcache/bins, House-family |
heap.md |
heap-exploitation-dev |
| FILE/FSOP stream corruption, libio dispatch |
heap-fsop.md |
fsop-dev |
| Format-string leak + staged write |
format-string.md |
(target dictates: stack/heap-dev) |
| Shellcode, ORW, seccomp, byte blacklists |
shellcode-filtering.md, sandbox.md |
shellcode-dev |
| RELRO/GOT/PLT, relocations, leakless partial overwrite |
relro-aslr-relocations.md |
— |
| SafeStack + CFI + shadow-stack + canary (composed, leak-free) |
safestack-cfi-shadowstack.md |
stack-exploitation-dev |
Loader _dl_fixup/forged symbols/lazy resolution |
dynamic-linker-resolver-pivots.md |
— |
| Kernel primitives and escalation |
kernel.md |
linux-internals-dev |
| Windows user-mode: SEH/DEP/CFG, PEB-walk |
windows-pwn.md |
stack-exploitation-dev, shellcode-dev, windows-internals-dev |
| Exotic arch (ARM32/ARM64/MIPS/RISC-V) |
exotic-arch.md |
asm-offensive-patterns |
| Same-process multi-stage / allocator drift |
stateful-exploit-campaigns.md |
— |
Quality gates
Mark a capability exploitation-ready only when all hold: the primitive is reproducible input-only; mitigation constraints are documented and accounted for; the chain relies on no hidden manual timing; the impact proof is within authorized scope; required assumptions (versions, flags, services, RLIMIT_STACK) are explicit. Separate exploitability from severity: prove control first, then business impact. Keep a chain ledger and re-apply every proven runtime fact (live offsets, register snapshots, alignment quirks, deterministic pointers) to each later sub-chain.
Anti-patterns
- Treating one lucky run as a stable exploit path, or mixing environment settings between runs and drawing wrong conclusions.
- Declaring a vector "impossible/dead" by deduction — reachability and impossibility are decided by a failing live test, not an argument. If you write "nothing reaches Y" or "X can't work leaklessly", hook Y and every candidate call site and fuzz adversarial inputs first.
- Jumping to payload engineering before a stable primitive; ignoring ABI/alignment; ignoring CFG/CET when choosing chain style.
- Reporting impact without showing primitive evolution, reliability, and boundary conditions.
Resources
Tooling belongs in the tool skills; load them for syntax:
offensive-tools/exploits/pwntools — remote/process interaction, packing, ELF/libc symbols, ROP helper, shellcraft.
offensive-tools/rev/gdb (pwndbg/gef) — register/stack/heap validation, checksec, live snapshots.
offensive-tools/rev/ropgadget, offensive-tools/rev/one-gadget — gadget and constraint-based shell-gadget discovery.
offensive-tools/rev/checksec, offensive-tools/rev/patchelf — mitigation inventory and target-libc reproduction.
Methodology neighbors: reversing-technique (bug discovery/handoff in), fuzzing-technique (repro), vuln-exploit-technique (CVE/service initial access), post-exploit-technique (after impact). For CTF-scoped triage, time-boxing, and the full recipe index, use offensive-ctf/pwn-ctf.
1---2name: binary-exploitation-technique3description: Auth/lab: binary/memory-corruption exploitation methodology — turn a confirmed corruption primitive (stack/heap overflow, UAF, double-free, type confusion, OOB, format string) into reproducible controlled impact. Use when deciding exploitability, qualifying a crash or primitive, selecting a mitigation-aware strategy (NX, ASLR/PIE, canary, RELRO, CET/CFG, safe-linking), planning a staged leak/control/impact chain, or choosing between control-flow (ROP/JOP/SROP/ret2dlresolve) and data-only paths. Routes to concrete pwn recipes and exploit-development skills. Not for CVE/PoC initial access (vuln-exploit-technique), static/dynamic analysis (reversing-technique), or writing primitives at code depth (offensive-coding/*-dev).4license: MIT5---67# Binary Exploitation Technique89Decision engine for converting a **confirmed memory-corruption primitive** into reproducible, mitigation-aware controlled impact. Finding the bug is upstream (`reversing-technique`, `fuzzing-technique`, `source-review-technique`); this technique decides *how* to weaponize it, *which* strategy fits the mitigation set, and *what* proves it. Concrete per-technique recipes live in `offensive-ctf/pwn-ctf/references`; primitive-construction depth lives in `offensive-coding/*-dev`. This skill is the methodology that routes between them.1011## When this technique applies1213- You control PC/return target/indirect call target, or can corrupt heap metadata, an object/vtable pointer, or an allocator-linked structure.14- You have an attacker-influenced crash and must separate "crash only" from "exploitable under constraints".15- You need a mitigation-aware plan before investing in a chain.1617If you do not yet have a repeatable, attacker-influenced primitive, stay in bug discovery and improve primitive quality first.1819## Boundary2021- **Input**: a confirmed primitive from `reversing-technique` (crash/RE), `fuzzing-technique` (repro), or `source-review-technique`.22- **Output**: a reproducible impact proof; hand a stable session to `post-exploit-technique`.23- **Not here**: CVE/PoC initial access on services/web -> `vuln-exploit-technique`; static/dynamic analysis and crash discovery -> `reversing-technique`; writing the primitive at code depth (allocator internals, gadget policy, FILE structs, shellcode bytes) -> `offensive-coding/*-dev`; CTF-scoped triage/time-boxing -> `offensive-ctf/pwn-ctf`.2425## Primitive qualification2627Classify the best **proven** primitive before selecting a technique.2829| Primitive | Typical source | Immediate value |30|---|---|---|31| PC control | stack overwrite, function pointer, handler confusion | direct control-flow steering |32| Stack pivot | constrained return overwrite | enables chain execution |33| Arbitrary read | OOB read, type confusion | leak base addresses/secrets |34| Arbitrary write | heap poisoning, UAF, index bug | overwrite function/hook/state |35| Partial overwrite | off-by-one, truncation | targeted corruption under constraints |36| Data-only corruption | auth/config flags, object fields | privilege/logic impact, no code exec |3738Prove one primitive fully before chaining two uncertain ones. Model **repeatability**: read every branch of a state guard (`is_set`, `initialized`, `done`, `idx == fav`) — the already-set/`else` branch often still performs the gated read/write/free, so an apparently one-shot primitive is a repeatable R/W loop. Confirm which branch runs on the second invocation before declaring a path dead.3940## Reproduction discipline4142Fix and record for every stage: binary hash, loader path, dependency/libc versions, argv/input/protocol framing, relevant env vars and cwd, mitigation state, debugger settings. Run a reliability loop before escalation: ~10 runs to validate a candidate primitive, 30+ for final proof. An **input-only** reproduction is the only proof a primitive works — a `gdb set`/hand-painted register or memory value is not a delivered primitive, and a cooked-mode PTY mangles `0x0a`/`0x7f`/`0x11`/`0x13` in pointer payloads, so drive local dev over a pipe or the live socket.4344## Mitigation-aware strategy selection4546Inventory protections first (`checksec`, module headers, loader settings): NX/DEP, ASLR/PIE, stack canary, RELRO, CFG/CET (Windows/hardware), allocator hardening (safe-linking/tcache guards). Then choose a compatible path:47481. **No executable-memory path** -> control-flow reuse (ROP/JOP/SROP/call chain).492. **No stable control-flow path** -> data-only impact if the objective permits.503. **ASLR/PIE unresolved** -> prioritize a leak/oracle stage before the final chain.514. **Hardware CET/IBT or Windows CFG active** -> prefer valid call targets or data-only state corruption; do NOT confuse hardware CET with compiler-emitted userland SafeStack/CFI/software-shadow-stack, which come apart leak-free (route to `safestack-cfi-shadowstack.md`).525. **Full RELRO + strict CFI** -> non-GOT writable targets, loader-assisted resolution, or bounded data-only impact.536. **Arbitrary write + libc leak, weak gadget surface** -> check an FSOP path (does `exit`/`fclose`/flush run on a path you control?).5455Reproduce the **remote**, not your dev box: kernel, `RLIMIT_STACK`, and libc differences move mmap adjacencies and mitigation reachability. Do not issue an impossibility/"dead vector" verdict from a dev-box or WSL layout — prove it with a failing live test or a length-sweep against the target.5657## Leak -> control -> impact ladder5859Build in stages; each stage depends only on prior **validated** primitives.6061- **Stage A (disclosure/oracle)**: obtain one dependable anchor (module/libc/PIE base, canary, pointer class, token). Skip only when addresses are already deterministic.62- **Stage B (control upgrade)**: constrained primitive -> robust primitive (constrained write -> arbitrary write; PC control -> pivot -> chain).63- **Stage C (impact)**: minimal, lowest-noise, reversible proof tied to authorized scope.6465Per-stage evidence packet: trigger input; observed register/memory transition; expected vs observed; failure mode and fallback. Drive to end-to-end execution early, then fix the *latest* fault (`x/i $pc`, `rsp & 0xf`, faulting field) — alignment (`movaps`), resolver-vs-`call` stack parity, and controlled bytes overlapping a lock/pointer/terminator surface only in a full run.6667## Crash-triage to exploitation handoff6869From a raw crash: (1) identify the faulting instruction and operand semantics; (2) verify attacker influence over the operand/target pointer; (3) classify the bug family (overflow/UAF/type confusion/index/format string); (4) confirm the crash is deterministic under the same input; (5) isolate the candidate path and discard non-deterministic branches. If determinism fails, return to primitive improvement before payload engineering.7071## Route to the right depth7273Match the dominant primitive to its canonical concrete recipe and exploit-development home. Load the narrowest that fits; do not re-derive what these already document.7475| Family / signal | Concrete recipes (`offensive-ctf/pwn-ctf/references/`) | Exploit-dev design (`offensive-coding/`) |76|---|---|---|77| Stack overflow, saved-RIP, partial return, ROP assembly | `overflow.md`, `rop.md` | `stack-exploitation-dev`, `rop-development-dev` |78| Heap: UAF/double-free/overlap, tcache/bins, House-family | `heap.md` | `heap-exploitation-dev` |79| FILE/FSOP stream corruption, libio dispatch | `heap-fsop.md` | `fsop-dev` |80| Format-string leak + staged write | `format-string.md` | (target dictates: stack/heap-dev) |81| Shellcode, ORW, seccomp, byte blacklists | `shellcode-filtering.md`, `sandbox.md` | `shellcode-dev` |82| RELRO/GOT/PLT, relocations, leakless partial overwrite | `relro-aslr-relocations.md` | — |83| SafeStack + CFI + shadow-stack + canary (composed, leak-free) | `safestack-cfi-shadowstack.md` | `stack-exploitation-dev` |84| Loader `_dl_fixup`/forged symbols/lazy resolution | `dynamic-linker-resolver-pivots.md` | — |85| Kernel primitives and escalation | `kernel.md` | `linux-internals-dev` |86| Windows user-mode: SEH/DEP/CFG, PEB-walk | `windows-pwn.md` | `stack-exploitation-dev`, `shellcode-dev`, `windows-internals-dev` |87| Exotic arch (ARM32/ARM64/MIPS/RISC-V) | `exotic-arch.md` | `asm-offensive-patterns` |88| Same-process multi-stage / allocator drift | `stateful-exploit-campaigns.md` | — |8990## Quality gates9192Mark a capability exploitation-ready only when all hold: the primitive is reproducible input-only; mitigation constraints are documented and accounted for; the chain relies on no hidden manual timing; the impact proof is within authorized scope; required assumptions (versions, flags, services, `RLIMIT_STACK`) are explicit. Separate exploitability from severity: prove control first, then business impact. Keep a chain ledger and re-apply every proven runtime fact (live offsets, register snapshots, alignment quirks, deterministic pointers) to each later sub-chain.9394## Anti-patterns9596- Treating one lucky run as a stable exploit path, or mixing environment settings between runs and drawing wrong conclusions.97- Declaring a vector "impossible/dead" by deduction — reachability and impossibility are decided by a failing live test, not an argument. If you write "nothing reaches Y" or "X can't work leaklessly", hook Y and every candidate call site and fuzz adversarial inputs first.98- Jumping to payload engineering before a stable primitive; ignoring ABI/alignment; ignoring CFG/CET when choosing chain style.99- Reporting impact without showing primitive evolution, reliability, and boundary conditions.100101## Resources102103Tooling belongs in the tool skills; load them for syntax:104105- `offensive-tools/exploits/pwntools` — remote/process interaction, packing, ELF/libc symbols, ROP helper, shellcraft.106- `offensive-tools/rev/gdb` (`pwndbg`/`gef`) — register/stack/heap validation, `checksec`, live snapshots.107- `offensive-tools/rev/ropgadget`, `offensive-tools/rev/one-gadget` — gadget and constraint-based shell-gadget discovery.108- `offensive-tools/rev/checksec`, `offensive-tools/rev/patchelf` — mitigation inventory and target-libc reproduction.109110Methodology neighbors: `reversing-technique` (bug discovery/handoff in), `fuzzing-technique` (repro), `vuln-exploit-technique` (CVE/service initial access), `post-exploit-technique` (after impact). For CTF-scoped triage, time-boxing, and the full recipe index, use `offensive-ctf/pwn-ctf`.