关于C#:缓冲区溢出的编译器艺术

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 堆栈粉碎保护吗?


编译时应禁用堆栈保护:

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?


当然有一些方法可以绕过堆栈粉碎保护(称为堆栈金丝雀),尽管在您的示例中并不容易。有关堆栈金丝雀的一些弱点,请参阅我的答案。