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

问题描述:

我目前正在写关于堆栈溢出,并创建了下面的程序如下(仅供参考,我使用的是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 

编译什么这个程序会是:

  • 填充所有 “foo” 的阵列与 'A' 字符
  • 填充小号AVED EBP带 'B' 字符
  • 写 'C' 字符(加空字符)到ESP保存

我证实了这一程序GDB andhere的行为是我得到:

(gdb) run 

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

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

这里是事情变得棘手的地方。做一个“信息处理映射”,我看到0xb7e30043似乎像“有效”的内存(内/lib/i386-linux-gnu/libc.so.6)

我知道,segfaults可以触发内存我不“拥有”,或者未映射的段。但在这种情况下,因为这是在我的应用程序的内存空间内部,并且libc被映射到它,为什么我得到一个段错误?

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

+0

除非你没有加载glibc符号,否则''中的0xb7e30043似乎暗示你不在'glibc'函数内。无论如何,为什么关注EIP地址?你对正在执行的指令一无所知。不要在segfault trace上考虑太多,只需在'main'的'return'处使用'stepi',观察寄存器,检查汇编代码,看看究竟发生了什么。此外,这个问题可能最适合用于*(无双关语) – xhienne

+0

_0xb7e30043在?似乎暗示你不在glibc函数中_运行时如何知道我不在glinc函数中?它在每次执行之前是否会看到一些符号表? –

+0

我不确定,但我认为该消息并没有说这是访问该地址的段错误,但是执行该地址处的代码会导致段错误。这很可能是因为您执行的随机代码没有相应设置寄存器。或者你有一个字节偏移到那里的实际操作码,并得到一个不同的操作码完全混乱的结果。你看过反汇编器了吗? – Philippos

问题在于0xb7e30043处的指令无效。

这是当前指令:

0xb7e30043: add %cl,(%eax) 

我看着EAX值,它是零。从那里,事情变得更容易。该进程试图访问内存在0x0和失败与段错误。