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调试它时,它总是首先将内存分配给整数变量然后分配字符数组; 无论变量声明的顺序是什么。
即在上述两种情况下,编译器首先将内存分配给a
,然后分配给b
。
(higher address)
Memory
| |
| |
+--------+
| |
| |
| |
| |
+--------+ <----- b (16 bytes)
| |
+--------+ <----- a (4 bytes)
| |
(lower address)
因此,即使我们在str
中提供超过16个字符,也不会影响a
的值。
有人可以帮帮我吗?
谢谢。
答案 0 :(得分:11)
是的,如果使用-fstack-protector
标志运行。
当使用该标志运行时,GCC添加堆栈canaries,将数组变量排序到堆栈帧的最高部分,使其更难以溢出它们并破坏其他变量,并使函数参数的副本与其他当地人。
有关详细信息,请参阅Wikipedia page on Buffer overflow protection和ProPolice主页
答案 1 :(得分:2)
即使GCC具有防止缓冲区溢出的功能,此处还有许多其他注意事项可能会导致固定的变量声明顺序。如果声明不是很重要,编译器将根据变量在运行时使用的时间和方式来做出分配决策。
最重要的是,编译器有望在堆栈框架中分配变量,并考虑到最佳的对齐方式。这取决于CPU和优化设置,可以以完全不同的方式进行。与优化内存消耗相比,优化速度可能会提供完全不同的分配。最有可能的是,它会在CPU寄存器中放入一些变量,从而消除整个RAM分配需求。
所以回答你的问题:GCC以各种方式分配变量,具体取决于编译器端口。如何做到这一点,并不是程序员需要过分关注的事情。可能有选项重新排列堆栈以防止缓冲区溢出攻击,但这只适用于某些类型的应用程序。据我们所知,甚至可能没有对特定系统的任何输入。因此,编译器默认启用此安全功能是没有意义的。
答案 2 :(得分:-1)
gcc是否智能地进行内存分配以防止缓冲区溢出攻击?
不,它没有。无法在没有边界检查的情况下阻止攻击或缓冲区溢出,这并非总是可行。事后,您有时只能检测到溢出。
编译器最多可以在堆栈的返回地址附近包含额外的信息(所谓的canary value),并且在从函数返回之前检查它是否完整,并且不会因缓冲区溢出而被覆盖。 / p>