The Art of Compiler on Buffer Overflow
现代编译器GCC非常强大,它甚至可以在编译阶段防止缓冲区溢出,使操作系统无法在堆栈空间上运行代码。
例如:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void function(char *str)
{ char buffer[16]; strncpy(buffer, str, 256); void main() for( i = 0; i < 256; i++) function(large_string); |
获得魔法 0x41414141 的唯一方法是设置 GCC 编译参数,例如:
1
|
gcc –fno–stack–protector –z execstack stackoverflow.c –o stackoverflow
|
(我在 ubuntu 10.04 x86 lucid 32bits box 上测试过)
有什么办法可以绕过 GCC 堆栈粉碎保护吗?
- 您指的是哪个限制,为什么要绕过它?
- 你想故意破坏堆栈吗?为什么?顺便说一句,您的代码有一个错误。您忘记了 NULL 终止 large_string。 strcpy() 将不限于 255 个字节。
- 我认为您的意思是询问是否可以绕过 gcc 堆栈保护,如果可以,您应该编辑问题以使其清楚。
- @NikosChantziaras 有了这个错误,它就更好了!
- @JonathanLeffler 限制是我只能覆盖 eip 寄存器,并且在编译代码时必须设置 -fno-stack-protector 和 execstack 参数。如果不设置上面的两个参数,即使存在”strcpy(buffer,str)”问题,我也无法利用缓冲区溢出技巧
- 您可以绕过它,但最有效的方法是查看生成的代码以了解它应该如何完成。
- @JustForTest 这不是限制它是一个功能
- @mux 完全正确!这就是我想要的。实际上,我的作业是我们需要在 C 代码中找到缓冲区溢出的古老性并加以利用(通过它运行 shellcode)。问题是,即使我在 strcpy() 函数中发现了问题,我也无法利用它,因为代码是使用 gcc 堆栈保护编译的。
- 然后在没有保护的情况下编译它。问题出在哪里?
- @mux 感谢您进行编辑以使问题更清楚;-)
- @AlexeyFrunze 你能告诉我一个关于如何绕过我遇到的这个问题的 GCC 堆栈粉碎保护的解决方案吗?
- 研究编译器的汇编输出以了解保护的工作原理。使用 -S 选项。
- @NikosChantziaras问题是没有保护我无法编译它,我需??要绕过堆栈保护
- @AlexeyFrunze 代码中的那个错误可能会使 strcpy 在返回之前崩溃,并且它还可能用意外的值(不是 \\’A\\’s)填充堆栈,你不认为它应该被修复吗?
- @mux 是的,我应该添加一个笑脸。
- 该示例代码中有一个错误,这只会使您的事情变得更加复杂,我对帖子进行了一些更改,我认为它们没有被提交。
- @mux 你能再次发送提交吗?
- @mux 为什么我们应该使用 strncpy() 而不是 strcpy()?
- @JustForTest 因为您必须以空值终止或指定要从字符串复制的字节数,否则, strcpy 将继续复制字节,直到达到空字节或崩溃,并且永远不会返回,请参见上面的评论。
编译时应禁用堆栈保护:
1
|
gcc –fno–stack–protector –z execstack stackoverflow.c –o stackoverflow
|
您可能还想禁用地址空间随机化 (ASLR):
1
|
sudo sh –c ‘echo 0 > /proc/sys/kernel/randomize_va_space’
|
现在你可以试试缓冲区溢出了,我推荐阅读 Smashing the Stack for Fun and Profit
编辑:
就像我在评论中所说的那样,可以安全地假设在您的分配中禁用堆栈保护是可以接受的,但是,如果您想绕过堆栈保护,您应该检查 SOF 中与金丝雀相关的问题,例如以下问题:
有没有办法绕过 SSP (StackSmashing Protection)/Propolice?
- 有没有一种方法可以直接粉碎堆栈而无需任何参数设置?
- 您的作业要求利用缓冲区溢出,我认为可以安全地假设禁用堆栈保护是可以接受的,否则问题实际上要复杂得多。
- 是的,我想是这样。很好奇是否有办法绕过如此强大的堆栈保护。另一方面,即使代码中存在堆栈溢出漏洞,也可以说它对代码是安全的,因为堆栈中的代码在堆栈保护编译后无法运行。(此类问题的最坏情况是程序终止,黑客无法通过它运行shellcode)
- 只是一个小的更正:您的 echo 命令将不起作用。它应该类似于 sudo sh -c ‘echo 0 > /proc/sys/kernel/randomize_va_space’。
- @工作谢谢!我总是忘记这一点:)
- @mux 为什么我不能简单地将 “0” 回显到 randomize_va_space 文件?
- @JustForTest 您需要以 root 身份执行此操作并以 root 身份执行整个命令。
- @mux 嗨,mux。你能给我你的电子邮件地址,我想更多地谈谈我的缓冲区溢出作业吗?
当然有一些方法可以绕过堆栈粉碎保护(称为堆栈金丝雀),尽管在您的示例中并不容易。有关堆栈金丝雀的一些弱点,请参阅我的答案。
- 你能为这种堆栈金丝雀举一个简单可行的例子吗
- @JustForTest:恐怕不会。在您的示例中绕过堆栈金丝雀的唯一方法是用相同的值覆盖它。由于没有内存泄漏漏洞,唯一的方法就是暴力破解它,这可能是不可行的……
来源:https://www.codenong.com/13024977/