Part 0 — Lab Setup & Toolchain

Series: Binary Exploitation | Difficulty: Beginner | Read time: ~20 min

What We're Building

Before we can exploit binaries, we need a proper lab. This article walks you through setting up a complete binary exploitation workstation from scratch. By the end, you'll have:

Everything here is free and open source. No paid tools, no corporate accounts. Just you, a terminal, and some binaries.

Why Linux?

Binary exploitation lives on Linux. The ELF binary format, the System V AMD64 ABI calling convention, the /proc filesystem — these are all Linux concepts. While you can do some pwn on Windows, almost every serious exploit developer uses Linux as their primary platform.

We'll use Ubuntu 22.04 LTS because it's stable, well-supported, and has excellent package management. LTS means "Long Term Support" — Canonical will provide security updates until 2027.

Step 1: Install VirtualBox

A virtual machine (VM) lets us run Linux inside our existing OS. If something breaks — and it will — we can snapshot and revert instantly.

  1. Download VirtualBox from https://www.virtualbox.org/wiki/Downloads
  2. Choose the package for your host OS (Windows, macOS, or Linux)
  3. Run the installer with default settings
  4. Reboot if prompted

Why not WSL?

Windows Subsystem for Linux is great for development, but it has limitations for binary exploitation. Some syscalls behave differently, /proc is incomplete, and you can't easily run 32-bit binaries. A full VM avoids all of these issues.

Step 2: Download and Install Ubuntu

  1. Download Ubuntu 22.04 LTS Server or Desktop from https://ubuntu.com/download/desktop
  2. Open VirtualBox and click New
  3. Name: pwn-lab, Type: Linux, Version: Ubuntu (64-bit)
  4. Memory: 4096 MB (4 GB minimum, 8 GB recommended)
  5. Disk: Create a virtual hard disk, 50 GB, dynamically allocated
  6. Settings → Storage → Add the Ubuntu ISO to the optical drive
  7. Start the VM and follow the Ubuntu installer

During installation:

VM Settings to Change

After installation, go to VM Settings:

Step 3: Update and Install Core Packages

Open a terminal in your VM (or SSH in). Run these commands one by one:

# Update package lists and upgrade existing packages
sudo apt update && sudo apt upgrade -y

# Install build essentials (gcc, g++, make)
sudo apt install -y build-essential

# Install the GNU debugger
sudo apt install -y gdb

# Install NASM (Netwide Assembler)
sudo apt install -y nasm

# Install Python 3 and pip
sudo apt install -y python3 python3-pip

# Install useful utilities
sudo apt install -y strace ltrace file strings objdump readelf hexedit vim tmux

Let's verify everything installed correctly:

gcc --version
# Should show: gcc (Ubuntu ...) 11.3.0 ...

gdb --version
# Should show: GNU gdb (Ubuntu ...) ...

nasm --version
# Should show: NASM version 2.15.05 ...

python3 --version
# Should show: Python 3.10.6 ...

If any of these commands fail, go back and check your steps. Don't skip ahead — every tool in this list will be used repeatedly in future articles.

Step 4: Understanding GCC

GCC (GNU Compiler Collection) is the backbone of C compilation on Linux. You'll use it constantly to compile vulnerable test programs. Here are the flags you need to know:

# Basic compilation
gcc -o output source.c

# With debug symbols (essential for GDB)
gcc -g -o output source.c

# Disable all protections (for learning purposes only!)
gcc -o output source.c -z execstack -fno-stack-protector -no-pie

# With specific flags explained:
#   -g              Include debug symbols
#   -z execstack    Allow execution on the stack (needed for shellcode)
#   -fno-stack-protector  Disable stack canaries
#   -no-pie         Disable Position Independent Executable
#   -m32            Compile as 32-bit (requires libc-dev-i386)

Security Warning

Flags like -z execstack and -fno-stack-protector make your binary intentionally vulnerable. NEVER use these on production software. They are for learning and CTF challenges only.

Compile Your First Vulnerable Binary

Let's create a simple program we can practice on:

// vuln.c
#include <stdio.h>
#include <string.h>

void win() {
    printf("Congratulations! You hijacked the flow.\n");
}

int main() {
    char buf[32];
    printf("Enter your name: ");
    gets(buf);  // NEVER do this in real code
    printf("Hello, %s!\n", buf);
    return 0;
}

Compile it with protections disabled:

gcc -g -o vuln vuln.c -z execstack -fno-stack-protector -no-pie

Run it and type something longer than 32 characters — watch it crash. We'll learn exactly why in Part 3.

Step 5: GDB — Your Debugger

GDB is the GNU Debugger. It lets you step through programs instruction by instruction, inspect memory, examine registers, and set breakpoints. It's ugly but incredibly powerful.

GDB Basics

# Start GDB
gdb ./vuln

