文档章节

一种处理栈越界的方法

悬崖
 悬崖
发布于 2016/04/14 11:00
字数 1688
阅读 112
收藏 1

作者:吉林小伙
链接:http://zhuanlan.zhihu.com/p/20642841
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在linux下,栈越界写坏返回地址会导致调用栈无法回溯,这就导致我们直接使用bt没有办法查看崩溃时调用栈,今天我讲一下我最近研究出来的一种方法(虽然是原创,但可能互联网上早有人发布过此种方法,只不过我没有查到而已).

废话少说,步入正题,首先我写了个简单的程序来构造一个栈溢出的情况,为了使效果更加明显,我使用了一些递归来增加调用栈的深度,代码如下:

不要吐槽命名方式,我也知道很丑,栈都能越界的程序,一定漂亮不到哪去,哈哈!

简单描述下这个代码的功能,func2里递归调用了func2,这样能有效增加调用栈深度,然后调用func3的时候,由于func3里写buf越界了,导致栈被破坏了,然后段错误崩溃.崩溃后生成了core文件,我们用gdb打开,输入bt,效果如下:

由于栈破坏有很多种方式,bt也有可能显示出一排??,总之栈破坏很有可能导致bt无法回溯就是了.那我们如何应对呢?我们首先来看一下调用栈的一些知识:

一般情况下,在调用函数之前,(部分)参数会放入栈内,然后执行汇编指令call, 执行call后会自动将返回地址压入栈中,然后执行被调用函数,被调用函数开头的两条汇编指令很可能是:
push rbp
mov  rbp,rsp
这两条指令的作用就是把rbp压入栈中,把栈顶指针rsp赋值给rbp,这样在栈内就会形成一个 链表,以便我们回溯调用栈.
注意:
在开启优化的时候,默认是 -fomit-frame-pointer,这样可能导致很多函数开头不会出现那两条汇编指令,-fno-omit-frame-pointer选项开启后就会生成以上两条指令.

好了,详细的栈资料请大家自行查阅资料学习,我就不再赘述了.你只要知道调用栈在栈内是以链表的方式保存即可.那栈越界写坏的地方我们可以认为是链表的头部,由于链表的头部被写坏了,导致gdb的bt指令无法回溯调用栈了.

既然如此,那我们可以再找一个节点作为链表的头部.只不过回溯的调用栈可能比"完美"的调用栈少那么一两条,不过半个面包总比没有好,说干就干:

上图的代码是gdb的扩展,我扩展了一个bts(backtrace stack)指令,其作用是打印给定addr后的count条内容.gdb中可以使用source指令来加载扩展,也可以在home路径下新建.gdbinit文件,将脚本内容写入,这样在gdb启动时就会自动生效,我们使用source .gdbinit来加载一个这个bts扩展指令.然后在gdb里输入i r rsp指令:

,rsp的值一般情况下是栈顶,不过不排除这个值是不对的,只是不对的概率比较小而已,然后键入指令:

(gdb) set pagination off
(gdb) set loggin on ./log
Copying output to ./log.
(gdb)bts 0x7fff81f7c250 1000

第一条指令的作用是关闭"超过一屏内容等待键入回车"功能,第二条是打开log,这样gdb里的输出就会写入log文件内,第三条就是我们写的扩展指令了,执行一下,等待结果写入到文件中吧.由于我们的测试程序很短,栈也没用多大,所以1000应该就可以了,实际程序中这个1000可能要变得很大,可能要跑几分钟,不过我很享受这几分钟,因为我就喜欢敲入一条命令然后屏幕刷刷滚的感觉,逼格高,哈哈!!

跑题了,好了,输出结束我们去看看./log文件,执行head ./log命令,结果如下:

这正是我们想要的内容,第一列是栈地址,第二列是该地址的内容,既然调用栈在栈内是链表,那我们就可以写个代码把栈内所有的链表都暴力搜出来,然后看下哪个最可能是调用栈.

这是我写的暴力搜索栈中链表的程序,其实大家完全可以用脚本写,比c++方便多了.好了,g++ stack.cpp -o stack编译一下,然后执行:

./stack log 100 > symbol

log就是我们的log文件了,100呢是调用栈的深度,当你指定100的时候,会把所有调用栈深度为100的链表打印出来,由于我们递归超过100次了,所以这里我就指定100了,如果你在实际应用中,100没有结果,那可以尝试逐渐减小这个数值,然后我们看看symbol里的内容:

