GS原理及绕过技术
1、GS工作原理
- 在所有函数调用发生时,向栈帧中压入额外的随机DWORD,这个随机数被称作"canary",在IDA中被标注为“Security Cookie”。
- Security Cookie位于EBP之前,系统还将.data的内存区域中存放一个Security Cookie副本
- 当栈发生溢出时,Security Cookie将被首先淹没,之后才是EBP和返回地址
- 在函数返回之前,系统将执行额外的安全验证操作,即Security Check
- 在Security Check过程中,系统将比较栈中原先存放的Security Cookie和.data中副本的值,如果两者不吻合,说明栈帧中的Security Cookie已被破坏,即栈中已经溢出
- 当检测处溢出时,系统将进入异常处理流程,函数不会被正常返回,ret指令也不会被执行
1.1、不会使用GS的情况
- 函数不包括缓冲区
- 函数被定义为具有变量参数列表
- 函数使用无保护的关键字标记
- 函数在第一个语句中包含内嵌汇编代码
- 缓冲区不是8字节类型且大小不大于4字节
当然,也可以使用#pragma strict_gs_check(on)为任意类型的函数添加Security Cookie。
1.2、其他栈保护措施
VS 2005及后续版本使用了变量重排技术,在编译时根据局部变量的类型对变量在栈帧中的位置进行调整,将字符串变量移动到栈帧的高地址。这样可以防止该字符串溢出时破坏其他的局部变量,同时还会将指针参数的字符串参数复制到内存中的低地址,防止函数参数被破坏。
1.3、Security Cookie生成细节
- 系统以.data节的第一个双字作为Cookie的种子,或原始Cookie(所有函数的Cookie都用这个DWORD生成)
- 在程序每次运行时Cookie的种子都不同,因此种子具有很强的随机性
- 在栈帧初始化以后系统用ESP异或种子,作为当前函数的Cookie,以此作为不同函数之间的区别,并增加 Cookie的随机性
- 在函数返回前,用ESP还原出(异或)Cookie的种子
1.4、GS优缺点
- 修改栈帧中函数返回地址的经典攻击将被GS机制有效遏制
- 基于改写函数指针的攻击,如C++虚函数的攻击,GS机制仍然很难防御
- 针对异常处理机制的攻击,GS很难防御
- GS是对栈帧的保护机制,因此很难防御堆溢出的攻击
2、GS的突破
- 1.猜测/计算cookie
- Reducing the Effective Entropy of GS Cookies:http://www.uninformed.org/?v=7&a=2&t=html
- 至从覆盖SEH的方法出现后,这种方法目前已基本不用了,它没有后面的方法来得简便
- 2.覆盖SEH
- 由于当security_check_cookie()函数检测到cookie被更改后,会检查是否安装了安全处理例程,也就是SEH节点中保存的指针,如果没有,那么由系统的异常处理器接管,因此我们可以通过(pop pop ret)覆盖SEH来达到溢出的目的。但对于受SafeSEH保护的模块,就可能会导致exploit失效,关于它的绕过在后续部分再述
- 辅助工具:OD插件safeSEH、pattern_create、pattern_offset、msfpescan、memdump
- 3.覆盖虚表指针
- 堆栈布局:【局部变量】【cookie】【入栈寄存器】【返回地址】【参数】【虚表指针】
- 当把虚表指针覆盖后,由于要执行虚函数得通过虚表指针来搜索,即可借此劫持eip
- 4.利用未被保护的内存突破
- 5.替换.data中的Cookie突破GS
评论区