# Inside GDB:
(gdb) break main          # Set breakpoint at main
(gdb) run                 # Start the program
(gdb) next                # Step over one line
(gdb) step                # Step into a function
(gdb) info registers      # Show all registers
(gdb) x/20x $rsp          # Examine 20 words at RSP (stack pointer)
(gdb) disassemble main    # Show assembly of main
(gdb) continue            # Continue execution
(gdb) quit                # Exit GDB

Install GEF for Better GDB

Raw GDB is painful. GEF (GDB Enhanced Features) adds a beautiful dashboard showing registers, stack, code, and more — all in one view.

# Install GEF
bash -c "$(curl -fsSL https://gef.blah.cat/sh)"

Restart GDB and open your binary. You'll see a much nicer interface with register values, stack contents, and disassembly all visible at once.

GDB Cheat Sheet

break *0x401180       # Break at specific address
info functions        # List all functions
x/s 0x401234         # Examine string at address
x/10i $rip           # Show 10 instructions at RIP
set $rip = 0x401100  # Change instruction pointer
info proc mappings    # Show memory layout
vmmap                 # GEF: show virtual memory map

Step 6: Python and Pwntools

Pwntools is a CTF framework and exploit development library for Python. It makes it trivial to craft payloads, interact with processes, and write exploits.

Install Pwntools

pip3 install pwntools

Verify it works:

python3 -c "from pwn import *; print('pwntools ready')"
# Should print: pwntools ready

Your First Exploit

Let's write a basic exploit for the vulnerable program we compiled earlier:

# exploit.py
from pwn import *

# Start the process
p = process('./vuln')

# Wait for the prompt
p.recvuntil(b'Enter your name: ')

# Send a payload (we'll explain this in Part 3)
payload = b'A' * 40  # Overflow buffer + saved RBP + partial return
p.sendline(payload)

# Check if we get a shell or crash
p.interactive()

Run it:

python3 exploit.py

The program should crash. That's progress! In Part 3, we'll learn exactly how to control that crash.

Step 7: Essential Utilities

These tools will come up repeatedly in the series:

file — Identify Binary Type

file ./vuln
# Output: ./vuln: ELF 64-bit LSB pie executable, x86-64 ...

objdump — Disassemble Binaries

objdump -d ./vuln           # Disassemble all functions
objdump -d -M intel ./vuln  # Intel syntax (more readable)

readelf — Inspect ELF Structure

readelf -h ./vuln    # ELF header
readelf -S ./vuln    # Section headers
readelf -l ./vuln    # Program headers (segments)

strings — Find Printable Strings

strings ./vuln       # List all printable strings in the binary

nm — Symbol Table

nm ./vuln            # List symbols (function names, variables)

Step 8: Disabling ASLR (For Practice)

Address Space Layout Randomization (ASLR) randomizes where memory is placed each time a program runs. It's a security feature that makes exploitation harder. For learning, we'll disable it temporarily:

# Disable ASLR (requires sudo)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

# Re-enable ASLR when done practicing
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

Don't Forget

Only disable ASLR for practice binaries on your VM. Re-enable it when you're done. ASLR is one of the most important security mitigations on modern Linux systems.

Step 9: Setting Up a Working Directory

Create a structured workspace for this series:

# Create directory structure
mkdir -p ~/pwn/{challenges,articles,tools,writeups}

# Create a symlink for convenience
ln -s ~/pwn ~/Desktop/pwn

# Navigate to challenges
cd ~/pwn/challenges

Step 10: Optional — tmux

tmux lets you split your terminal into multiple panes. It's incredibly useful when you want GDB in one pane and a text editor in another.

# Install tmux
sudo apt install -y tmux

# Start a new session
tmux

# Split vertically (side by side)
Ctrl+b %

# Split horizontally (top/bottom)
Ctrl+b "

# Switch between panes
Ctrl+b Arrow keys

# Detach (leave tmux running)
Ctrl+b d

# Reattach
tmux attach

Quick Reference Card

Pin this somewhere. You'll need it.

=== COMPILE ===
gcc -g -o vuln vuln.c -z execstack -fno-stack-protector -no-pie

=== DEBUG ===
gdb ./vuln
  break main → run → next → step → info registers → x/20x $rsp

=== INSPECT ===
file ./vuln
objdump -d -M intel ./vuln
readelf -h ./vuln
strings ./vuln

=== EXPLOIT ===
python3 -c "from pwn import *; p = process('./vuln')"

=== DISABLE ASLR ===
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Quiz — Test Your Setup

Answer these questions to confirm your lab is ready:

Question 1

Which GCC flag disables stack canaries?

Question 2

What does the -g flag do in GCC?

Question 3

Which tool identifies a file as an ELF 64-bit binary?

Question 4

What value disables ASLR in /proc/sys/kernel/randomize_va_space?

Question 5

Which Python library simplifies exploit development?

What's Next

Your lab is ready. In Part 1 — Inside an ELF Binary, we'll crack open a compiled program and examine every byte. You'll learn what the ELF header looks like, how sections map to memory, and why the Program Counter points where it does.

We're going to read hex for fun. Let's go.

← Back to Home Part 1 - Inside an ELF →