gcc-stack-protector
以堆栈溢出为代表的缓冲区溢出已成为最为普遍的安全漏洞,由此引发的安全问题比比皆是。我们知道攻击者利用堆栈溢出漏洞时,通常会破坏当前的函数栈。
那有没有一种机制来检测“栈溢出”呢?---- 在gcc中,通过编译选项可以添加 函数栈的保护机制,通过重新对局部变量进行布局来实现,达到监测函数栈是否非破坏的目的。
gcc中有3个与堆栈保护相关的编译选项
- -fstack-protector:启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码。
- -fstack-protector-all:启用堆栈保护,为所有函数插入保护代码。
- -fno-stack-protector:禁用堆栈保护。
首先,来看一个比较明显的栈溢出的代码段:
#include <string.h>
#include <stdio.h>
int main(void)
{
char array[5] = {
0};
strcpy(array, "stackoverflow");
return 0;
}
该段代码,首先定义了一个char型数组,数组大小为5,然后我们使用strcpy函数拷贝字符串“stackvoerflow”到array缓冲区,很明显array缓冲区溢出了
然后,我们编译运行,结果如下:
./a.out
*** stack smashing detected ***: terminated
已放弃 (核心已转储)
可以看到程序崩溃了,而且还有一些提示信息:
*** stack smashing detected ***: terminated
该提示信息就是gcc提供的栈溢出保护机制在检测到程序存在缓冲区溢出时所打印出来的信息,那么gcc提供的栈溢出保护机制是什么呢?
通过查看gcc的使用手册,我们可以知道该机制为gcc的-fstack-protector一系列选项所提供的**缓冲区溢出检测机制。**下面为该机制的原理介绍:
*当-fstack-protector启用时,当其检测到缓冲区溢出时(例如,缓冲区溢出攻击)时会立即终止正在执行的程序,并提示其检测到缓冲区存在的溢出的问题
- 这种机制是通过在函数中的易被受到攻击的目标上下文添加变量来完成的。这些函数包括使用了allcoa函数以及缓冲区大小超过8bytes的函数(此处不是很明白,上面的例子缓冲区大小为5同样触发了该机制)。这些保护变量在进入函数的时候进行初始化,当函数退出时进行检测,如果某些变量检测失败,那么会打印出错误提示信息并且终止当前的进程。
cmake中使用堆栈保护机制
if (NOT WIN32 AND NOT HAIKU)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wstack-protector")
endif()
原理:待研究