A dense reference library for turning memory corruption into shells during CTFs. You'll reach for this when you've already identified the vulnerability class and need execution recipes: stack pivots, SROP with encoding constraints, tcache poisoning variants, FILE structure hijacks, seccomp bypasses, or any of the thirty-plus writeup-derived techniques across eleven supporting files. The scope is admirably narrow. It won't help you reverse the binary or understand what's broken, but once you know you have a format string or heap UAF, you get concrete exploit chains including edge cases like single-bit flips, bloom filter OOB writes, and Windows SEH overwrite. Best used alongside a reversing skill when the challenge has multiple phases.
npx -y skills add ljagiello/ctf-skills --skill ctf-pwn --agent claude-codeInstalls into .claude/skills of the current project.
Quick reference for binary exploitation (pwn) CTF challenges. Each technique has a one-liner here; see supporting files for full details.
Python packages (all platforms):
pip install pwntools ropper ROPgadget
Linux (apt):
apt install gdb binutils strace ltrace qemu-system-x86
macOS (Homebrew):
brew install gdb binutils qemu
Ruby gems (all platforms):
gem install one_gadget seccomp-tools
Manual install:
brew install pwndbg/tap/pwndbg-gdb__call_tls_dtors, custom shadow stack pointer overflow bypass, signed int overflow negative OOB heap write, XSS-to-binary pwn bridge/ctf-reverse before trying to exploit it./ctf-misc./ctf-web./ctf-crypto.# Binary analysis
checksec --file=binary
file binary
readelf -h binary
# Find gadgets
ROPgadget --binary binary | grep "pop rdi"
ropper -f binary --search "pop rdi"
one_gadget /lib/x86_64-linux-gnu/libc.so.6
# Debug
gdb -q binary -ex 'start' -ex 'checksec'
# Pattern for offset finding
python3 -c "from pwn import *; print(cyclic(200))"
python3 -c "from pwn import *; print(cyclic_find(0x61616168))"
# libc identification
./libc-database/find puts <leaked_addr_last_3_nibbles>
pthread -> race conditionsusleep()/sleep() -> timing windowsbash -c '{ echo "cmd1"; echo "cmd2"; sleep 1; } | nc host port'
gets(), scanf("%s"), strcpy()printf(user_input)| Protection | Status | Implication |
|---|---|---|
| PIE | Disabled | All addresses (GOT, PLT, functions) are fixed - direct overwrites work |
| RELRO | Partial | GOT is writable - GOT overwrite attacks possible |
| RELRO | Full | GOT is read-only - need alternative targets (hooks, vtables, return addr) |
| NX | Enabled | Can't execute shellcode on stack/heap - use ROP or ret2win |
| Canary | Present | Stack smash detected - need leak or avoid stack overflow (use heap) |
Quick decision tree:
__free_hook, __malloc_hook (glibc < 2.34), or return addressescyclic 200 then cyclic -l <value>checksec --file=binaryret2win with magic value: Overflow -> ret (alignment) -> pop rdi; ret -> magic -> win(). Stack alignment: SIGSEGV in movaps = add extra ret gadget. Offset: buffer at rbp - N, return at rbp + 8, total = N + 8. Input filtering: assert payload avoids memmem() banned strings. Gadgets: ROPgadget --binary binary | grep "pop rdi", or pwntools ROP() for hidden gadgets in CMP immediates. See overflow-basics.md for full exploit code.
Pattern: Custom file parser (PCAP, image, archive) allocates fixed stack buffer but input records can exceed it. memcpy copies before length validation, overflowing saved registers and return address. Must restore callee-saved registers: rbx to readable memory (BSS), loop counters to exit values, then ret gadget + win function. See overflow-basics.md.
Pattern: Menu create/modify/delete on structs with data buffer + pointer. Overflow name into pointer field with GOT address, then write win address via modify. See overflow-basics.md for full exploit and GOT target selection table.
Pattern: scanf("%d") without sign check; negative quantity * price = negative total, bypasses balance check. See overflow-basics.md.
Pattern: Overflow valid flag between buffer and canary. Use ./ as no-op path padding for precise length. See overflow-basics.md and advanced.md for full exploit chain.
Pattern: Adjacent global variables; overflow via extra CSV delimiters changes filename pointer. See overflow-basics.md and advanced.md for full exploit.
Leak libc via puts@PLT(puts@GOT), return to vuln, stage 2 with system("/bin/sh"). See rop-and-shellcode.md for full two-stage ret2libc pattern, leak parsing, and return target selection.
DynELF libc discovery: pwntools.DynELF(leak_func, pointer_in_libc) resolves libc symbols remotely without knowing the libc version. See rop-and-shellcode.md.
Constrained shellcode in small buffers: When buffer is too small, use read() shellcode stub (< 20 bytes) to pull full stage-2 shellcode. See rop-and-shellcode.md.
Raw syscall ROP: When system()/execve() crash (CET/IBT), use pop rax; ret + syscall; ret from libc. See rop-and-shellcode.md.
ret2csu: __libc_csu_init gadgets control rdx, rsi, edi and call any GOT function — universal 3-argument call without libc gadgets. See rop-and-shellcode.md.
Bad char XOR bypass: XOR payload data with key before writing to .data, then XOR back in place with ROP gadgets. Avoids null bytes, newlines, and other filtered characters. See rop-and-shellcode.md.
Exotic gadgets (BEXTR/XLAT/STOSB/PEXT): When standard mov write gadgets are unavailable, chain obscure x86 instructions for byte-by-byte memory writes. See rop-and-shellcode.md.
Stack pivot (xchg rax,esp): Swap stack pointer to attacker-controlled heap/buffer when overflow is too small for full ROP chain. Requires pop rax; ret to load pivot address first. See rop-and-shellcode.md.
rdx control: After puts(), rdx is clobbered to 1. Use pop rdx; pop rbx; ret from libc, or re-enter binary's read setup + stack pivot. See rop-and-shellcode.md.
Canary XOR epilogue as rdx zeroing gadget: When no pop rdx; ret exists, jump into the canary check epilogue xor rdx, fs:28h -- it zeros RDX when the canary is intact. See rop-and-shellcode.md.
stub_execveat as execve alternative: When no pop rax; ret exists, use stub_execveat (syscall 322/0x142) instead of execve -- send exactly 0x142 bytes so read() return value sets rax. See rop-and-shellcode.md.
Shell interaction: After execve, sleep(1) then sendline(b'cat /flag*'). See rop-and-shellcode.md.
ROT13-encoded format string: When input is ROT13/Caesar-transformed before reaching printf, pre-encode the format string payload with the inverse transform so it arrives intact. See format-string.md.
addr_limit bypass via failed file open: When a kernel module sets addr_limit = KERNEL_DS but fails to restore it on error paths, force the error (e.g., make target file a directory) to retain kernel memory access from userspace read()/write(). See kernel-techniques.md.
CPU emulator eval injection: When an emulator's print opcode uses eval('"' + buf + '"') for escape sequences, build "+__import__("os").system("cmd")# in emulator memory via ADD opcodes to escape the string and execute Python. See sandbox-escape.md.
Neural network function pointer OOB: When a binary uses NN output as an index into a function pointer array without bounds checking, retrain weights/biases to produce an out-of-bounds index that reads a target address from the biases array. See advanced-exploits-4.md.
Shellcode unique-byte limit bypass via counter overflow: When shellcode is limited to N unique bytes, spray the stack to corrupt the seen[256] counter, then re-execute main (skipping memset) so the overflowed counter allows arbitrary bytes on the second run. See advanced-exploits-4.md.
Use field-notes.md once you have confirmed the challenge is truly exploitation-heavy.
juliusbrussee/caveman
mattpocock/skills
shadcn/improve
obra/superpowers
forrestchang/andrej-karpathy-skills
vercel-labs/skills