软件安全之堆栈攻击
软件安全之堆栈攻击
博客:cbb777.fun
全平台账号:安妮的心动录
github: https://github.com/anneheartrecord
下文中我说的可能对,也可能不对,鉴于笔者水平有限,请君自辨。有问题欢迎大家找我讨论
软件安全分为三类
- 软件漏洞
- 恶意代码
- 软件侵权
恶意代码:指未被授权的情况下,以破坏软硬件设备、窃取用户信息、干扰用户正常使用、扰乱用户行为为目的而编制的软件或代码片段。实现方式有很多种:二进制文件、脚本、宏代码、寄生在其他代码中的一段指令。
恶意代码包括计算机病毒、蠕虫、木马、后门、广告、流氓软件等等
漏洞
0day漏洞:已经被发现(有可能未被公开) 但官方还没有相关补丁的漏洞
1day漏洞:厂商发布补丁之后但是大部分用户还未打补丁的漏洞,此类漏洞依然具有可利用性
历史漏洞:出现一段时间还没修复的漏洞
为什么冯诺依曼体系容易导致漏洞产生
1.指令和数据都是二进制表示, 从机器的角度上来看,指令也是数据,数据也可以是指令 ,指令可被数据篡改(病毒),外部数据可被当作指令植入(SQL注入、木马植入)
2.指令和数据组成程序存储到内存中自动执行, 数据和指令混乱,数据可影响指令和控制 , 数据区域的越界可能会导致指令出问题
3.程序依据代码设计的逻辑,接收外部输入,输出结果,程序员可以实现特殊功能(后门),或者通过输入数据触发特定分支(后门)
程序内存分配
一般来说,一个程序经过编译、链接,最终生成可执行文件,在运行的时候,操作系统会自动加载该文件到内存,然后映射出虚拟内存空间,继续运行,这就形成了进程空间。
1.代码区:放程序汇编后的机器代码和只读数据,这个代码区一般是只读的
2.数据区:用于存储全局变量和静态变量
3.堆:用户分配
4.栈:系统分配

其中栈的增长方向是向低地址方向增长,堆的增长方向是向高地址方向增长。
而且内存分配在栈上的速度,和在栈上移除的速度都很快,只需要一条原子命令PUSH和UNPUSH,但是在堆上就会慢很多,需要先找到一块大小合适的内存,再将变量分配在这块内存上。
程序用的缓冲区既可以是堆区和栈区,也可以是存放静态变量的数据区 。由于进程各个区域都有自己的用途,根据缓冲区利用的方法和内存所在区域,可以分为堆溢出和栈溢出。
缓冲区溢出:向缓冲区写入数据时,因为没有做边界检查,导致写入缓冲区的数据超过预先分配的编辑,从而使溢出数据覆盖在合法数据上而引起的系统异常的一种现象。
栈漏洞
首先来了解一下栈帧的这个概念:
对于一个单独的函数栈空间,我们把它叫做栈帧,对于函数调用栈的集合,我们叫做系统栈。
很明显栈帧是系统栈的子集,那么我们在一个系统栈之中是怎么判断出某个栈帧有多大,确定某地址是属于哪个栈帧空间的呢?
这就需要用到ESP和EBP两个寄存器
ESP:Extened Stack Pointer 里面的指针存放的是栈帧栈顶的地址
ESP:Extended Base Pointer 里面的指针存放的是栈帧栈底的地址
两个值之间的空间即为当前的栈帧空间
在函数调用过程中,除了这两个寄存器外,还有一个非常重要的寄存器:EIP,扩展指令寄存器(Extened Instruction Pointer),分析的是下一条将要执行的指令,EIP指向哪里,CPU就会执行哪里的指令
栈帧的内容
1.前一个栈帧的栈底位置,用于在函数调用后恢复主调函数的栈帧 (当前帧的栈顶可计算得到)
2.函数的局部变量
3.函数调用的参数
4.函数的返回地址RET,用于保存函数调用前指令的位置,以便函数返回时能够恢复到函数调用前的代码区,继续执行指令。
函数调用的步骤
1.参数入栈,将被调函数的实际参数从右到左一次压入主调函数的栈帧中
2.返回地址RET入栈,将当前指令的下一条指令压入主调函数栈帧中
3.代码区跳转,CPU从当前代码区跳转到被调函数的入口,EIP指向函数入口处
4.当前栈帧调整为被调函数的栈帧
返回主调函数的步骤
1.保存返回值,放在寄存器EAX中
2.弹出当前栈帧,将其哪一个栈帧恢复为当前栈帧
栈溢出的原理
在栈帧中,局部变量是顺序排列的,局部变量下面紧跟着的是当前栈帧EBP及函数返回地址RET,如果这些局部变量为数组,由于存在越界的漏洞,那么越界的数组元素将会覆盖相邻的局部变量,甚至覆盖前栈帧EBP及返回地址RET,从而造成程序的异常。
栈溢出攻击:是一种利用栈溢出漏洞所进行的攻击行动,目的在于扰乱某些具有特权运行程序的功能,使得攻击者取得程序的控制权,如果该程序具有足够的权限,那么整个主机就被控制了。
两种栈溢出攻击的基本原理
- JMP ESP覆盖方法:覆盖函数返回地址,因为函数返回时ESP总是指向函数返回后的下一条指令,如果用JMP将ESP覆盖掉,那么程序就可以跳转到攻击者希望的内存地址执行
- SEH覆盖方法:在windows中,操作系统或应用程序运行时,为了保证在出现除0,非法内存访问等错误是,系统也能够正常运行而不至于崩溃或者宕机,windows会对运行在其中的程序提供一次异常处理来处理错误,SEH就是覆盖掉异常处理程序地址的方式
堆溢出的原理
堆管理有三类操作:堆块的分配,堆块的释放和堆块的合并,这些都是对堆块空表的操作,如果能修改表的指针,就可以拿到读写内存的机会