我目前正在写关于堆栈溢出的文章,并创建了以下程序(作为参考,我使用的是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"字符(加上null字符)写入已保存的ESP
我在GDB中验证了这个程序的行为,下面是我得到的:
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0xb7e30043 in ?? () from /lib/i386-linux-gnu/libc.so.6
在这种情况下,程序试图跳转到0xb7e30043(溢出值,带有0x43和null终止符),而不是原始值0xb7e31637,它是__libc_start_main的返回点。
对我来说,这就是事情变得棘手的地方。在进行"info-proc映射"时,我发现0xb7e30043似乎就像"有效"内存(在/lib/i386-linux-gnu/libc.so.6中)
我知道segfault可能是由我不"拥有"的内存或未映射的段触发的。但在这种情况下,既然它在我的应用程序的内存空间中,并且libc被映射到它,为什么我会得到一个segfault?
我怀疑这是由于某种错位造成的,因为在溢出后EIP指向libc内的随机指令。如果是,我该如何调整?它背后的制约因素是什么?谁来执行它?内核,MMU?
问题是0xb7e30043处的指令无效。
这是当前的指令:
0xb7e30043: add %cl,(%eax)
我查了一下eax值,结果是零。从那里开始,事情变得更容易了。进程尝试访问0x0处的内存,但由于segfault而失败。