OverTheWire FormulaOne Level 2 → Level 3 Tutorial!!
Login
We now have the credentials for formulaone2.
ssh formulaone2@formulaone.labs.overthewire.org -p 2232
# password: OvQAKUM3BrvbH4pKjBJBCOUpTGSDjNum
Task
The goal is to exploit the binary formulaone3
in order to retrieve the password for formulaone3.
A little bit of Theory
Looking inside /formulaone/
:
We see both the compiled formulaone3
and its source formulaone3.c
. The binary has setuid permissions, so it runs as formulaone3.
The source reveals a program that uses System V Shared Memory (shm), with two buffers:
msg.ptr[1024]
in shared memorybuf[256]
on the stack indoecho()
The code calls memcpy(buf, echo->ptr, echo->sz)
but only checks:
if (echo->sz < sizeof(buf))
This introduces a race condition → if we change echo->sz
quickly after the check but before the memcpy
, we can force a buffer overflow.
Key exploit concept:
- Normal copy if
sz < 256
. - If we flip
sz
to >256 right after, memcpy will overflow the 256-byte stack buffer. - With setuid enabled, this overflow lets us hijack execution and read
/etc/formulaone_pass/formulaone3
.
Solution
Step 1 — Proof of Concept
We write a helper program that alternates sz
:
shared_memory->sz = 255; // passes the check
usleep(500);
shared_memory->sz = 510; // triggers overflow
Running this alongside /formulaone/formulaone3
results in segmentation faults:
→ Confirmed: buffer overflow is possible.
Step 2 — Crafting the Exploit
Security check via checksec
:
RELRO Partial RELRO
STACK CANARY No canary
NX Enabled
PIE No
NX means we can’t execute code directly on the stack, so we’ll inject shellcode into shared memory (executable) and redirect execution there.
We generate shellcode with pwntools:
pwn shellcraft cat /etc/formulaone_pass/formulaone3 -f d
Step 3 — Final Exploit
We craft payload with:
- NOP sled (for stable landing).
- Shellcode (
cat /etc/formulaone_pass/formulaone3
). - Return address overwrite pointing into shared memory.
Exploit loop runs until the race condition hits
Step 4 — Success 🎉
We get the password for formulaone3:
Liqb5fEvP7IjKWZpoFOdYfQT494msxyv
Troubleshooting Quick Tips
- Segfault only → Adjust
usleep()
timings. - No output → Check if shellcode is copied correctly.
- Wrong password → Ensure return address points inside shared memory.
Conclusion
This level combines race conditions with a classic buffer overflow — a powerful combo in real-world exploitation. We also see why NX and stack canaries exist today: to stop exactly this style of attack.
By chaining timing tricks and memory corruption, we gained access to the next user.
Thanks for reading!
Until next time — Otsumachi!! 💖☄️✨