内存飞踩问题的几点思考
1、程序编译,链接后生成二进制可执行程序。二进制可执行文件以elf格式实现排列。可以通过readelf -S xxxx查看具体section的划分,粗略划分如下图所示。
在这些section中,代码段是只读的,自然也就不存在代码(指令)被改写的情况。数据段,堆,栈区具有读写的属性,但是数据段和堆一般存放的是数据,不涉及到指令的问题。剩下的栈区,存放的既有数据,又有代码(指令),可能存在代码(指令)被改写,即内存被飞踩现象。
2、栈空间数据被修改情况
2.1、先做个实验(ARM 32环境)
2.1.1、栈区空间
#include <unistd.h>
#include <stdio.h>int do_nothing(int a)
{return a;
}int max(int a,int b)
{int c = 0;do_nothing(c);return a + b;
}int main()
{int res = 0;int a = 1;int b = 2;res = max(a, b);return res;
}
arm-linux-gcc func.c -o func
arm-linux-objdump -d func > func.txt
查看反汇编结果
00010490 <max>:10490: e92d4800 push {fp, lr} ;把bl <max>的下一条指令地址lr保存到栈区10494: e28db004 add fp, sp, #410498: e24dd010 sub sp, sp, #16 ;确定好栈区大小1049c: e50b0010 str r0, [fp, #-16]104a0: e50b1014 str r1, [fp, #-20] ; 0xffffffec104a4: e3a03000 mov r3, #0
增加max函数的局部变量个数,再查看相对应的反汇编
int max(int a,int b)
{int c = 0;int d = 0;int e = 0;c = d;do_nothing(c);return a + b;
}
00010490 <max>:10490: e92d4800 push {fp, lr}10494: e28db004 add fp, sp, #410498: e24dd018 sub sp, sp, #24 ;栈区空间增大1049c: e50b0018 str r0, [fp, #-24] ; 0xffffffe8104a0: e50b101c str r1, [fp, #-28] ; 0xffffffe4104a4: e3a03000 mov r3, #0
由此可见,栈区的大小在程序编译的时候就已经确定。存放着函数退出后下一条指令的地址和局部变量的数值。
2.1.2、栈区数据
#include <stdio.h>
#include <string.h>int do_nothing()
{printf("nothing\n");
}int func(int i)
{int a = 6;int b = 0;int *p = NULL;char num[3] = {0x6d, 0x04, 0x01};p = &b;printf("b addr=0x%x, func=0x%x\n", p, do_nothing);printf("stack value:0x%x, 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", *(p + 1), *(p + 2), *(p + 3), *(p + 4), *(p + 5), *(p + 6), *(p + 7), *(p + 8));
// memcpy((char *)(p+8), num, 3);return a * i;
}int main(void)
{int i = 1;func(i);i++;return i;
}
从局部变量中,获取栈区地址,打印栈区里面的部分数据。
第一个红框存放着局部变量的数据,第二个红框存放着退出函数后下一条指令的地址,可以从反汇编中确认。
2.1.3、修改栈区数据,其中存放的下一条指令的地址0x10545被改写,程序运行是不是就会出现异常。
上图截图中绿框所示,对应着是另外一个函数do_nothing的地址,假如把栈区0x10545的数据改写成do_nothing的地址,应该就会执行do_nothing的函数。
释放2.1.2代码的memcpy处注释,运行程序,程序果然执行了do_nothing的函数
2.2、上述假如被踩的数据是其他值,程序就可能会直接崩溃。而当程序出现崩溃时,数据可能在崩溃前的某一时刻就被修改,出现崩溃的现场并不是第一现场,很难定位。如下面的代码:
void fun(void) {char arr[5];strcpy(arr, "are you ok.are you ok.");return;
}
2.3、可以在编译的时候添加-fstack-protector-all编译选项,减少定位难度(哪位大侠有更好的定位手段,在评论区求赐教),不至于代码跑飞,艰难查找到第一现场。
gcc stack.c -fstack-protector-all -o stack
没有添加-fstack-protector-all编译选项出现异常时的日志
此core_dump很难查找到问题原因,因为出现异常的地方不是第一现场。
2.4、栈区被踩问题的定位手段
栈区数据被飞踩问题定位手段_sydyh43的博客-CSDN博客
3、GOT表被修改情况
3.1、可以先看看下面的这篇分析
动态库*.so的延时绑定分析_sydyh43的博客-CSDN博客
打开git源码中的Makefile屏蔽和main函数的#if 0既可。
3.2、如以下的代码
int arr[2]; //arr数组是全局变量void fun(void) {arr[-8] = 0xFF;return;
}
3.3、这种内存被踩的情况一般不会出现,因为编译器默认会把relacation后的GOT表设置成只读。
4、综上所述,关于内存被踩的问题,需要编译的时候做好准备。在编译的时候添加编译选项,出现问题的时候可以保留第一现场。编译选项添加情况可以通过checksec.sh脚本校验,详见:
linux程序的常用保护机制 | 上善若水
内存飞踩问题的几点思考相关推荐
- 内存泄漏 内存溢出 踩内存 malloc底层实现原理
本文主要对内存泄漏.内存溢出.内存踩踏[踩内存]以及malloc的底层实现原理进行了总结.话不多说,直接往下看: 参考文章: 内存泄漏与内存溢出: https://blog.csdn.net/ruir ...
- 关于iphone、QQ通讯录、飞聊联系人排序设计的思考
目前,对于联系人的排序,如果不考虑对方的在线状态,一般都是按照音序排序的.所谓音序排序,也就是拼音字母的顺序:首先是按照整个拼音的首字母(26个字母从A~Z)的顺序排列,如果首字母相同,则依次按照声母 ...
- java构建内存池队列_内存池完整实现代码及一些思考
为了提高效率和有效的监控内存的实时状态,我们采取了内存池的思想来解决效率与对内存实现监控的问题. 网上查找到了一些方案,根据自己的理解实现了应用. 我们什么时候要调用到内存池, 1,当我们频繁的申请释 ...
- C语言系统内存被踩情况总结
C语言由于可以直接操作内存,给我们的编程带来了便利,同时也带来了内存写越界之类的问题,常常造成我们的系统crash.下面总结了我在工作中碰到的导致内存越界的各种场景,以供分析此类问题时作个参考. 1. ...
- 栈区数据被飞踩问题定位手段
1.栈溢出或者栈数据被踩时,继续运行就会出现segmentation fault.可以尝试着接管SIGSEGV信号,在信号处理函数中保存一些出现异常时候的信息. 2.基于栈溢出场景,栈空间被破坏,也就 ...
- 简记H2 Database内存数据踩过的坑
开发入门步骤: 一.maven中添加依赖项 <dependency><groupId>com.h2database</groupId><artifactId& ...
- linux踩内存怎么定位,问题定位:内存泄漏,踩内存。
1.内存泄漏 确定现象: linux 内存泄漏,可以查看slabinfo 和另外一个proc下(貌似meminfo),关于内存的信息,可以看到内存是否在不断减少,以及减少的速度. vxworks系统, ...
- 使用mprotect定位踩内存故障
前言 对于 C 语言来说,内存被踩是比较常见的问题,轻则普通变量被改写程序逻辑出错,重则指针变量被改写引发指针解引用出现未定义行为风险: 定位内存被踩一直是棘手的难题,如果出现程序跑死,一般可以通过堆 ...
- 全局变量同名导致踩内存
今天遇到一个诡异的内存被踩的问题,后来发现是一个全局变量与另一个静态库中的全局变量重名了, a.c: #include <stdio.h>int g_ctx = 0; int g_over ...
最新文章
- linux 怎么删除大文件,如何在Linux中删除超大的(100-200GB)文件
- oracle pga的作用,浅析Oracle中PGA和UGA两者间的区别
- 因果关系和相关关系 大数据_数据科学中的相关性与因果关系
- 关于JFace中的向导式对话框(WizardDialog类)
- 小程序 图片上传php后台,微信小程序图片选择、上传到服务器、预览(PHP)实现实例...
- 谷歌终于拒绝 AI 武器化了!
- Jepack4.5.1上手动安装cuda10.0 cudnn 7, Jepack4.5.1 TX2 i安装pytorch1.6.0
- Spring学习(下)
- SPSS做因子分析(非常细致的过程)
- 【PS】抠图教程(0基础快速入门)
- 【概率论与数理统计】1.5 独立性
- Goldendict 及其词典详述
- 三星S5终于降临 4月上市开卖的新机盘点
- 华为云冰山安全,让用户安心用云
- 聚焦2019世界人工智能大会:看马斯克、马云“唇枪舌战”,谁更胜一筹?
- element filtername is not allowed here
- 基于SphereFace深度学习的人脸考勤系统(Caffe+windows+OpenCV)
- pusher 创建新应用_laravel之pusher应用广播事件- 黑白课堂
- Direct exchange
- Windows下利用Ghost32一次性完成U盘版PE的制作
热门文章
- 计算机教室展台,多媒体教室视频展示台的系统.ppt
- 《风尚坐火箭学习vue》-- 第二章:页面中输出hello Vue
- 淘宝API图片尺寸的缩略图解决办法
- clumsy一款模拟弱网的工具
- ping命令详解 ping命令入门详解
- indexof java_Java中indexOf的用法
- 三门峡大坝和小浪底水库,是不是相互依存的关系?
- androidAPP 接入微信/支付宝支付,获取应用的签名(随笔)
- Spark中mapToPair和flatMapToPair的区别【附示例源码及运行结果】
- 量子计算机作文材料,作文素材:九章问世,量子科技,你该知道的世界!.docx...