Site: http://overthewire.org/wargames/behemoth/
Level: 5
Situation: Reading Assembly Exercise?
So let us start how we usually do. We are going to create our temp directory, check file arch type, run our application.
behemoth5@melinda:~$ mkdir /tmp/bh5
behemoth5@melinda:~$ cd /tmp/bh5
behemoth5@melinda:/tmp/bh5$ file /behemoth/behemoth5
/behemoth/behemoth5: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=cc9166a1934734dac9f39544c1383cef7bfa84d8, not stripped
behemoth5@melinda:/tmp/bh5$ /behemoth/behemoth5
behemoth5@melinda:/tmp/bh5$
Not much is being told to us here. We will now do some information grabbing. We will grab the global offset table and ltrace the application.
behemoth5@melinda:/tmp/bh5$ objdump -R /behemoth/behemoth5
/behemoth/behemoth5: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ffc R_386_GLOB_DAT __gmon_start__
0804a00c R_386_JUMP_SLOT fgets
0804a010 R_386_JUMP_SLOT fclose
0804a014 R_386_JUMP_SLOT rewind
0804a018 R_386_JUMP_SLOT htons
0804a01c R_386_JUMP_SLOT fseek
0804a020 R_386_JUMP_SLOT perror
0804a024 R_386_JUMP_SLOT malloc
0804a028 R_386_JUMP_SLOT __gmon_start__
0804a02c R_386_JUMP_SLOT exit
0804a030 R_386_JUMP_SLOT strlen
0804a034 R_386_JUMP_SLOT __libc_start_main
0804a038 R_386_JUMP_SLOT ftell
0804a03c R_386_JUMP_SLOT fopen
0804a040 R_386_JUMP_SLOT memset
0804a044 R_386_JUMP_SLOT sendto
0804a048 R_386_JUMP_SLOT atoi
0804a04c R_386_JUMP_SLOT socket
0804a050 R_386_JUMP_SLOT gethostbyname
0804a054 R_386_JUMP_SLOT close
We gain a bit of information here we can clearly see that socket and gethostbyname is being called. As well as fgets and seek. So we can assume a few things.
- A file is being read and parsed
- A socket of some kind is being opened.
behemoth5@melinda:/tmp/bh5$ ltrace /behemoth/behemoth5
__libc_start_main(0x804873d, 1, 0xffffd784, 0x8048960 <unfinished ...>
fopen("/etc/behemoth_pass/behemoth6", "r") = 0
perror("fopen"fopen: Permission denied
) = <void>
exit(1 <no return ...>
+++ exited (status 1) +++
From this we now know what file is being opened. To our surprise it is the password file for the next level.
Note. It is failing to open the file due to ltrace running the application with behemoth5 permissions. Under normal execution it can access the file.
Because we know that a socket is being and we know the odds of it being a server socket are slim do to the fact that the applications closes. We have a general idea of what to look for. Now we simply load up our debugger and disassemble to see what’s going on.
behemoth5@melinda:/tmp/bh5$ gdb /behemoth/behemoth5
(gdb) unset env LINES
(gdb) unset env COLUMNS
(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
-- SNIP --
0x08048829 <+236>: call 0x8048620 <gethostbyname@plt>
0x0804882e <+241>: mov DWORD PTR [esp+0x30],eax
0x08048832 <+245>: cmp DWORD PTR [esp+0x30],0x0
0x08048837 <+250>: jne 0x8048851 <main+276>
0x08048839 <+252>: mov DWORD PTR [esp],0x8048a1f
0x08048840 <+259>: call 0x8048560 <perror@plt>
0x08048845 <+264>: mov DWORD PTR [esp],0x1
0x0804884c <+271>: call 0x8048590 <exit@plt>
0x08048851 <+276>: mov DWORD PTR [esp+0x8],0x0
0x08048859 <+284>: mov DWORD PTR [esp+0x4],0x2
0x08048861 <+292>: mov DWORD PTR [esp],0x2
0x08048868 <+299>: call 0x8048610 <socket@plt>
0x0804886d <+304>: mov DWORD PTR [esp+0x34],eax
0x08048871 <+308>: cmp DWORD PTR [esp+0x34],0xffffffff
0x08048876 <+313>: jne 0x8048890 <main+339>
0x08048878 <+315>: mov DWORD PTR [esp],0x8048a2d
0x0804887f <+322>: call 0x8048560 <perror@plt>
0x08048884 <+327>: mov DWORD PTR [esp],0x1
-- SNIP --
-- SNIP --
0x08048911 <+468>: mov eax,DWORD PTR [esp+0x34]
0x08048915 <+472>: mov DWORD PTR [esp],eax
0x08048918 <+475>: call 0x80485f0 <sendto@plt>
0x0804891d <+480>: mov DWORD PTR [esp+0x38],eax
0x08048921 <+484>: cmp DWORD PTR [esp+0x38],0xffffffff
0x08048926 <+489>: jne 0x8048940 <main+515>
0x08048928 <+491>: mov DWORD PTR [esp],0x8048a39
0x0804892f <+498>: call 0x8048560 <perror@plt>
0x08048934 <+503>: mov DWORD PTR [esp],0x1
0x0804893b <+510>: call 0x8048590 <exit@plt>
0x08048940 <+515>: mov eax,DWORD PTR [esp+0x34]
0x08048944 <+519>: mov DWORD PTR [esp],eax
0x08048947 <+522>: call 0x8048630 <close@plt>
0x0804894c <+527>: mov DWORD PTR [esp],0x0
0x08048953 <+534>: call 0x8048590 <exit@plt>
-- SNIP --
End of assembler dump.
We can confirm that indeed a socket is being made. Also we see sendto function sendto is used to broadcast a message on a stateless connection a.k.a “UDP”. We are only missing the host and the port now. If we had a good debugger we would be able to see the data in each memory address in our disassembly. We could iterate over all the addresses and look at memory. However to make things quick we run strings.
behemoth5@melinda:/tmp/bh5$ strings /behemoth/behemoth5
-- SNIP --
QVh=
D$L1
[^_]
/etc/behemoth_pass/behemoth6
fopen
localhost
gethostbyname
socket
1337
sendto
-- SNIP --
Looks like localhost and 1337. So to listen on the port we are going to use netcat.
behemoth5@melinda:/tmp/bh5$ nc -ul 1337
behemoth5@melinda:/tmp/bh5$ /behemoth/behemoth5
behemoth5@melinda:/tmp/bh5$
behemoth5@melinda:/tmp/bh5$ nc -ul 1337
[OMITTED]
There is our password.