Lab 1: Buffer Overflow Exploits
🎯 Objective
In this lab, you'll explore classic stack-based buffer overflow vulnerabilities and learn how to craft exploits by directly manipulating binary input. The goal is not just to understand how overflows work, but to gain hands-on experience reading assembly, analyzing binaries, and reasoning about control flow at a low level.
This lab focuses on: - Understanding stack layout and calling conventions - Analyzing vulnerable binaries - Crafting exploit payloads - Techniques like code injection and return-to-libc
🗃️ Setup
Target Platform
- OS: Linux (Ubuntu recommended)
- Architecture: 32-bit x86 (even if your host system is 64-bit)
- Tools:
gcc
with-m32
optiongdb
(GNU Debugger)- Ghidra (for decompilation and disassembly)
- Optional:
hexedit
or a hex editor of your choice
Compilation Flags
To make the attack possible, disable certain security features:
gcc -m32 -fno-stack-protector -z execstack -no-pie -o example example.c
Disable ASLR
ASLR (Address Space Layout Randomization) must be disabled:
# Temporarily disable (requires sudo)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
# Or: Launch a shell with ASLR disabled
setarch `uname -m` -R /bin/bash
🧵 Vulnerable Code Walkthrough
#include <stdio.h>
#include <string.h>
int IsPasswordOkay(void)
{
char Password[12];
gets(Password);
if (!strcmp(Password, "goodpass"))
return 1;
return 0;
}
int main(void)
{
int PwStatus;
puts("Enter password:");
PwStatus = IsPasswordOkay();
if (PwStatus == 0) {
puts("Access denied");
return -1;
}
puts("Access granted");
return 0;
}
The vulnerability lies in the use of gets()
, which does no bounds checking. Input longer than 12 bytes overwrites adjacent memory.
🧠 How Stack-Based Buffer Overflows Work
[ Higher Address ]
+-----------------+
| Return Address | <- what we want to overwrite
+-----------------+
| Saved %ebp |
+-----------------+
| Buffer (??B) | <- Need to determine the actual size of the buffer
+-----------------+
[ Lower Address ]
🧪 Attack 1: Authentication Bypass
Goal: Trick the program into printing “Access granted” without knowing the correct password.
- Analyze the binary in Ghidra
- Find offset to return address
- Identify the address of the instruction that prints “Access granted”
- Construct payload:
[12 or more bytes junk][4 bytes junk][4 bytes of desired address]
🧪 Attack 2: Shellcode Injection (Code Injection)
Goal: Inject shellcode into the program and redirect control flow to it.
- Create an input:
- NOP sled (
0x90
) - Shellcode
- Padding
- Overwrite return address with address into sled
- Use GDB to find stack address
- Handle small stack shifts using NOP sled
🧪 Attack 3: Return-to-libc
Goal: Hijack control flow to system("ps")
without injecting code.
- Find
system()
address using GDB - Place
"ps"
or"/bin/sh"
string in memory - Stack layout:
[ system() address ]
[ return address (dummy) ]
[ pointer to string ]
Note: This only works cleanly on 32-bit. On 64-bit, arguments go in registers.
⚠️ Tips
- Intel is little-endian:
0xdeadbeef
→\xef\xbe\xad\xde
- Use
gdb
andx/24x $esp
to examine stack - Disable ASLR every time
- Use
hexedit
to inspect and edit your attack inputs
📄 Submission Instructions
Submit a report (no code needed) including: - Explanation of each attack - Your payloads - GDB screenshots or output - Observations and challenges
💬 Final Thoughts
This lab is about developing intuition and hands-on skill with binary exploits. Reach out on Slack or in office hours for help.