gcc-stack-protector机制

简介: gcc-stack-protector机制

GCC "stack smashing detected"机制


相信使用C/C++语言开发软件的程序猿们都经历过‘栈溢出’的问题。‘栈溢出’问题通常十分的隐蔽,有的时候问题复现也十分的困难。每当软件出现莫名其妙的问题时,总是有人怀疑是不是栈溢出了,但是问题的排查又十分的困难,所以,‘栈溢出’就是广大C/C++开发者的噩梦。大家不禁要问有没有通用的方法来避免或者来检测’栈溢出‘问题呢?其实,’栈溢出‘问题有的时候是没有办法避免的,即使是经验丰富的程序猿同样可以陷入’栈溢出‘的陷阱,相信大家都听说过很多知名的软件系统由于‘栈溢出’而导致的各类安全问题。为了减少‘栈溢出’的出现几率,我们平时在编写代码的时候要时刻注意栈上的缓冲区的使用方式,熟悉关于栈缓冲区的各种操作API(使用最为频繁的就是字符串操作函数)的正确使用方式。但是,人总有犯错误的时候,那有没有一种机制来检测‘栈溢出’呢?今天要说的就是gcc编译器提供关于stack保护的各种机制。 首先,来看一个比较明显的栈溢出的代码段,本段代码的编译平台为:Ubuntu14.04 Gcc的版本为4.8.4。代码内容如下:


#include <string.h>
#include <stdio.h>
int main(void)
{
    char array[5] = {0};
    strcpy(array, "stackoverflow");
    return 0;
}


该段代码,首先定义了一个char型数组,数组大小为5,然后我们使用strcpy函数拷贝字符串“stackvoerflow"到array缓冲区,很明显array缓冲区溢出了,稍后会介绍strcpy的使用方式。


然后,我们编译运行,结果如下:


lhl@lhl-Aspire-4930:~/技术总结/linux/gcc$ ./buscore 
*** stack smashing detected ***: ./buscore terminated
已放弃 (核心已转储)


可以看到程序崩溃了,而且还有一些提示信息:


*** stack smashing detected ***: ./buscore terminated


该提示信息就是gcc提供的栈溢出保护机制在检测到程序存在缓冲区溢出时所打印出来的提示信息。那gcc提供栈溢出保护机制是什么呢?


通过查看gcc的使用手册,我们可以知道该报机制为gcc的-fstack-protector一系列选项所提供的缓冲区溢出检测机制。下面为该机制的原理介绍:


当-fstack-protector启用时,当其检测到缓冲区溢出时(例如,缓冲区溢出攻击)时会立即终止正在执行的程序,并提示其检测到缓冲区存在的溢出的问题。这种机制是通过在函数中的易被受到攻击的目标上下文添加保护变量来完成的。这些函数包括使用了allcoa函数以及缓冲区大小超过8bytes的函数(此处不是很明白,上面的例子缓冲区大小为5同样触发了该机制)。这些保护变量在进入函数的时候进行初始化,当函数退出时进行检测,如果某些变量检测失败,那么会打印出错误提示信息并且终止当前的进程。


注意:在测试过程中,当缓冲区的大小小于8bytes同样触发了该机制。在函数中使用了alloca函数后,缓冲区溢出后但没有触发该机制,不知为何?


char *stack_ptr = alloca(0);
    char *str = "hello, world";
    strcpy(stack_ptr, str); 
    printf("stack_ptr = %s\n", stack_ptr);
    上面的代码并不能触发该机制?


那问题来了,-fstack-protector真的是万能的吗?它真的可以检测一切栈溢出的问题吗?我们可以通过下面的例子测试一下:


#include <alloca.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
    char str[2];
}overflow_t;
int main(void) 
{
char *str = "welcom to China";
    overflow_t v;  
    printf("sizoef(v) = %d\n", sizeof(v));
    memcpy(&v, str, strlen(str));
    printf("v.str = %s\n", v.str);
}


gcc buscore.c -o buscore,我们编译运行结果如下:
sizoef(v) = 2
v.str = welcom to China


我们看到程序正常执行了,并没有触发栈溢出检测?这是为什么呢?通过进一步查阅gcc手册,发现其还提供一个-fstack-protector-all选项,其解释为:


其功能类似于-fstack-protector,但是其为所有的函数都进行栈溢出检测。重新编译程序,并加上-fstack-protector-all选项,然后运行结果如下:


sizoef(v) = 2


v.str = welcom to China *** stack smashing detected ***: ./buscore terminated 已放弃 (核心已转储)。可以看到进程成功的检测到了栈溢出。


所以,我们在开发软件时,最好加上-fstack-protector-all选项,这很大一部分栈溢出问题就会被探测到。


同时我们也应该注意到,当进程由于栈溢出崩溃时,会产生coredump文件,对于coredump的配置可以参见Android系统coredump这篇文章。 那怎么根据coredump文件定位问题呢?上面介绍-fstack-protector机制的原理时,说过其会在函数退出时进行检测,这样我们就可以根据coredump中的函数栈信息定位到发送栈溢出的函数,这样问题的范围就大大缩小了,我们可以专注于查看出问题的函数,然后定位出哪里存在栈溢出。



相关文章
|
SQL Oracle 关系型数据库
|
安全 C++ Windows
好工具推荐系列:VC++开发必备神器 -- Dependencies,查看依赖库DLL,支持win10,比depends更好用
好工具推荐系列:VC++开发必备神器 -- Dependencies,查看依赖库DLL,支持win10,比depends更好用
4302 0
好工具推荐系列:VC++开发必备神器 -- Dependencies,查看依赖库DLL,支持win10,比depends更好用
|
8月前
|
数据采集 搜索推荐 前端开发
鸿蒙HarmonyOS埋点SDK,ClkLog适配鸿蒙埋点分析
ClkLog鸿蒙埋点SDK通过手动埋点的方式实现HarmonyOS 原生应用的前端数据采集。快速接入即可获取埋点数据,同时支持分析功能(基础统计分析、自定义分析、用户画像等)。
352 59
|
安全 测试技术 网络安全
除了安全的编程实践,还有哪些常见的缓冲区溢出攻击防范方法?
【10月更文挑战第20天】综上所述,防范缓冲区溢出攻击需要综合运用多种方法,从系统安全机制增强、漏洞检测与修复、网络安全防护到安全策略与管理等多个层面入手,形成全方位的安全防护体系,才能有效地抵御缓冲区溢出攻击,保障计算机系统和网络的安全。
|
机器学习/深度学习 人工智能 编解码
深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
【9月更文挑战第2天】深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
 深入探索AI文生语音技术的奥秘:从文本输入到逼真语音输出的全链条语音合成过程解析
|
开发框架 前端开发 机器人
从模型到前端,你应该知道的LLM生态系统指南
LLM在在2023年发展的风生水起,一个围绕LLM的庞大生态系统正在形成,本文通过介绍这个生态系统的核心组成部分,来详细整理LLM的发展。
1023 2
|
芯片
EDA设计:原理、实践与代码深度解析
EDA设计:原理、实践与代码深度解析
899 2
|
测试技术 编译器 C#
一篇文章讲明白hook(钩子程序)(转载)
一篇文章讲明白hook(钩子程序)(转载)
762 0
|
网络协议 Linux
Linux内核源码剖析之TCP保活机制(KeepAlive)
总之,TCP保活机制通过定期发送保活探测报文,以检测空闲连接是否仍然活跃。这种机制在网络通信中有助于及时检测和关闭不再使用的连接,从而节省资源并提高连接的可靠性。
630 0