Written by
kumqu
on
on
绕过GS的栈溢出攻击原理
GS安全编译选项保护原理
针对缓冲区溢出时覆盖函数返回地址这一特征, 微软在 VS 7.0
及以后的VS版本中默认启用了GS安全编译选项,其基本原理如下:
- 在所有函数发生调用时,向栈帧内压入一个额外的随机
DWORD
, 被称为canary
或者Security Cookie
Security Cookie
位于EBP
之前, 系统还会在.data
的内存区域存放一个Security Cookie
副本- 当栈中发生溢出时,
Security Cookie
将首先被淹没, 之后才是EBP
和返回地址
- 在函数返回之前, 系统将执行一个额外的安全验证操作, 被称作
Security check
- 在
Security check
过程中, 系统比较栈帧中原先存放的Security Cookie
和.data
中副本的值, 如果两者不吻合, 说明栈帧中的Security Cookie
已被破坏, 即栈中发生了溢出 - 若检测到栈中发生溢出, 系统将进入异常处理流程, 函数不会正常返回,
ret
指令也不会被执行 - 采用GS机制, 经典的修改栈帧中函数返回地址的攻击得到了有效遏制
Security Cookie
产生细节:
- 系统以
.data
节的第一个双字作为Cookie
的种子 (所有函数的Cookie
都使用这个DWORD
产生) - 程序每次运行时
Cookie
的种子都不同 - 在栈帧初始化以后系统使用
EBP
异或种子, 作为不同函数的区别 - 在函数返回前, 用
EBP
异或还原Cookie
的种子
以下情况不会应用GS:
- 函数不包含缓冲区, 或缓冲区不是8字节类型且大小不大于4字节
- 函数被定义为具有变量参数列表
- 函数使用无保护的关键字标记
- 函数在第一个语句中包含内嵌汇编代码
绕过GS的几种攻击方法
1. 利用未被保护的内存突破GS
系统为了将GS对性能的影响降到最小, 并不是所有的函数都会保护. 例如, 一个函数中不包含4字节以上的缓冲区时, 即使GS处于开启状态, 这个函数也是不受保护的. 因此, 可以针对这类函数, 构造巧妙的shellcode
进行溢出.
2. 攻击异常处理突破GS
GS机制没有对SEH
提供保护, 因此可以通过攻击程序的异常处理机制达到绕过GS的目的. 通过构造超长的字符串覆盖掉异常处理指针, 然后触发一个异常, 程序就会转入异常处理; 由于异常处理指针已被覆盖, 因此可以通过劫持SEH
来控制程序的后续流程.
3. 覆盖虚函数突破GS
程序只有在函数返回时, 才会去检查Security Cookie
,而我们在程序检查Security Cookie
之前劫持程序流程的话,就可以实现对程序的溢出。例如使用C++的虚函数溢出即可实现上述功能.
4. 同时替换栈和.data中的Cookie突破GS
若要在Security Cookie
正常工作的情况下实现绕过, 由于Cookie
具有很强的随机性, 难以猜测, 所以只能同时替换栈和.data中的Cookie实现绕过. 构造特殊的shellcode
使用相同的值覆盖栈和.data中的Cookie, 即可实现GS绕过.