# Linux Exploitation Lab Setup

> Build and run the vulnerable binaries used throughout the Linux Exploitation Fundamentals series, in Docker or natively.

- Published: 2026-03-02
- Difficulty: intermediate
- Tags: Linux, Exploit Development, Tooling, Docker
- Source: https://stevenfoerster.com/tutorials/linux-exploitation-lab-setup/

## Prerequisites

- Basic Linux command line knowledge
- A disposable Linux VM; Docker is supported inside that VM

The [Linux Exploitation Fundamentals](https://stevenfoerster.com/tutorials/basic-stack-buffer-overflow-x86/) series walks through a progression of binary exploitation techniques. Every tutorial analyses a purpose-built vulnerable binary; this guide shows you how to build them and set up a working lab environment.

All source code lives in the [linux-tutorial-tools](https://gitlab.com/sfoerster/linux-tutorial-tools/) repository on GitLab.

> [!warning]
> These binaries are intentionally vulnerable. Use a disposable VM that contains
> no valuable data or credentials. A container is process isolation, not a
> security boundary for a privileged exploit-development lab.

## What's Included

Each directory contains a C source file, a Makefile with the exact compiler flags needed to reproduce the vulnerability, and a README explaining how to verify offsets on your system.

| Directory                | Binary       | Tutorial                                                                       | Arch | NX  | PIE | Canary | RELRO   |
| ------------------------ | ------------ | ------------------------------------------------------------------------------ | ---- | --- | --- | ------ | ------- |
| `01-hidden-function/`    | `reader`     | [Redirecting Execution](https://stevenfoerster.com/tutorials/redirecting-execution-to-hidden-functions/) | x86  | Off | Off | Off    | Partial |
| `02-basic-overflow-x86/` | `vuln`       | [Basic Stack Overflow](https://stevenfoerster.com/tutorials/basic-stack-buffer-overflow-x86/)            | x86  | Off | Off | Off    | Partial |
| `03-overflow-x64/`       | `vulnerable` | [Stack Overflow x64](https://stevenfoerster.com/tutorials/stack-buffer-overflow-x64/)                    | x64  | Off | Off | Off    | Partial |
| `04-ret2libc-x86/`       | `vulnerable` | [Return-to-libc](https://stevenfoerster.com/tutorials/return-to-libc-attack-x86/)                        | x86  | On  | Off | Off    | None    |
| `05-rop-x64/`            | `bypass_nx`  | [ROP NX Bypass](https://stevenfoerster.com/tutorials/bypassing-nx-with-rop-x64/)                         | x64  | On  | Off | Off    | Partial |
| `06-mprotect-rop/`       | `target`     | [mprotect ROP](https://stevenfoerster.com/tutorials/bypassing-nx-with-mprotect-rop/)                     | x64  | On  | Off | Off    | N/A     |
| `07-aslr-bypass/`        | `target`     | [ASLR Bypass](https://stevenfoerster.com/tutorials/bypassing-aslr-x64/)                                  | x64  | On  | Off | Off    | Partial |
| `08-socket-reuse/`       | `server`     | [Socket Reuse](https://stevenfoerster.com/tutorials/remote-exploitation-socket-reuse/)                   | x86  | Off | On  | Off    | Partial |
| `09-format-string-x86/`  | `vuln`       | [Format String x86](https://stevenfoerster.com/tutorials/format-string-vulnerabilities-x86/)             | x86  | On  | Off | On     | Partial |

NX is disabled for the first three exercises (shellcode on the stack) and on for most of the later ones (forcing ret2libc and ROP techniques); exercise 8 turns NX off again so the socket-reuse tutorial can demonstrate stack-resident shellcode in a remote service. PIE is only enabled for exercise 8, where the tutorial demonstrates leaking addresses to defeat it. Exercise 6 is statically linked so that `mprotect` is available directly in the binary. Exercise 9 leaves the stack canary on intentionally, the format string bug doesn't smash the saved return pointer, and the same binary is used in the next tutorial to demonstrate canary leakage.

## Docker setup inside a disposable VM

The provided image includes GCC with multilib, GDB-PEDA, pwntools, ROPgadget,
ropper, and checksec, with the exercise binaries pre-built. Run it on a
disposable VM host, not directly on a workstation that holds credentials or
production access.

```bash
git clone https://gitlab.com/sfoerster/linux-tutorial-tools.git
cd linux-tutorial-tools
docker compose up -d
docker compose exec lab bash
```

Once inside the container, verify the build:

```bash
checksec --file=01-hidden-function/reader
```

```text
RELRO           STACK CANARY      NX            PIE
Partial RELRO   No canary found   NX disabled   No PIE
```

The repository's Compose profile is intentionally privileged so GDB can attach
and the exercises can control process layout. Linux does not namespace
`kernel.randomize_va_space`; a privileged container that writes that sysctl can
change ASLR on its host. That is why the host for this lab should itself be a
disposable VM. Stop the stack when the lab is over and confirm ASLR on the VM
host with `sysctl kernel.randomize_va_space`.

## Native Setup (Alternative)

If you prefer to build natively on a Debian or Ubuntu system:

```bash
# Install dependencies
sudo apt update
sudo apt install -y gcc gcc-multilib gdb python3 python3-pip python3-venv \
    socat nasm netcat-openbsd checksec make curl git

# Clone and build
git clone https://gitlab.com/sfoerster/linux-tutorial-tools.git
cd linux-tutorial-tools
make

# Disable ASLR on this disposable VM (not on a general-purpose workstation)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```

> [!note]
> `kernel.randomize_va_space` is host-wide. Run this only on the disposable VM,
> and re-enable it when you finish:
> `echo 2 | sudo tee /proc/sys/kernel/randomize_va_space`.

You'll also want GDB-PEDA and pwntools:

```bash
# GDB-PEDA
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

# pwntools + gadget finders
python3 -m venv ~/pwn
source ~/pwn/bin/activate
pip install pwntools ROPGadget ropper
```

## Directory Structure

```text
linux-tutorial-tools/
├── 01-hidden-function/    # reader binary (SUID exercise)
├── 02-basic-overflow-x86/ # vuln binary
├── 03-overflow-x64/       # vulnerable binary
├── 04-ret2libc-x86/       # vulnerable binary (NX on)
├── 05-rop-x64/            # bypass_nx binary
├── 06-mprotect-rop/       # target binary (static)
├── 07-aslr-bypass/        # target binary
├── 08-socket-reuse/       # server binary (PIE on)
├── 09-format-string-x86/  # vuln binary (canary on)
├── Dockerfile
├── docker-compose.yml
├── Makefile
└── tests/
    └── test_binaries.sh
```

Each exercise directory contains a `Makefile` with the exact flags used to compile the binary and a `README.md` that documents expected offsets and how to rederive them with GDB-PEDA if your compiler produces different results.

## Verifying the Build

Run the included test script to validate that every binary has the correct security properties:

```bash
./tests/test_binaries.sh
```

Or verify an individual binary with `checksec`:

```bash
checksec --file=05-rop-x64/bypass_nx
```

```text
RELRO           STACK CANARY      NX            PIE
Partial RELRO   No canary found   NX enabled    No PIE
```

> [!important]
> Buffer offsets depend on your compiler version, glibc version, and build flags. If your exploit doesn't work with the offsets shown in a tutorial, each exercise README explains how to rederive the correct offset with GDB-PEDA's `pattern create` / `pattern offset` workflow.

## Tooling Overview

The Docker image (and the native setup above) includes everything the tutorials reference:

- **GDB + PEDA**, debugging, pattern creation, offset calculation
- **pwntools**, Python exploit scripting (`from pwn import *`)
- **ROPgadget / ropper**, automated gadget search for ROP chains
- **checksec**, verify binary security properties (NX, PIE, canary, RELRO)
- **socat**, network forwarding for the socket reuse exercise
- **nasm**, assembler for custom shellcode
- **netcat**, connecting to remote services
