15

gcc 是否智能进行内存分配以防止缓冲区溢出攻击?

int function(char *str) {
    int a = 0;                 // See the
    char b[16] = "abcd";       // changes here

    if(!strcmp(b, str))
        a = 1;

    return a;
}

int function(char *str) {
    char b[16] = "abcd";       // See the
    int a = 0;                 // changes here

    if(!strcmp(b, str))
        a = 1;

    return a;
}

当我用 gdb 调试它时,它总是先分配内存给整数变量,然后是字符数组;不管变量声明的顺序是什么。即在上述两种情况下,编译器首先分配内存ab.

(higher address)
  Memory
|        |
|        |
+--------+
|        |
|        |
|        |
|        |
+--------+ <----- b (16 bytes)
|        |
+--------+ <----- a (4 bytes)
|        |
(lower address)

因此,即使我们在 中提供超过 16 个字符str,也不会影响a. 有人可以帮我吗?

谢谢你。

4

3 回答 3

11

是的,如果带着-fstack-protector国旗跑。

当使用该标志运行时,GCC 添加堆栈金丝雀,将数组变量排序到堆栈帧的最高部分,以使其更难以溢出和破坏其他变量,并将函数参数的副本与其他局部变量一起存储。

有关更多信息,请参阅有关缓冲区溢出保护的 Wikipedia 页面ProPolice主页

于 2013-03-19T09:20:48.517 回答
2

即使 GCC 有这样的功能来防止缓冲区溢出,这里还有许多其他考虑因素可能会导致固定的变量声明顺序。在哪里进行声明并不重要,编译器将根据变量在运行时的使用时间和方式做出分配决定。

最重要的是,编译器希望在堆栈帧中分配变量时考虑到最佳对齐方式。这可以根据 CPU 和优化设置以完全不同的方式进行。与优化内存消耗相比,优化速度可能会给出完全不同的分配。最有可能的是,它会将一些变量放入 CPU 寄存器中,从而消除整个 RAM 分配需求。

因此,回答您的问题:GCC 根据编译器端口以各种方式分配变量。它是如何做到的,不是程序员需要过分关心的事情。可能有一些选项可以重新排列堆栈以防止缓冲区溢出攻击,但这仅在某些类型的应用程序中才有意义。据我们所知,甚至可能没有任何输入到特定系统。因此,编译器默认启用此安全功能是没有意义的。

于 2013-03-19T11:43:40.777 回答
-1

gcc 是否智能进行内存分配以防止缓冲区溢出攻击?

不,它没有。如果没有边界检查,就无法防止攻击或缓冲区溢出,这并不总是可能的。您有时只能在事后检测到溢出。

编译器最多可以在堆栈上的返回地址附近包含额外信息(所谓的金丝雀值),并且在从函数返回之前检查它是否完好无损并且没有由于缓冲区溢出而被覆盖。

于 2013-03-19T09:14:28.097 回答