您的位置:首页 > 理论基础

理解程序调用以及由此引出的缓冲区攻击问题

2016-12-03 15:01 302 查看
在阅读《深入理解计算机系统》第三章,程序的机器级表示的时候,解开了以前学习C语言的时候的一些疑惑,在这里稍做记录。

程序在调用另一个程序的时候涉及下面的这个数据结构——栈帧,这个数据结构是实现整个过程的关键。



调用者程序调用(call指令)另一个被调用者程序的时候,首先调用者程序将将当前程序计数器的值(下一条指令的地址)保存(push)在栈帧中,再跳转到被调用者程序。然后被调用者程序保存原来的帧指针(%ebp),并且跟新%ebp使得它指向栈底,然后通过减少栈指针(%esp)的值给程序自身分配栈空间,用于存放被调用者程序需要保存的寄存器值,被调用者函数所需的局部变量,临时变量,以及需要传递给它所调用函数的参数,最后被调用者程序调用ret指令返回到之前保存的程序计数器的值所指向的程序的地址。

以上是针对IA32架构的,新的x86-64架构,引入了更多的寄存器(从8个到16个)从而对程序调用产生了影响,当然工程师们出于其它原因的考虑还做了优化。总结如下:

参数(最多是前6个)通过寄存器传递到过程,而不是在栈上。这消除了在栈上存储和检索值的开销。

callq指令将一个64位地址存储在栈上。

函数最多可以访问超过当前栈指针128个字节的栈上存储空间。这允许一些函数将信息存储在栈上而无需修改栈指针。

没有帧指针,作为替代,对栈位置的引用相对于栈指针。大多数函数在调用开始时分配所需要的整个栈存储,并保持栈指针指向固定位置。

理解了函数调用的一般原理,下面记录一下缓冲区溢出带来的攻击问题。



其实道理很简单,buf是一个指向局部变量(是一个字符数组)的一个指针参数,传给某个接口,书中以gets为例,但是gets存在漏洞(它不检查buf缓冲区的大小),如果程序用户通过gets输入的字符串大于buf的大小,就会覆盖保存%ebp的地方以及程序的返回地址,如果在返回地址上覆盖上攻击者代码的指针,那么攻击者就可以调用自己的程序胡作非为了。

针对这种攻击方法,现在已经有一些方法了。分别是

1.栈随机化,从而无法在攻击字符串中嵌入攻击代码程序的指针。2.栈破坏检测。3.限制可执行代码的区域。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  计算机
相关文章推荐