2015/5/21 11:07:55
之前我們一直在Linux平臺上分析漏洞,那是因爲對於絕大多數Hacker獲得一個Linux平臺更加容易,而且主流的服務器系統基本也都是Linux/Unix的;另外一個好處就是Linux提供了用戶自定義的強大功能,我們可以根據需要編譯彙編程序代碼,關閉相應的安全保護機制,便於我們的研究學習。
然而現實中有影響力的漏洞大多是基於Windows系統,因此這節我們來介紹下Winodws系統上是安全保護機制,至於Windows上的漏洞分析,我們會在之後的惡意代碼分析章節繼續介紹。
理解SEH
Windows系統內存保護
Windows系統內存保護機制繞過簡介
一、理解SEH
一般來說,觸發漏洞會導致程序的崩潰,Windows中引入了SEH(Structured Exception Hadnling),即結構化異常處理機制,這種機制在源代碼中一般是通過Try-Exception來實現的,比如像下面:
int main()
{
_try {
//可能出現異常崩潰的代碼
}
_except(EXCEPTION_EXECUTE_HANDLER) {
//異常處理程序
}
return 0;
}
這種SEH結構在運行中主要通過添加一個EXCEPTION_REGISTRATION結構來實現,這個結構有兩個成員:
prev:用於指向下一個SEH記錄的指針;
handler:指向實際處理程序代碼的指針;
其實Windows在原始的程序棧前面添加了一個異常處理結構,該結構由一系列的異常處理鏈表組成,這條鏈表的起始點總是放在TIB(Thread Information Block)的第一個成員中,在x86計算機中存儲在FS:[0]寄存器中。鏈表的最後總是默認處理程序,這個默認處理程序的指針總是0xFFFFFFFF。具體結構如下圖:
二、Windows系統內存保護
如果想全面探討Windows下的安全保護機制,一定需要很大的篇幅,在這裏我們僅對重要的做一個介紹,以起到拋磚引玉之用,感興趣的朋友可以繼續查詢更多資料。
1. 基於棧的緩衝區溢出檢測(GS)
我們首先來介紹基於棧的緩衝區溢出檢測(GS)的實現,這個機制的本質思想是在緩衝區溢出導致的覆蓋位置設置一個標籤值,該值具體位於所保存的EBP和RETN(EIP)地址的上方,當從函數返回時會檢查這個標籤值,看其是否被修改。由於其位於EBP上方,因此一檔該值修改,則可以判定RETN也被修改,即發生了緩衝區溢出***。新的函數開場白如下:
push ebp
mov ebp, esp
sub esp, 24h ;這三步同正常的開場白一致
move ax, dword ptr [vuln!_security_cookie]
xor eax, ebp ;xor cookie with ebp
mov dword ptr [ebp - 4]
而對應的函數收場白也添加了cookie值的驗證:
mov ecx, dword ptr [ebp - 4]
xor ecx, ebp ;if cookie or ebp changed
call vuln!_security_check_cookie(004012e8)
leave
ret
其實就是將安全cookie同ebp進行異或運算後存放在棧上,然後函數返回的時候取出安全cookie,再次與ebp進行異或測試是否同系統值匹配。一種改進是在這個基礎上添加了一份參數副本,從而使得原始函數參數即使被覆蓋也沒用,具體結構如下:
2. SafeSEH
SafeSEH主要是對SEH結構的保護機制,防止覆蓋和使用存儲在棧上的SEH結構。在觸發異常時SafeSEH會進行以下幾項檢查:
確保異常記錄位於當前線程的棧上;
確保處理程序指針沒有回指棧;
確保處理程序已經在授權處理程序列表中登記;
確保處理程序位於可執行的內存映像中;
3. 堆保護
傳統的堆漏洞***會覆蓋對塊首部,並視圖創建一個僞造的塊,當內存釋放例程執行時可以使用該塊在任意內存地址處寫入任意4個字節。具體爲:
安全移除:在進行移除前,操作系統會驗證向前和向後指針指向的相同的塊;
堆元數據cookie:在堆塊首部存儲一個1字節的cookie,當從空閒列表中移除之前先檢查該值。Vista中在幾個關鍵首部字段增加了XOR加密措施,並在使用前進行檢查,以防止篡改。
4. DEP
DEP(Data Execution Prevention),即數據執行保護,阻止存放在堆、棧或數據內存中的代碼執行,這一直以來都是安全操作系統設計的目標。2004年AMD在其CPU中提供了NX位,首次允許硬件識別內存頁是否可執行並採取相應措施。Intel後來推出來了XD功能,實現了類似的功能。
5. ASLR
ASLR(Address Space Layout Randomization),即地址空間隨機化,思想時在進程使用的內存地址引入隨機性,這樣會使得***變得更加艱難。一些隨機化有:
可執行映像採取255個隨機位置之一;
DLL映像中,ntdll.dll隨機加載到256個隨機位置之一,然後其他的DLL文件隨機加載到另一個隨機位置;
棧:比其他內存區更加隨機化;
堆:基本堆結構位於32個隨機位置之一;
PEB(Process Enviroment Block,進程環境塊)/TEB(Thread Enviroment Block,線程環境塊)
但是應該注意到,由於Windows系統64KB內存頁的限制,因此內存地址隨機化時其中一些內存區的熵值較小,即隨機化空間不大,因此可以利用蠻力破解。
三、Windows系統內存保護機制繞過簡介
安全的***總是一種競賽的態勢,交替發展。這部分我們來簡要介紹下Windows下的保護繞過機制,重點是GS和ASLR的一些思路,主要在於啓發大家的思路,網上有着更加 豐富的資料。
1. 繞開GS保護
直接來介紹幾種可能的思路:
猜測cookie值:由於GS保護機制使用了幾個較弱的cookie源,因此***者可以對它們進行計算並進行預測\猜測cookie值,這種方式適合應用在本地系統***中;
覆蓋調用函數指針:通過調用虛函數時調用方函數會講對象或結構放在棧上,因此如果能夠覆蓋虛函數的vtable,然後創建僞造的vtable,那麼就可以重定向虛函數並獲得代碼執行;
替換cookie:由於cookie的值寫在.data區,而這個區是可寫的,因此如果有任意內存寫入權限,那麼就可以覆蓋該值;
覆蓋SEH記錄:GS機制並沒有保護SEH,因此如果能夠寫入足夠的數據覆蓋SEH,並在函數收場白檢查cookie之前觸發異常,將執行流程導向SEH,那麼就可以控制程序的執行。
2. 繞開ASLR
繞開ASLR的最簡單方式就是返回到那些沒有鏈接ASLR保護機制的模塊中,可以使用pvefindaddr工具的noasir選項列出所有沒有鏈接ASLR的模塊,比如MSVCR71.dll模塊就沒有受到ASLR的保護,我們可以返回到該模塊。
** Refer: Gray Hat Hacking: The Ethical Hacker's Handbook, Third Edition **