《Windows安全机制》之GS机制

前言

有时候再用IDA分析的时候,经常会看到__security_cookie,最开始不清楚他是什么东西,上网查阅,说是为了防止缓冲区溢出的一种机制,后来经过学习,特别是学习了《0day》之后,了解到只是一种GS机制,针对缓冲区溢出时覆盖函数返回地址这一特征来检测栈溢出。(图源部分来自网络)

GS的编译选项

微软在编译程序时使用了一个很酷的安全
编译选项——GS,在 Visual Studio 2003 (VS 7.0)及以后版本的 Visual Studio 中默认启用了这个
编译选项。
通过菜单中的 Project→project Properties→Configuration Prop erties→C/C++→Code Ge neration→Buffer Sec urity Check 中对 GS 编译选项进行设置,如图所示。
在这里插入图片描述

GS提供的保护作用:

  1. 修改栈帧中函数返回地址的经典攻击将被 GS 机制有效遏制;
  2. 基于改写函数指针的攻击,如对 C++虚函数的攻击,GS 机制仍然很难防御;
  3. 针对异常处理机制的攻击,GS 很难防御;
  4. GS 是对栈帧的保护机制,因此很难防御堆溢出的攻击。

GS 机制的保护原理

核心原理:
GS 编译选项为每个函数调用增加了一些额外的数据和操作,用以检测栈中的溢出。
原理细节:
1.在所有函数调用发生时,向栈帧内压入一个额外的随机 DWORD,这个随机数被称做 “canary”,但如果使用 IDA 反汇编的话,您会看到 IDA 会将这个随机数标注为“Security Cookie”。
2.Security Cookie 位于 EBP 之前,系统还将在.data的内存区域中存放一个 Security Cookie
的副本,如图【GS保护机制下的内存布局】所示。GS保护机制下的内存布局
3.当栈中发生溢出时,Security Cookie 将被首先淹没,之后才是 EBP 和返回地址。
4.在函数返回之前,系统将执行一个额外的安全验证操作,被称做 Security check。
5.在 Security Check 的过程中,系统将比较栈帧中原先存放的 Security Cookie 和.data 中副本的值,如果两者不吻合,说明栈帧中的 Security Cookie 已被破坏,即栈中发生了溢出。
6.当检测到栈中发生溢出时,系统将进入异常处理流程,函数不会被正常返回,ret 指令也不会被执行,如图所示。在这里插入图片描述
注意事项:
因为额外的数据和操作带来的直接后果就是系统性能的下降,为了将对性能的影响降到最
小,编译器在编译程序的时候并不是对所有的函数都应用 GS,以下情况不会应用 GS。
(1)函数不包含缓冲区。 (就不会有栈溢出)
(2)函数被定义为具有变量参数列表。
(3)函数使用无保护的关键字标记。
(4)函数在第一个语句中包含内嵌汇编代码。
(5)缓冲区不是 8 字节类型且大小不大于 4 个字节。
解决以上问题的方法:
方法一:
为了在性能与安全之间找到一个平衡点,在 Visual S tudio 2005 SP1 起引入了一个新的安全标识:

#pragma strict_gs_check 

通过添加#pragma strict_gs_check(on) 可以对任意类型的函数添加 Security Cookie。
如以下代码所示,通过设置该标识,可以对不符合 GS 保护条件的函数 vulfuction 添加 GS 保护。

#include"stdafx.h" 
#include"string.h" 
#pragma strict_gs_check(on) // 为下边的函数强制启用 GS 
intvulfuction(char * str) 
{ 
	chararry[4];   //缓冲区不是 8 字节类型且大小不大于 4 个字节。
	strcpy(arry,str); 
	return 1; 
} 
//缓冲区不是 8 字节类型且大小不大于 4 个字节。本来没有GS保护机制
//添加#pragma strict_gs_check ,开启GS机制
int_tmain(intargc, _TCHAR* argv[]) 
{ 
	char* str="yeah,i have GS protection"; 
	vulfuction(str); 
	return 0; 
} 

