gcc-stack-protector机制【转】

转自:https://blog.csdn.net/lhl_blog/article/details/70193865

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/linux_embedded/article/details/70193865 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 1 该提示信息就是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中的函数栈信息定位到发送栈溢出的函数,这样问题的范围就大大缩小了,我们可以专注于查看出问题的函数,然后定位出哪里存在栈溢出。 ———————————————— 版权声明:本文为CSDN博主「奔跑的码仔」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lhl_blog/article/details/70193865

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI科技评论

业界 | 美图推出业界最大规模教程类行为数据集 | CVPR 2019

AI 科技评论按,计算机视觉顶会 CVPR 2019 即将于 6 月在美国长滩召开,今年有超过 5165 篇的大会论文投稿,最终录取 1299 篇。随着会议临近...

7510
来自专栏AI科技评论

干货 | 漫画:什么是Bitmap算法?

AI 科技评论按,本文本文来自公众号“程序员小灰”(ID:chengxuyuanxiaohui),原载于知乎,AI 科技评论获授权转载。

9820
来自专栏大学生计算机视觉学习DeepLearning

关于C#界面开发winform与SharpGL结合鼠标只在OpenGLControl绘图区域显示坐标移动消息响应(c#鼠标单独在某个控件上的消息响应)

原文链接:https://www.cnblogs.com/DOMLX/p/11773260.html

8830
来自专栏BanzClub

Zookeeper简介

“Zookeeper是一个开源的,为了解决分布式应用协调的服务,具有低延迟、高可用等特点。”

11120
来自专栏AI科技评论

亿级学术图谱 Open Academic Graph 更新至 2.0 版本:包含约 7 亿实体数据、20 亿关系

AI 科技评论按:继 2017 年 8 月份首度联合发布开放学术图谱(Open Academic Graph, OAG),近日,清华大学和微软研究院再度携手将 ...

9320
来自专栏AI科技评论

干货 | 强化学习中,如何从稀疏和不明确的反馈中学习泛化

AI 科技评论按,强化学习(RL)为优化面向目标的行为提供了一个统一而灵活的框架,在解决诸如玩电子游戏、连续控制和机器人学习等具有挑战性的任务方面取得了显著的成...

4920
来自专栏武培轩的专栏

Nginx 了解一下?

如图所示,一个请求会先经过 Nginx 到达应用服务层,然后再去访问数据层(比如 Redis、MySQL 等),提供基本的数据功能。我们的应用服务因为要求开发效...

7320
来自专栏Java那些事

面试官:谈谈你对mysql索引的认识?

其实这下面每个问题,我都可以讲一篇文章出来!而且这些问题,不是我凭空编的。如下图所示(注意看第三题)

9320
来自专栏程序员小明

数亿的用户,如何统计独立用户访问量?

众所周至,拼多多的待遇也是高的可怕,在挖人方面也是不遗余力,对于一些工作3年的开发,稍微优秀一点的,都给到30K的Offer,当然,拼多多加班也是出名的,一周上...

19720
来自专栏Java开发者杂谈

一文理解java对象初始化顺序

​ 由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang....

9630

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励