缓冲区溢出中编译器的艺术

8
现代编译器GCC非常强大,甚至可以在编译阶段预防缓冲区溢出,这样操作系统就不能在堆栈空间上运行代码。
例如:
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);
}

我只能通过设置GCC编译参数来获得神奇的0x41414141,例如:
gcc -fno-stack-protector -z execstack stackoverflow.c -o stackoverflow

(我在Ubuntu 10.04 x86 Lucid 32位系统上进行了测试)

有没有办法绕过GCC的栈溢出保护?


我认为你的意思是询问是否有可能绕过gcc的堆栈保护,如果是的话,你应该编辑问题以明确这一点。 - iabdalkader
1
@NikosChantziaras 有了那个漏洞,它甚至更好! - Alexey Frunze
@mux 没错!那正是我想要的。实际上这是我的作业,我们需要在C代码中找到缓冲区溢出漏洞并利用它(通过运行shellcode)。问题是,即使我在strcpy()函数中发现了问题,由于代码被编译为gcc堆栈保护,我无法利用它。 - JustForTest
1
然后取消保护编译它。问题出在哪里? - Nikos C.
@AlexeyFrunze,代码中的那个错误可能会导致strcpy在返回之前崩溃,并且还可能用意外的值(而不是'A')填充堆栈,你不觉得应该修复它吗? - iabdalkader
显示剩余14条评论
2个回答

7

编译时应禁用堆栈保护:

gcc  -fno-stack-protector -z execstack stackoverflow.c -o stackoverflow

您可能还希望禁用地址空间随机化(ASLR):

sudo sh -c 'echo 0 > /proc/sys/kernel/randomize_va_space'

现在你可以尝试缓冲区溢出攻击,我建议阅读Smashing the Stack for Fun and Profit编辑: 正如我在评论中所说,可以假设在您的任务中禁用堆栈保护是可以接受的,但是,如果您想要绕过堆栈保护,您应该检查与canaries相关的SOF问题,例如这些问题: Is there any way to bypass SSP (StackSmashing Protection)/Propolice?

有没有一种方法可以直接在不设置任何参数的情况下破坏堆栈? - JustForTest
你的作业要求利用缓冲区溢出,我认为可以假设禁用堆栈保护是可以接受的,否则问题就会变得更加复杂。 - iabdalkader
@Job 谢谢!我总是忘记那个 :) - iabdalkader
@mux为什么我不能简单地向randomize_va_space文件中输出“0”? - JustForTest
@JustForTest,您需要以root身份执行整个命令才能这样做。 - iabdalkader
显示剩余3条评论

1

当然有方法可以规避堆栈保护(称为堆栈金丝雀),尽管在您的示例中这并不容易。请参见我的答案此处,了解一些堆栈金丝雀的弱点。


你能给一个简单可行的例子来说明栈保护吗? - JustForTest
@JustForTest:恐怕不行。在你的例子中,规避堆栈保护机制的唯一方法是用相同的值覆盖它。由于没有内存泄漏漏洞,这样做的唯一方法就是暴力破解,这可能不可行... - mtvec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接