我正在研究堆栈缓冲区溢出,我看到一些让我思考的东西。首先,操作系统该死的易受攻击的Linux ,内核 2.6.20 , ASLR禁用。
事实是,我知道当你在C程序中调用exec函数时,堆和堆栈中的内存将被清零并丢失。但是如果我在堆中分配一个缓冲区(malloc)然后我将指向该缓冲区的指针作为参数传递给使用exec函数执行的程序,则缓冲区内的数据(在堆中)将保存在堆栈中。所以在exec的末尾我有堆栈中的缓冲区(以前在堆中)。 为了使它更清楚,这是一个例子:
Program: bingo
#include <stdlib.h>
int main(int argc,char* argv[]){
int i;
char *buffer=malloc(600);
for (i=0;i<600;i++){
buffer[i]='A';
}
buffer[600-1]=0;
execl("./test","test",buffer,0);
free(buffer);
return 0;
}
测试将是一个简单的程序。
Program: test
#include <stdlib.h>
int main(int argc,char* argv[]){
printf("Hello world\n");
return 0;
}
现在,如果我使用GDB调试bingo程序,我可以看到放在堆中的缓冲区(所有As)的内容实际上是在execl函数中复制到堆栈上的。因此,在程序执行结束时,堆被清零,但缓冲区的内容已完全复制到堆栈上。我的解释是发生这种情况是因为这样缓冲区的内容将可用于执行的程序(测试)。我只想知道这种行为是否正常。 我的疑问是:当我调用execl函数时,我实际上将一个指针作为参数传递给执行的程序(测试)。 '因为缓冲区是一个指针。所以我的(可能是愚蠢的)问题是:不应该只将指针传递给执行的程序而不是指针指向的内容吗?
谢谢
答案 0 :(得分:3)
将缓冲区复制到堆栈的原因是它在./test中作为参数argv [1]传递。 buffer只是一个引用bingo内存位置的变量。进程时,堆分配不会持久存在 退出。
注意:假设缓冲区在宾果进程的内存中引用0xfff123
。这是一个虚拟(特定于流程)的地址。 0xffff123
甚至可能不会映射到./test。因此,将指针传递给0xfff123
并不能保证按照您的想法行事。
成功调用execl
后,bingo会在此时退出,并且与该进程关联的所有内存都将丢失,free(buffer)
永远不会执行。
答案:不会。进程堆分配不会在进程间持续存在。共享内存对象是内核持久性的,malloc
调用的结果不是。
我不确定你所有的困惑在哪里,但这是我最好的猜测。
相对地址示例:
进程都有0x00000000
(32位)地址。如果内核将每个进程映射到相同的物理地址,则每个进程将共享0x0000000
这不可能发生。内核将虚拟地址(0x0000000
)更改为实际物理地址,如0x3535fffa
。所以我在我的过程中的指针是“针对”0x00000000
虚拟,但这确实是0x3535fffa
。
这意味着您不能直接在进程之间传递堆指针。它不会起作用。我指向0x3535fffa
的指针与您0x3535fffa
过去引用的地址不同。