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:
gccwith-m32optiongdb(GNU Debugger)- Ghidra (for decompilation and disassembly)
- Optional:
hexeditor 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
gdbandx/24x $espto examine stack - Disable ASLR every time
- Use
hexeditto 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.