___security_cookie機制


.text:00411500 ; int __cdecl wmainCRTStartup()
.text:00411500 _wmainCRTStartup proc near              ; CODE XREF: startj
.text:00411500                 mov     edi, edi
.text:00411502                 push    ebp
.text:00411503                 mov     ebp, esp
.text:00411505                 call    j____security_init_cookie
.text:0041150A                 call    __tmainCRTStartup
.text:0041150F                 pop     ebp
.text:00411510                 retn
.text:00411510 _wmainCRTStartup endp

__tmainCRTStartup前調用___security_init_cookie進行全局___security_cookie初始化,___security_cookie開始時固定為0BB40E64Eh:

.data:00417014 ___security_cookie dd 0BB40E64Eh

 ___security_init_cookie負責___security_cookie初始化工作,首先將___security_cookie與0BB40E64Eh比較,相同則表示未初始化過,跳入初始化代碼loc_411D01,否則向下執行。將___security_cookie和0FFFF0000h進行與操作,高4字節為0則跳入初始化代碼loc_411D01,否則保存___security_cookie到ecx。

初始化代碼中,首先取時間,分別與進程ID,線程ID,TickCount,性能計數器等異或,保證隨機性,結果存入___security_cookie。到此全局的___security_cookie初始化完畢,並且初始化后在進程中這個值不再變化。

使用/GS選項編譯,或使用了Windows SEH的代碼,都會在CRT中加入 ___security_init_cookie。在受保護的函數中:

.text:00413200 var_4           = dword ptr -4
……
.text:0041321E                 mov     eax, ___security_cookie
.text:00413223                 xor     eax, ebp
.text:00413225                 mov     [ebp+var_4], eax

首先取 ___security_cookie與ebp異或存入eax,將eax值放到棧上ebp-4位置。與ebp異或保證了棧上cookie值不可預測。棧上的cookie是放在ebp&返回地址與本地變量之間,這樣可以保護ebp&返回地址及以上地址空間不被覆寫。

但保護不了本地變量,微軟沒有實現本地變量重排:

0106321E  mov         eax,dword ptr [___security_cookie (1067014h)]  
01063223  xor         eax,ebp  
01063225  mov         dword ptr [ebp-4],eax  

int a = 10;
01063228  mov         dword ptr [ebp-0Ch],0Ah  

int b = 2;
0106322F  mov         dword ptr [ebp-18h],2  

char str[16];
printf("%p\n", str);
01063236  mov         esi,esp  
01063238  lea         eax,[ebp-30h]  
0106323B  push        eax  
0106323C  push        offset string "%s\n" (10657A0h)  
01063241  call        dword ptr [__imp__printf (10682ACh)]  

受保護的函數返回前:

.text:00413283                 mov     ecx, [ebp+var_4]
.text:00413286                 xor     ecx, ebp        ; cookie
.text:00413288                 call    j_@__security_check_cookie@4 ;__security_check_cookie(x)

從棧上取出cookie與ebp異或,將還原后___security_cookie存入ecx,然后調用__security_check_cookie檢查。

.text:00412A00 @__security_check_cookie@4 proc near    ; CODE XREF: __security_check_cookie(x)j
.text:00412A00
.text:00412A00 cookie          = dword ptr -4
.text:00412A00
.text:00412A00                 cmp     ecx, ___security_cookie
.text:00412A06                 jnz     short failure
.text:00412A08                 rep retn
.text:00412A0A ; ---------------------------------------------------------------------------
.text:00412A0A
.text:00412A0A failure:                                ; CODE XREF: __security_check_cookie(x)+6j
.text:00412A0A                 jmp     j____report_gsfailure
.text:00412A0A @__security_check_cookie@4 endp

__security_check_cookie函數將全局___security_cookie與ecx中存放的還原出的___security_cookie比較,若不同則表示發生了溢出,調用____report_gsfailure執行異常處理。

下面分析一下StackCookie繞過的可行性,有利條件:

1、__security_cookie可以從內存讀到。
2、ebp與esp地址相鄰,通過泄漏esp可猜測ebp。

不利條件:

1、程序檢測到溢出,____report_gsfailure崩潰退出。
2、棧布局隨機化,重新運行程序,ebp變化即上次泄漏的esp失效。

Hook掉____report_gsfailure等異常處理函數可以輕松繞過stack cookie,但已經能在目標系統執行代碼,再寫這個溢出就沒什么意義了。

因為___security_cookie+ASLR的存在,Windows的棧溢出漏洞已經很難利用。覆蓋SEH鏈這類方法雖然可行,但並不是獲取了cookie值,所以不能算作對cookie機制的破解。

下面引用tombkeeper在微博上的一段話:

內存破壞類漏洞攻防對抗的發展形勢大概會是這樣:目前所有已知攻擊方式在未來幾年內被逐漸阻止或充分緩解,新的攻擊方式將不僅難以被設計出來,而且實現過程也很復雜——如果沒有相關研究作為基礎,即使捕捉到野外樣本,分析者甚至可能難以理解樣本是如何被制作出來的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM