为什么这个程序会导致段错误?

Why does this program causes a segfault?

我目前正在撰写有关堆栈溢出的文章,并在下面创建了以下程序(供参考,我使用的是 32 位 linux 机器):

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

int main () {
    char foo[16];
    strcpy(foo, "AAAAAAAAAAAAAAAABBBBC");
}

这个程序是用

编译的
 gcc stack_buffer_2.c -g -o stack_buffer_2 -fno-stack-protector

这个程序的作用是:

我在 GDB 中验证了这个程序的行为,这是我得到的:

(gdb) run

Program received signal SIGSEGV, Segmentation fault.
0xb7e30043 in ?? () from /lib/i386-linux-gnu/libc.so.6

程序试图跳转到 0xb7e30043(溢出值,带有 0x43 和空终止符)而不是原始值 0xb7e31637,在此上下文中,它是 __libc_start_main 的 return 点。

这就是让我感到棘手的地方。做一个 "info proc mappings",我看到 0xb7e30043 似乎是 "valid" 内存(在 /lib/i386-linux-gnu/libc.so.6 内)

我知道段错误可以由我不 "own" 的内存或未映射的段触发。但在这种情况下,因为它在我的应用程序的内存 space 中,并且 libc 映射到它,为什么我会遇到段错误?

我怀疑这是由于某种错位造成的,因为溢出后 EIP 指向 libc 中的随机指令。如果是,我该如何调整它?它背后的约束是什么,谁来执行它?内核,MMU?

问题是 0xb7e30043 处的指令无效。

这是当前指令:

0xb7e30043: add    %cl,(%eax)

我查看了 eax 值,它是零。从那里开始,事情变得更容易了。该进程试图访问 0x0 处的内存,但因段错误而失败。