大概是这样的,还有好多条,我只截取了部分,之所以有info symbol,是因为我要在gdb中加载这个symbol文件,加载后会自动执行info symbol address,作用就是打印出这条地址附近的符号:

(gdb)source ./symbol

此处应该有掌声!!!

从下往上看,依次是__libc_start_main()->main()->func1()->func2()...,这的确是我们程序中的调用栈,只不过丢失了func3而已.

最后总结一下,此片专栏只是提供一种解决方法而已,具体能否成功,要看运气了.我一直觉得调试找bug是要看运气的,尤其是那些偶然出现的crash,在你不知道原因无法重现时只能从core dump里寻找蛛丝马迹了.

经验:一般栈越界很有可能是字符串越界,此时可以查看rsp附近的内存,说不定有很明显的字符串,一下就定位问题了呢.

由于水平有限,文章中有错误在所难免,请大家包含并指教,谢谢!

-----------------------------------------------

更新一下暴力搜索调用栈的那个代码,其中有一处bug可能导致在遍历调用栈的时候死循环.更新后如上图所示,这样就不怕栈里有回路了,还有一处修改,这个地方用sizeof(void*),就兼容32bit 64bit的程序了,以前写的8只支持64bit的程序


本文转载自:http://zhuanlan.zhihu.com/p/20642841

共有 人打赏支持
悬崖
粉丝 3
博文 54
码字总数 22549
作品 0
海淀
程序员
3.10 在机器级程序中将控制与数据结合起来

3.10.1 理解指针 指针是C语言的一个核心特色,它提供了一种统一方式,对不同数据结构中的元素产生引用。 每个指针都对应一个类型,void *类型代表通用指针,它通过强制或隐式类型转换变成一个...

ShutLove
04/20
0
0
Java数据结构与算法(三)-栈和队列

1.栈 先进后出,后进先出 栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素...

FantJ
2017/12/21
0
0
Java十大低级错误

1、Java十大低级错误 不能用"=="比较两个字符串内容相等。 对list做foreach循环时,循环代码中不能修改list的结构。 日志和实际情况不一致;捕获异常后没有在日志中记录异常栈。 魔鬼数字。 ...

周东尧
2016/03/30
118
2
只会左键断点?是时候试试这样那样断点了

文本是投稿文章,作者:空之境界(博客) 编码不能没调试,调试不能没断点(Break Point)。XCode的断点功能也是越来越强大。 基本断点 如下图,这种是最常用的断点,也是最容易设置。左键点...

TomatosX
2015/08/01
0
0
Flash 0day漏洞(CVE-2018-5002)千万不要乱打开Excel文档!

腾讯御见威胁情报中心近日监控到一例使用Adobe Flash 0day漏洞(CVE-2018-5002)的APT攻击,攻击者疑通过即时聊天工具和邮箱等把恶意Excel文档发送给目标人员,诱骗目标人员打开文档。实际上...

网站安全
06/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

活动招募 HUAWEI HiAI公开课·北京站-如何在4小时把你的APP变身AI应用

人工智能和机器学习是全球关注的新趋势,也是当前最火爆、最流行的话题。当你拿手机用语音助手帮你点外卖,智能推荐帮你把周边美食一网打尽;当你拿起P20拍照时,它将自动识别场景进行最美优...

华为终端开放实验室
32分钟前
1
0
匹配两位小数,js正则

var regex = /^\d*(\.[1-9]|\.\d[1-9])*$/ console.log(1.2,regex.test(1.2)); console.log(0.3,regex.test(0.3)); console.log(1.03,regex.test(1.03)); ......

微信小程序-暗潮
37分钟前
1
0
905. Sort Array By Parity - LeetCode

Question 905. Sort Array By Parity Solution 题目大意:数组排序,偶数放前,奇数在后,偶数的数之间不用管顺序,奇数的数之间也不用管顺序 思路:建两个list,一个放偶数,一个放奇数,最...

yysue
41分钟前
1
0
h5 禁止手机自带键盘弹出

html: <div style="width: 350px;margin:50px auto;"><input type="text" id="datePicker" class="date_picker form-control" placeholder="点击选择入住日期" /></div> js: $("#date......

Delete90
58分钟前
1
0
color透明度对照表

透明度百分比 数值 100% 不透明 FF 95% F2 90% E6 85% D9 80% CC 75% BF 70% B3 65% A6 60% 99 55% 8C 50% 80 45% 73 40% 66 35% 59 30% 4D 25% 40 20% 33 15% 26 10% 1A 5% 0D 0% 完全透明 ......

_无问西东
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部