方法二:变量 重排技术——保护相邻局部变量
在编译时根据局部变量的类型对变量在栈帧中的位置进行调整,将字符串变量移动
到栈帧的高地址。这样可以防止该字符串溢出时破坏其他的局部变量。同时还会将指针参数和
字符串参数复制到内存中低地址,防止函数参数被破坏。如图所示。
在这里插入图片描述
这样就会避免栈溢出造成的局部变量改变,虽然函数参数 arg 还是会被覆盖,但由于程序会在栈帧低地址处保存参数的副本,所以 Buff 的溢出也不会影响到传递进来的函数参数。

核心Security Cookie

1.系统以.data 节的第一个双字作为 Cookie 的种子,或称原始 Cookie(所有函数的 Cookie
都用这个 DWORD 生成)。
2.在程序每次运行时 Cookie 的种子都不同,因此种子有很强的随机性
3.在栈桢初始化以后系统用 ESP 异或种子,作为当前函数的 Cookie,以此作为不同函数
之间的区别,并增加 Cookie 的随机性
4.在函数返回前,用 ESP 还原出(异或)Cookie 的种子若想在程序运行时预测出 Cookie 而突破 GS 机制基本上是不可能的。

实际分析

我们通过这段代码去更好地认识GS机制在程序中所起到的作用。

#include<Windows.h>
#include<iostream>
using namespace std;

void BigBuffer()
{
	char BufferData[10] = "";
	int num = 1;
}
void SmallBuffer()
{
	char BufferData[4] = "";
	int num = 2;
}


int main()
{
	BigBuffer();
	SmallBuffer();
	getchar();
	return 0;
}

BigBuffer()的缓冲区是符合GS机制要求的:
开栈时,出现_security_cookie,恢复堆栈时也进行了堆栈检查,@__security_check_cookie@4。
在这里插入图片描述

_security_cookie和BufferData以及num的内存分布也符合变量重排之后的内存分布。
在这里插入图片描述
下面看cookie的详细细节:
首先将___security_cookie变量的值给取出来。然后就是将取出来的Cookie全局变量与当前EBP的值进行异或运算。
这里的异或就是上面所说的为了增加随机性,具体的优点如下:

  1. 可以增加随机性,尽可能使不同函数的安全Cookie都不同。

  2. 可以检查EBP是否被破坏,因为在函数结束检查Cookie时,还会将Cookie变量值再次与EBP异或,如果EBP的值没有变化,那么就能恢 复成原来的___security_cookie值。

然后紧接着将值存入ebp-4.

003C16CE A1 04 80 3C 00       mov         eax,dword ptr [__security_cookie (03C8004h)]  
003C16D3 33 C5                xor         eax,ebp  
003C16D5 89 45 FC             mov         dword ptr [ebp-4],eax  

最后来看@__security_check_cookie@4进行校验的过程。
首先将Cookie变量的值重新取出来并异或还原并保存到ECX中。然后异或再调用__security_check_cookie函数检测。

003C1706 8B 4D FC             mov         ecx,dword ptr [ebp-4]  
003C1709 33 CD                xor         ecx,ebp  
003C170B E8 61 FB FF FF       call        @__security_check_cookie@4 (03C1271h)  

__security_check_cookie的检测原理:
在这里插入图片描述
SmallBuffer不被GS保护:
SmallBuffer的缓冲区缓冲区不是 8 字节类型且大小不大于 4 个字节,不符合GS机制,看代码也确实没有_security_cookie。
在这里插入图片描述
为了解决这个问题,我们使用上面说到的#pragma strict_gs_check 。
加上之后,SmallBuffer也会被GS机制保护。
在这里插入图片描述

突破GS的方法:

GS机制虽然能够很好的防止栈溢出,但并不是绝对防御,还有存在着漏洞可以利用
1.利用未被保护的内存突破 GS
2.覆盖虚函数突破 GS
3.攻击异常处理突破 GS
4.同时替换栈中和.data 中的 Cookie 突破 GS
后续,我将进行总结归纳。

参考资料:

《0day安全:软件漏洞分析技术》
https://blog.csdn.net/masefee/article/details/4633305

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章