汇编角度解释溢出段错误
来源:互联网 发布:html css js源码下载 编辑:程序博客网 时间:2024/06/06 22:49
在编写代码时,由于读写了系统保护的内存或者访问了给定地址以外的内存地址,这时会发生段错误,直接性的结果就是代码出错退出,这也仅仅是系统唯一能让我们直观的可知这是发生段错误了,但是对代码在系统中的运行情况以及内存情况一无所获,因为高级语言屏蔽了这些底层的实现。但是所有的语言编译的最终可执行代码都是1和0形式的机器代码,机器代码由汇编语言编译而成,所以汇编是低级语言即直接可以操作内存。下面来用汇编来解释段错误:
C代码
int test_fun1(char * ptr)
{
memcpy(ptr,"1234567890",strlen("1234567890"));
return 0;
}
int test_fun2()
{
char buf[5];
test_fun1(buf);
return 0;
}
代码test_fun2的汇编形式
mov %esp,%ebp
subl $20,%esp
leal -8(%ebp),%ebx
mov %ebx,(%esp)
call test_fun1
ret
栈结构图:
因为函数test_fun1中向ptr指向的内存写了10个字节的数据,而这块内存大小只有5个字节,所以它会把%ebp的备份覆盖以及test_fun2的函数的返回地址,所以当它返回时会出错的。
段错误不紧影响代码的运行及维护,而且往往会变成黑客入侵的入口,黑客一般分三步来攻击(借助段错误攻击):
1.定位栈
2.放置可执行代码
3.进行溢出操作,用上面可执行代码地址来覆盖程序中的某个地址,以达到程序运行到覆盖的地点时,执行黑客代码
比如上面那段测试代码,黑客就会找到该函数的栈,然后对ptr指向的内存写入足够覆盖返回地址的数据,一般覆盖返回地址的数据是指向另一端黑客的代码地址,当函数返回时,因为已经覆盖,所以直接跳转到黑客的代码,这时你的机器就被黑客控制了。
因为黑客是依靠上述三步来进行攻击,那么现在的操作系统也从这三方面进行了安全提升:
1.随机地址
用户代码编译后的栈地址是不定的
2.可执行代码区域进行限制
现在的栈可读可写不能执行
3.系统在代码中放置数据检测是否发生溢出
如test_fun2的添加了检测数据的汇编形式
push %ebp
movl %esp,%ebp
subl $20,%esp
movl %gs:20,-4(%esp)
leal -12(%ebp),%ebx
mov %ebx,(%esp)
call test_fun1
movl -8(%ebp),%eax
xorl %gs:20,%eax
je .L1
call __stack_chk_fail
.L1
ret
栈如图:
在存放buf地址的后面加存放了%gs:20,当调用完函数test_fun1时,执行xorl%gs:20,%eax,检测存放的值有无改变,如果已经改变了则异常退出,否则正常执行返回。
所以在现代系统中,只要发生了溢出系统都会检测到并异常退出程序。
虽然现在的系统都对段错误添加了多种手段来检测段错误,预防黑客借助段错误攻击,但是一个良好的编程习惯,条理清晰的逻辑结构是最好的预防段错误的方法,编程时不要边想边写,而是在编码之前把整个需要实现的功能,以功能实现过程的逻辑结构画出来,然后根据这个结构图再编程。
- 汇编角度解释溢出段错误
- 从汇编的角度看段错误
- 段错误与栈溢出
- 段错误与栈溢出
- 随笔: 段错误, 数字大小溢出
- 反汇编角度解释C++语言中引用的原理
- 基础概念:从概念及汇编角度解释指针本质
- 从概念及汇编角度解释指针本质
- 指针 段溢出 段错误的自我学习
- 通过反汇编定位段错误
- 利用反汇编帮助查找段错误
- 汇编溢出
- 函数栈溢出引起的段错误segmentation fault
- 函数栈溢出引起的段错误segmentation fault
- 关于段错误和栈溢出的问题
- (转)基础概念:从概念及汇编角度解释指针本质
- 计算机基础知识--汇编溢出
- 汇编 溢出 解析
- windows编程之动态链接库的使用
- 大话设计模式———c++反射机制实现
- mssql 按月统计,按日统计,按周统计,按季度统计
- 图像的基本函数运算
- Linux学习之路
- 汇编角度解释溢出段错误
- 标签、css、
- toascii字符串转换函数应用实例
- iOS 10 新特性
- 学习总结01
- java中ArrayList应用实例
- JS-正则表达式1
- 程序员的基础生存技能:高效用Google
- c++代码习惯