Windows安全机制---栈保护:GS机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37809075/article/details/82973151

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中的值
通过调试已知条件:

  1. .data地址:0x00403000
  2. 栈中需要覆盖的地址:0x0012FF60
  3. 栈中需要返回的地址0x0012FF68
  4. 堆分配首地址0x00410048
    计算可得:0x410048-0x403000=53320,由于这个偏移应该是负数,所以i=-53320=FFFF2FB8

确定栈中的值
将90909090写入.data,GS校验的时候,会将cookie和ebp异或然后和90909090对比,所以,cookie=90909090 xor 当时的ebp。
在这里插入图片描述
shellcode布局

猜你喜欢

转载自blog.csdn.net/m0_37809075/article/details/82973151