《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

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