Windows安全机制
微软关于内存保护机制
- GS编译技术
- SEH的安全校验机制
- Heap Cookie,Safe Unlinking等一系列堆安全机制
- DEP数据执行保护
- ASLR加载地址随机
- SEHOP SEH的覆盖保护
栈的保护:GS
原理
在编译时可以选择是否开启GS安全编译选项。这个操作会给每个函数增加一些额外的数据和操作,用于检测栈溢出。
在函数调用时,会在返回地址和EBP之前压入一个额外的Security Cookie。系统会比较栈中的这个值和原先存放在.data中的值做一个比较。如果两者不吻合,说法栈中发生了溢出。
并不是对所有的函数都应用GS,以下情况不会应用GS
- 函数不包含缓冲区
- 函数使用无保护的关键字标记
- 函数在第一个语句中包含内嵌汇编代码
- 缓冲区不是8字节类型且大小不大于4个字节
引入#pragma strict_gs_check(on)可以对任意类型的函数添加Security Cookie。
细节
在Visual Studio 2005之后,使用了变量联排技术,在编译时对局部变量进行调整。
- 将字符串变量移动到栈帧的高位置,防止字符串溢出破坏其他局部变量。
- 将指针参数和字符串参数复制到内存低地址中,防止被破坏
- 系统以.data节的第一个双字节作为cookie的种子
- 每次cookie的种子都不同
- 在栈帧初始化以后用ESP异或种子,作为当前函数的cookie,以此作为不同函数之间的区别
- 在函数返回前,用ESP还原出cookie种子
弊端
- 难以防御基于函数指针,虚函数的攻击
- 难以防御异常处理的攻击
- 只是防御栈,对堆无能为力
GS的绕过
缓冲区大于4个字节
下面这段代码缓冲区小于4字节,所以即使GS机制打开,这个函数也不受保护。
#include"stdafx.h"
#include"string.h"
int vulfuction(char * str)
{
char arry[4];
strcpy(arry,str);
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
char* str="yeah,the fuction is without GS";
vulfuction(str);
return 0;
}
覆盖虚函数突破GS
异常处理突破GS
test函数存在栈溢出漏洞。将buf溢出到SEH异常处理句柄淹没并改为shellcode的地址。由于strcpy的溢出,覆盖了input的地址,strcat会从一个非法地址读取数据,所以造成了异常。(在Security Cookie之前转入异常处理)
#include<stdafx.h>
#include<string.h>
charshellcode[]=" ";
void test(char * input)
{
char buf[200];
strcpy(buf,input);
strcat(buf,input);
}
void main()
{
test(shellcode);
}
替换.data来欺骗GS
同时替换栈中和.data中的Cookie来保证溢出后的Cookie值的一致性。
void test(char* str, inti,char* src)
{
chardest[200];
if(i<0x9995)
{
char*
buf=str+i;
*buf=*src;
*(buf+1)=*(src+1);
*(buf+2)=*(src+2);
*(buf+3)=*(src+3);
strcpy(dest,src);
}
}
void main()
{
char* str=(char*)malloc(0x10000);
test(str,0xFFFF2FB8,shellcode);
}
在正常情况下,我们是无法访问到.data段中的,只有当一个指针偏移没有作判断,能够为我们所用,将它指向.data的时候,才能够覆盖修改.data的第一个dword。在以上代码实例中,先申请一块堆区,再创建一个指针指向的地址是堆区+偏移(i),当i为我们恶意构造的负数的时候,就有可能指向.data段。然后,要有shellcode覆盖,代码中给了一个strcpy。
确定.data中的值
通过调试已知条件:
- .data地址:0x00403000
- 栈中需要覆盖的地址:0x0012FF60
- 栈中需要返回的地址0x0012FF68
- 堆分配首地址0x00410048
计算可得:0x410048-0x403000=53320,由于这个偏移应该是负数,所以i=-53320=FFFF2FB8
确定栈中的值
将90909090写入.data,GS校验的时候,会将cookie和ebp异或然后和90909090对比,所以,cookie=90909090 xor 当时的ebp。
shellcode布局