【问题标题】:Why does this program causes a segfault?为什么这个程序会导致段错误?
【发布时间】:2017-10-06 00:45:29
【问题描述】:

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

这个程序的作用是:

  • 用“A”字符填充所有“foo”数组
  • 用“B”字符填充保存的 EBP
  • 将“C”字符(加上空字符)写入保存的 ESP

我在 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 的返回点。

这对我来说是个棘手的问题。进行“info proc mappings”,我看到 0xb7e30043 似乎就像“有效”内存(在 /lib/i386-linux-gnu/libc.so.6 内)

我知道段错误可能由我不“拥有”的内存或未映射的段触发。但是在这种情况下,由于这是在我的应用程序的内存空间内,并且 libc 已映射到它,为什么我会遇到段错误?

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

【问题讨论】:

  • 除非您没有加载 glibc 符号,否则0xb7e30043 in ?? 似乎暗示您不在glibc 函数中。无论如何,为什么要关注 EIP 地址?您对正在执行的指令只字未提。不要在段错误跟踪上考虑太多,只需 stepi 来自 mainreturn,观察寄存器,检查汇编代码,看看到底发生了什么。此外,这个问题可能最适合 StackOverflow(没有双关语)
  • 0xb7e30043 在 ??似乎暗示您不在 glibc 函数中 - 运行时如何知道我不在 glinc 函数中?每次执行前它是否看起来一些符号表?
  • 我不确定,但我认为该消息并没有说访问该地址是段错误,而是在该地址执行代码会导致段错误。这很可能是因为您执行没有相应设置寄存器的随机代码。或者你对那里的实际操作码有一个字节偏移,并得到一个不同的操作码,得到完全混乱的结果。你看反汇编器了吗?
  • @Philippos 你是对的!不是我不能跳到它,而是我可以并且其中一个指令是无效的。我会在答案中添加一些细节。

标签: virtual-memory segmentation-fault


【解决方案1】:

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

这是当前的指令:

0xb7e30043: add    %cl,(%eax)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2011-03-16
    • 2017-08-18
    • 1970-01-01
    相关资源
    最近更新 更多