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 ()
{
char large_string [256];
int i ;
for( i = 0; i < 256; i ++)
large_string [i ] = 'A';
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:恐怕不会。在您的示例中绕过堆栈金丝雀的唯一方法是用相同的值覆盖它。由于没有内存泄漏漏洞,唯一的方法就是暴力破解它,这可能是不可行的......