突破GS之理论篇
GS就是一个缓冲区溢出标志,如果发生缓冲区溢出,该标志会被覆盖,导致其值和其在.data区域的备份值不同,由此系统进入异常处理流程,函数不会正常返回,ret指令也不会执行。
以下情况VS不会开启GS:
- 函数不包含缓冲区
- 函数被定义为具有变量参数列表
- 函数使用无保护的关键字标记
- 函数在第一个语句中包含内嵌汇编代码
- 缓冲区不是8字节类型且大小不大于4字节
开GS和不开GS的对比(此处均关闭了代码优化,防止变量位置被编译器调整):
#include "string.h"
#pragma strict_gs_check(on) //此程序没有4字节以上的缓冲区,故函数不受GS保护,除非使用此句强制开启
int vulfunction(char* str){
char arr[4];
strcpy(arr,str);
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
char *str="yeah,i'm a guy.";
vulfunction(str);
printf("hellworld");
return 0;
}
以下是突破GS的几种策略:
- 专门攻击没有GS保护的函数 - -||
- 溢出覆盖虚表指针,将程序要调用的虚函数地址替换为我们的shellcode地址
利用覆盖虚表指针来突破GS的可行原因是:this_ptr存放在[ebp-0C]处,而cookie存放在[ebp-4]处,所以溢出会先覆盖this_ptr;恰好函数返回前(gs检查前)调用了虚函数,所以可以通过只篡改虚表指针达到调用shellcode、且gs保护丝毫不会察觉的效果 - 攻击异常处理机制
溢出覆盖S.E.H中的异常处理函数地址,当发生异常时,就可以直接跳转执行! - 同时替换栈中cookie和.data区域的备份
在堆中申请数组空间,通过数组越界篡改.data区域的cookie备份,而栈中用到的cookie又是从.data区取的,所以此突破方式简直神不知鬼不觉啊。。。不过不同环境下,.data区的cookie位置可能有所不同。。。同时要注意cookie不是直接存于栈区、直接和备份进行比对的,参见上图中的cookie装载、cookie检测过程
Those who seek some sort of a higher purpose or 'universal goal', who don't know what to live for, who moan that they must 'find themselves'. You hear it all around us. That seems to be theofficial bromide of our century. Every book you open. Every drooling self-confession. It seems to be the noble thing to confess. I'd think it would be the most shameful one.