Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Classify the dominant artifact, primitive, or objective.
Load the closest offensive-techniques methodology before selecting tools.
Load the closest top-level reference for the dominant primitive (overflow.md, rop.md, heap.md, heap-fsop.md, relro-aslr-relocations.md, sandbox.md, kernel.md, exotic-arch.md, advanced-primitives.md, weird-machines.md, windows-pwn.md).
Load only top-level references in references/.
Choose the smallest tool chain that can produce a validation signal.
Record the exact proof path and stop once the objective is reproducible.
Technique integration
Primary methodology to load:
reversing-technique
vuln-exploit-technique
fuzzing-technique
Use these as decision engines. This skill adds challenge-oriented triage and time-boxing.
Tool routing
Prefer these tool families when the corresponding signal appears:
pwntools
gdb
radare2
ghidra
coding/asm-patterns
coding/asm-testing
offensive-coding/rop-development-dev
offensive-coding/heap-exploitation-dev
offensive-coding/shellcode-dev
Tool syntax belongs in the tool skills. This skill decides when a tool family fits and what output should validate progress.
Category-specific quick pivots
Triage binary and mitigations first; prove exact controlled primitive before payload engineering.
Build exploit in stages: local repro, info leak, base calculation, control-flow/data-only effect, remote adaptation.
Keep offsets, libc/loader assumptions, and environment drift explicit.
For stateful exploits, keep leaks, allocator shaping, staging, and the trigger on one connection unless process boundaries are proven irrelevant. Load references/stateful-exploit-campaigns.md when later stages depend on earlier menu actions, sort order, allocator history, or live stack state.
Treat emulators, permutation models, and offline address calculations as candidate generators. Promote a candidate only after a live breakpoint snapshot proves the exact call site, register arguments, target memory, return state, and next reachable stage.
If _dl_fixup, link_map, dynamic tags, forged symbols, or an unresolved PLT entry become an endgame, load references/dynamic-linker-resolver-pivots.md. Prove a reachable lazy call in the final process state before building resolver metadata.
Harness reliability: anchor each response parser on a stable token (the menu reprint), not the input prompt the previous step already consumed — a swallowed delimiter desyncs the next recvuntil and reads as a flaky exploit, usually papered over with long timeouts instead of fixed. Parse binary leaks over raw pipes or the live socket, never a pty (a pty mangles non-printable bytes).
For local ground truth during development — PIE/heap/libc bases and arbitrary R/W to validate offsets before wiring the leak — read /proc/<pid>/{maps,mem} directly instead of trusting the exploit's own parsed values.
If RELRO, GOT/PLT, relocation tables, or leakless partial overwrites appear, load references/relro-aslr-relocations.md before deciding the final target.
If shellcode has a byte blacklist (filter function rejecting specific bytes), load references/shellcode-filtering.md first — decode the blacklist semantics, find safe XOR/ADD encoding, use register-based string construction to avoid blocked opcodes and string literals.
If the binary stacks Clang -fsanitize=safe-stack, cross-DSO CFI, a hand-rolled software shadow stack, and/or a canary on the unsafe stack (i.e. an overflow that can't reach the return address), load references/safestack-cfi-shadowstack.md. Each mitigation is defeated leak-free by attacking the runtime data they share (the TLS block, the callee's saved-register window, the jump-table-base register) rather than fighting it head-on: unsafe-pointer relocation, canary self-reference/overwrite, CFI base-register rewrite, shadow-stack bare-gadget pivot, sustained main-re-entry loop. Critically, the unsafe-stack neighbourhood depends on RLIMIT_STACK: ulimit -s unlimited (typical socat deploys) puts the writable TCB directly above the unsafe stack so the overflow reaches __safestack_unsafe_stack_ptr/canary — a WSL or default-stack /proc/pid/maps showing libc abutting the unsafe stack is a top-down-mmap artifact, NOT the remote. Reproduce with patchelf+ulimit -s unlimited, or length-sweep the live service.
Quality gates
No claim without a validation signal: recovered secret, replayed exploit, decoded artifact, reproduced model behavior, or corroborated evidence.
Do not brute force before representation, constraints, and success oracle are known.
Keep a pivot ledger: hypothesis, evidence, result, next shortest path.
Preserve coverage by using the top-level references in references/ and keeping cross-links between them consistent.
Keep challenge/platform/competition names out of notes and generated reports.
Failure modes to avoid
Never declare a vector "impossible" or "dead" by reasoning. Impossibility and reachability are decided by dynamic evidence only — code-path enumeration is always incomplete, so deductive impossibility proofs are almost always wrong. A "dead vector" claim requires a failing live test, not an argument. If you write "X can't work leaklessly/deterministically" or "nothing reaches Y", rewrite it as "X untested — run the discriminating experiment," then run it. Repeated impossibility arguments are the signal to hook everything and fuzz, not to write a longer proof.
Prove reachability by hook + fuzz, not deduction. For "does anything call Y", "can malloc return Z", "is this slot/gadget reached": breakpoint Y (and every candidate call site at once) and vary inputs — huge/boundary numeric tokens, error paths, allocation/scratch-buffer thresholds, locale. Internal parser and buffer growth introduce calls absent from normal input. Only "no hit after adversarial fuzzing" counts as unreachable.
Drive to end-to-end execution early, then fix the latest crash. After components verify in isolation, fire the whole chain and iterate: at each fault read x/i $pc, rsp & 0xf, and the faulting field, fix that one point, re-run. Late bugs — resolver-vs-call stack parity (movaps), controlled bytes overlapping a lock/pointer/terminator field, parser overwriting your string — surface only in a full run, never in isolated tests.
Keep a facts ledger and re-apply every proven fact to each later sub-chain. Carry forward every runtime fact (live offsets, register snapshots, alignment quirks, call-site parity, deterministic pointers). A fix found in one context is usually needed again in the final chain; forgetting your own earlier finding is a self-inflicted loss.
Re-read this skill's own pivots when the endgame matches one. If loader/_dl_fixup/forged-symbol, stateful, or partial-overwrite signals appear, load the matching reference before concluding the path fails — the guidance to prove reachability lives there, not in your head.
Reproduce the REMOTE, not your dev box, before trusting a boundary or a "dead" verdict. Kernel, RLIMIT_STACK, and libc differences move mmap adjacencies and mitigation reachability — WSL's top-down (default-stack) layout vs the remote's ulimit -s unlimited bottom-up layout is a classic false wall that makes a solvable overflow look "bounded/impossible". patchelf a copy onto the target libc and run under the target's stack limit, or length-sweep the live service, before any impossibility claim.
An INPUT-ONLY reproduction is the only proof a primitive works. Never accept a helper's, a workflow agent's, or a gdb set/hand-painted sim's "primitive works / doesn't" verdict — reproduce it delivered purely by attacker input. A local PTY in cooked mode silently mangles 0x7f/0x0a/0x11/0x13 bytes in pointer payloads, which fakes an "exploit never fires" negative (drive local dev over a pipe, not a PTY); a gdb set variable that hand-writes a shadow slot or register is not a delivered primitive.
Resources
references/advanced-primitives.md — advanced edge cases: seccomp oddities, VM/JIT/interpreter bugs, runtime pivots, and data-reinterpretation tricks that do not fit cleanly under the core references.
references/dynamic-linker-resolver-pivots.md — load when a leakless chain redirects loader metadata, forges dynamic symbols, triggers lazy resolution through a library path, or chains multiple resolver calls.
references/exotic-arch.md — RISC-V, ARM32, ARM64, and MIPS exploitation notes: register conventions, shellcode, gadget patterns, and architecture-specific pitfalls.
references/rop.md — x86-64 ROP and shellcode flow: leaks, pivots, chain assembly, and constrained environments.
references/safestack-cfi-shadowstack.md — Clang SafeStack + cross-DSO CFI + software shadow stack + canary as a composed mitigation: leak-free breaks (unsafe-stack-pointer relocation, canary self-reference/overwrite, CFI jump-table-base rewrite, shadow-stack bare-gadget pivot, sustained re-entry loop with 16-byte-alignment + locale-forge fixes) and the RLIMIT_STACK/WSL layout trap.
references/sandbox.md — restricted-environment escapes, proc-based pivots, and command-execution constraints.
references/shellcode-filtering.md — byte-blacklist bypass: blacklist semantic analysis, XOR/ADD register-based encoding, alternative syscall construction, blocked instruction substitutions, and ORW shellcode template for filtered execve.
references/stateful-exploit-campaigns.md — load when an exploit depends on same-process state, allocator/call-site drift, deterministic data permutations, staged pivots, or probabilistic remote retries.