exploit-pwn-chain
Engineer a reliable exploit from a known memory-corruption bug — stack, heap, or kernel — taking a local crash to a stable remote exploit: ret2libc/ret2csu/one_gadget, tcache/fastbin/unsorted-bin tech
SKILL.mdskills/exploit-dev/exploit-pwn-chain/SKILL.md
GitHubPwn chain: bug to working exploit
When it applies
You already know where it crashes — reverse-eng-binary-triage or exploit-memory-corruption
found the overflow/UAF/double-free — and now you must produce a stable exploit against the real
remote target, not a script that only works on your laptop. Covers userspace stack pwn, glibc heap
exploitation, and Linux kernel/driver pwn (e.g. an ioctl bug for privesc). Pentest-only; note the
crash risk in the RoE (tradecraft-scope-roe).
Why it works
A local win and a remote win differ by engineering, not by the bug: the remote libc version, ASLR slide, stack alignment, network buffering, and heap layout all shift. The chain is always the same — model the protections, leak what randomization hides, build the primitive (ROP/poisoned bin/sprayed object), then iterate against the real environment until the success rate is measured, not assumed.
Method
Stack / heap / kernel technique reference (templates, glibc version table, spray objects, privesc paths): see
cheatsheet.mdnext to this file.
- Classify bug + protections.
checksec ./vuln(NX / canary / PIE / RELRO / FORTIFY) decides the whole strategy. Bug class: stack overflow / format string / heap (UAF, double-free, overflow) / integer / race / kernel. - Pick the strategy. NX off + no ASLR → shellcode. NX + libc provided → ret2libc / one_gadget.
NX + no libc → leak, then libc-database lookup. Heap → technique per glibc version (tcache /
fastbin / unsorted / large bin). Kernel →
commit_credsROP,modprobe_path, orcore_pattern. - Stage libc + gadgets.
./find puts 0x6f0in libc-database;ROPgadget --binary ./libc.so.6 --only "pop|ret";one_gadget ./libc.so.6; base =leaked - libc.sym['puts']. Run the target under the exact remote libc locally:patchelf --set-interpreter ./ld-linux-x86-64.so.2 --set-rpath . ./vuln. - Write the pwntools skeleton.
context.binary = ELF('./vuln'); iterate withprocess()/gdb.debug('./vuln', 'b *main+xx');cyclic()/cyclic_find()for the offset; finish atp.interactive(). - Make it work locally — attach, watch registers, tune offsets with pwndbg/GEF
(
vmmap,heap,bins,telescope), then switch toremote(). - Stabilize remotely. Never guess libc offsets — leak and reverse-lookup. Fix
movapsstack alignment with an extraretgadget. Anchor reads withrecvuntil(b'exact marker'), neversleep; prefersendlineafteroversendline. For heap sprays, oversize the spray and leave padding chunks against consolidation. Then loop the exploit (while True) until it succeeds ≥ 95% over 20+ remote runs.
Gotchas
- "Local works, remote segfaults in
system" — almost always 16-byte stack misalignment (movaps xmm0, [rsp]); add oneretgadget. Second cause: wrong libc version — leak first. - Heap techniques are glibc-version-locked — tcache appeared in 2.27, safe-linking in 2.32,
hooks removed in 2.34. Same binary + different libc = completely different exploit path. Check
with
./libc.so.6 | head -1. - Kernel pwn: confirm CPU flags first —
+smep +smap +pkuin the qemu line (or the real kernel's config) dictates the ROP chain; KPTI forces theswapgs_restore_regs_and_return_to_usermodetrampoline for the return to userland. - One KASLR leak is enough — compute everything as offsets from it; repeated leaking just adds failure surface.
- canary on forking servers — child processes share the canary; brute-force it byte by byte (1/256 per byte).
- Static binaries have no GOT — use SROP or raw syscalls instead of ret2libc.
Verify success
The exploit runs end-to-end against the real remote target ≥ 95% of the time across 20+ consecutive runs, from the same pwntools script, with the libc identified by leak — not assumed. A shell (or root shell, for kernel pwn) that survives reconnection is the proof.
References
pwntools docs; GEF (bata24 fork for kernel structs) / pwndbg; ROPgadget / ropper; one_gadget;
libc-database. Find the bug with reverse-eng-binary-triage; userspace basics in
exploit-memory-corruption; post-exploitation via exploit-chaining and payloads-reverse-shells.
Portions adapted from reverse-skill by zhaoxuya520, MIT License.