windows溢出保護原理與繞過方法概覽(轉自riusksk's blog(泉哥))

前言
從20世紀80年代開始,在國外就有人開始討論關於溢出的攻擊方式。可是在當時並無引發人們的注意,直至後來經一些研究人員的披露後,特別是著名黑客雜 志Phrack上面關於溢出的經典文章,引領許多人步入溢出研究的行列,今後關於緩衝區溢出的問題才爲人們所重視。隨着溢出研究的深刻,網上開始出現不少 關於溢出攻擊教程,揭露了許多溢出利用技術,特別是經典的call/jmp esp,藉此溢出攻擊案例層出不窮。這也引發了微軟的重視,他們在 windows系統及VC++編譯器上加入了各類溢出保護機制,以試圖阻止這類攻擊,惋惜每次公佈溢出保護機制以後,不久就有人公佈繞過方法。MS每次都 稱某保護機制將成爲溢出利用的末日,惋惜每次都被終結掉。既而,黑客與微軟之間的溢出鬥爭一直持續着。更多關於windows溢出的歷史,可參見由 Abysssec安全組織編寫的文章 《Past,Present,Future of Windows Exploitation》(http://www.abysssec.com /blog/2010/05/past-present-future-of -windows-exploitation/)。在本篇文章中主要揭露了 windows平臺上的各類溢出保護機制原理以及繞過方法,具體內容參見下文。

1、GS編譯選項

原理:經過VC++編譯器在函數先後添加額外的處理代碼,前部分用於由僞隨機數生成的cookie並放入.data節段,當本地變量初始化,就會向棧中插入cookie,它位於局部變量和返回地址之間:

    ┏━━━━━━━━┓內存低地址
    ┃   局部變量     ┃▲
    ┣━━━━━━━━┫┃
    ┃security_cookie ┃┃
    ┣━━━━━━━━┫┃棧
    ┃  入棧寄存器    ┃┃生
    ┣━━━━━━━━┫┃長                       
    ┃     SEH節點    ┃┃方
    ┣━━━━━━━━┫┃向
    ┃    返回地址    ┃┃
    ┣━━━━━━━━┫┃
    ┃    函數參數    ┃┃
    ┗━━━━━━━━┛內存高地址

經GS編譯後棧中局部變量空間分配狀況:

sub   esp,24h
mov   eax,dword ptr [___security_cookie (408040h)]
xor   eax,dword ptr [esp+24h]
mov   dword ptr [esp+20h],eax

在函數尾部的額外代碼用於在函數返回時,調用security_check_cookie()函數,以判斷cookie是否被更改過,當函數返回時的狀況以下:

mov   ecx,dword ptr [esp+20h]
xor   ecx,dword ptr [esp+24h]
add   esp,24h
jmp   __security_check_cookie (4010B2h)

在緩衝區溢出利用時,若是將惡意代碼從局部變量覆蓋到返回地址,那麼天然就會覆寫cookie,當檢測到與原始cookie不一樣時(也就是比較上面408040h與4010B2h兩處cookie值的比較),就會觸發異常,最後終止進程。

繞過方法:

1.猜想/計算cookie
Reducing the Effective Entropy of GS Cookies:http://www.uninformed.org/?v=7&a=2&t=html
至從覆蓋SEH的方法出現後,這種方法目前已基本不用了,它沒有後面的方法來得簡便。

2.覆蓋SEH
因爲當security_check_cookie()函數檢測到cookie被更改後,會檢查是否安裝了安全處理例程,也就是SEH節點中保存的指針, 若是沒有,那麼由系統的異常處理器接管,所以咱們能夠經過(pop pop ret)覆蓋SEH來達到溢出的目的。但對於受SafeSEH保護的模塊,就 可能會致使exploit失效,關於它的繞過在後續部分再述。
輔助工具:OD插件safeSEH、pattern_create、pattern_offset、msfpescan、memdump

3.覆蓋虛表指針
堆棧佈局:[局部變量][cookie][入棧寄存器][返回地址][參數][虛表指針]
當把虛表指針覆蓋後,因爲要執行虛函數得經過虛表指針來搜索,便可藉此劫持eip。

2、SafeSEH

原理:爲了防止SEH節點被攻擊者惡意利用,微軟在.net編譯器中加入/sdeseh編譯選項引入SafeSEH技術。編譯器在編譯時將PE文件全部合 法的異常處理例程的地址解析出來製成一張表,放在PE文件的數據塊(LQAJ)一C0N—FIG)中,並使用shareuser內存中的一個隨機數加密, 用於匹配檢查。若是該PE文件不支持safesEH,則表的地址爲0。當PE文件被系統加載後,表中的內容被加密保存到ntdl1.dll模塊的某個數據 區。在PE文件運行期間,若是發生異常須要調用異常處理例程,系統會逐個檢查該例程在表中是否有記錄:若是沒有則說明該例程非法,進而不執行該異常例程。

繞過方法

利用SafeSEH保護模塊以外的地址
對於目前的大部分windows操做系統,其系統模塊都受SafeSEH保護,能夠選用未開啓SafeSEH保護的模塊來利用,好比漏洞軟件自己自帶的 dll文件,這個能夠藉助OD插件SafeSEH來查看進程中各模塊是否開啓SafeSEH保護。除此以外,也可經過直接覆蓋返回地址 (jmp/call esp)來利用。另外一種方法,若是esp +8 指向EXCEPTION_REGISTRATION 結構,那麼你仍然能夠尋找一個 pop/pop/ret指令組合(在加載模塊的地址範圍以外的空間),也能夠正常工做。但若是你在程序的加載模塊中找不到pop/pop/ret 指令, 你能夠觀察下esp/ebp,查看下這些寄存器距離nseh 的偏移,接下來就是查找這樣的指令:

call dword ptr[esp+nn] / jmp dword ptr[esp+nn] 
call dword ptr[ebp+nn] / jmp dword ptr[ebp+nn] 
call dword ptr[ebp-nn] / jmp dword ptr[ebp-nn]
(其中的nn 就是寄存器的值到nseh 的偏移,偏移nn多是: esp+8, esp+14, esp+1c, esp+2c, esp+44, esp+50, ebp+0c, ebp+24, ebp+30, ebp-04, ebp-0c, ebp-18)。

若是遇到以上指令是以NULL字節結尾的,可將shellcode放置在SEH以前:
• 在nseh 上放置向後的跳轉指令(跳轉7 字節:jmp 0xfffffff9);
• 向後跳轉足夠長的地址以存放shellcode,並藉此執行至shellcode;
• 把shellcode 放在用於覆蓋異常處理結構的指令地址以前。

3、DEP

原理:數據執行保護 (DEP) 是一套軟硬件技術,可以在內存上執行額外檢查以防止在不可運行的內存區域上執行代碼。 在 Microsoft Windows XP Service Pack 二、 Microsoft Windows Server 2003 Service Pack 1 、 Microsoft Windows XP Tablet PC Edition 2005 、 Microsoft Windows Vista 和 windows 7 中,由硬件和軟件一塊兒強制實施 DEP。DEP 有兩種模式,若是CPU 支 持內存頁NX 屬性, 就是硬件支持的DEP。只有當處理器/系統支持NX/XD位(禁止執行)時,windows才能擁有硬件DEP,不然只能支持軟件 DEP,至關於只有SafeSEH保護。

繞過方法:

1.ret2lib
其思路爲:將返回地址指向lib庫中的代碼,而不直接跳轉到shellcode 去執行,進而實現惡意代碼的運行。能夠在庫中找到一段執行系統命令的代 碼,好比system()函數,用它的地址覆蓋返回地址,此時即便NX/XD 禁止在堆棧上執行代碼,但庫中的代碼依然是能夠執行的。函數 system()可經過運行環境來執行其它程序,例如啓動Shell等等。另外,還能夠經過VirtualProtect函數來修改惡意代碼所在內存頁面 的執行權限,而後再將控制轉移到惡意代碼,其堆棧佈局以下所示:
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓       
┃                        ┃            惡意代碼              ┃內存高地址
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃        lpflOldProtect            ┃┃
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃          flNewProtect            ┃┃棧
┃       調用參數         ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃             dwSize               ┃┃生
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃            lpAddress             ┃┃長
┃                        ┣━━━━━━━━━━━━━━━━━┫┃
┃                        ┃      惡意代碼的入口地址          ┃┃方
┣━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━┫┃
┃      返回地址          ┃    VirtualProtect函數地址        ┃┃向
┣━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━┫┃
┃ EBP上層函數堆棧基址    ┃                                  ┃┃
┣━━━━━━━━━━━━┫                                  ┃┃
┃ 異常例程入口地址(如有 ┃     填充數據的覆蓋區域          ┃┃
┃設置的話,好比try…catch)┃       (AAAAAAAA……)           ┃┃
┣━━━━━━━━━━━━┫                                  ┃▼
┃      局部變量          ┃                                  ┃內存低地址
┗━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┛
更多信息可參考資料:http://www.infosecwriters.com/text_resources/pdf/return-to-libc.pdf

2.利用TEB突破DEP
在以前的《黑客防線》中有篇文章《SP2下利用TEB執行ShellCode》,有興趣的讀者能夠翻看黑防出版的《緩衝區溢出攻擊與防範專輯》,上面有這 篇文章。該做者在文中提到一種利用TEB(線程環境塊)來突破DEP的方法,不過它受系統版本限制,只能在XP sp2及其如下版本的windows系統 上使用,由於更高版本的系統,其TEB地址是不固定的,每次都是動態生成的。該方法的具體實現方法以下:
(1)將返回地址覆蓋成字符串複製函數的地址,好比lstrcpy,memcpy等等;
(2)在返回地址以後用目標內存地址和shellcode地址覆蓋,當執行復制操做時,就會將shellcode複製到目標內存地址,該目標內存地址位於TEB偏移0xC00的地方,它有520字節緩存用於ANSI-to-Unicode函數的轉換;
(3)複製操做結束後返回到shellcode地址並執行它。
此時其堆棧佈局以下:
【shellcode】【save ebp】【lstrcpy】【TEB緩存地址,用於複製結束後返回到shellcode】【TEB緩存地址】【ShellCode地址】

3.關閉DEP
關於此方法最原始的資料應該是黑客雜誌《uninformed》上的文章《Bypassing Windows Hardware- enforced Data Execution Prevention》(http://www.uninformed.org/?v=2& a=4),另外也能夠看下本人以前翻譯的《突破win2003 sp2中基於硬件的DEP》(http://bbs.pediy.com /showthread.php?t=99045),此方法的主要原理就是利用NtSetInformationProcess()函數來設置 KPROCESS 結構中的相關標誌位,進而關閉DEP,KPROCESS結構中相關標誌位狀況以下:

0:000> dt nt!_KPROCESS -r
ntdll!_KPROCESS
. . .
+0x06b Flags       : _KEXECUTE_OPTIONS
  +0x000 ExecuteDisable     : Pos 0, 1 Bit
  +0x000 ExecuteEnable     : Pos 1, 1 Bit
  +0x000 DisableThunkEmulation   : Pos 2, 1 Bit
  +0x000 Permanent     : Pos 3, 1 Bit
  +0x000 ExecuteDispatchEnable   : Pos 4, 1 Bit
  +0x000 ImageDispatchEnable   : Pos 5, 1 Bit
  +0x000 Spare       : Pos 6, 2 Bits
  
當DEP 被啓用時,ExecuteDisable 被置位,當DEP 被禁用,ExecuteEnable 被置位,當Permanent 標誌置位時表示這些設置是最終設置,不可更改。代碼實現:

ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE;
NtSetInformationProcess(
  NtCurrentProcess(),   // ProcessHandle = -1
  ProcessExecuteFlags,   // ProcessInformationClass = 0x22(ProcessExecuteFlags)
  &ExecuteFlags,     // ProcessInformation = 0x2(MEM_EXECUTE_OPTION_ENABLE)
  sizeof(ExecuteFlags));   // ProcessInformationLength = 0x4
    
具體實現思路(以我電腦上VirtualBox虛擬機下的xp sp3爲例):
1.將al設置爲1,好比指令mov al,1 / ret,而後用該指令地址覆蓋返回地址:

0:000> lmm ntdll
start    end        module name
7c920000 7c9b3000   ntdll      (pdb symbols)          c:\symbollocal\ntdll.pdb\1751003260CA42598C0FB326585000ED2\ntdll.pdb
0:000> s 7c920000 l 93000 b0 01 c2 04
7c9718ea  b0 01 c2 04 00 90 90 90-90 90 8b ff 55 8b ec 56  ............U..V
0:000> u 7c9718ea
ntdll!NtdllOkayToLockRoutine:
7c9718ea b001            mov     al,1
7c9718ec c20400          ret     4

因爲上面的ret 4,所以要再向棧中填充4字節(好比0xffffffff)以抵消多彈出的4字節,若是選擇的指令恰好是ret則無須再多填充4字節。

2.跳轉到ntdll!LdrpCheckNXCompatibility中的部分代碼(從cmp al,1 開始,可經過windbg下的命令 uf ntdll!LdrpCheckNXCompatibility來查看其反彙編代碼),好比如下地址就須要用0x7c93cd24來覆寫堆棧上的第 二個地址:

ntdll!LdrpCheckNXCompatibility+0x13:
7c93cd24 3c01            cmp     al,1
7c93cd26 6a02            push    2
7c93cd28 5e              pop     esi
7c93cd29 0f84df290200    je      ntdll!LdrpCheckNXCompatibility+0x1a (7c95f70e)  ; 以前已將al置1,故此處實現跳轉

3.上面跳轉後來到這裏:

0:000> u 7c95f70e
ntdll!LdrpCheckNXCompatibility+0x1a:
7c95f70e 8975fc          mov     dword ptr [ebp-4],esi  ; [ebp-0x4]= esi = 2
7c95f711 e919d6fdff      jmp     ntdll!LdrpCheckNXCompatibility+0x1d (7c93cd2f)

4.上面跳轉後來到:

0:000> u 7c93cd2f
ntdll!LdrpCheckNXCompatibility+0x1d:
7c93cd2f 837dfc00        cmp     dword ptr [ebp-4],0
7c93cd33 0f85f89a0100    jne     ntdll!LdrpCheckNXCompatibility+0x4d (7c956831) ; 不相等再次實現跳轉

5.上面跳轉後來到:

0:000> u 7c956831
ntdll!LdrpCheckNXCompatibility+0x4d:
7c956831 6a04            push    4     ;ProcessInformationLength = 4
7c956833 8d45fc          lea     eax,[ebp-4]
7c956836 50              push    eax      ;ProcessInformation = 2(MEM_EXECUTE_OPTION_ENABLE)
7c956837 6a22            push    22h       ;ProcessInformationClass = 0x22(ProcessExecuteFlags)
7c956839 6aff            push    0FFFFFFFFh
7c95683b e84074fdff      call    ntdll!ZwSetInformationProcess (7c92dc80)
7c956840 e92865feff      jmp     ntdll!LdrpCheckNXCompatibility+0x5c (7c93cd6d)
7c956845 90              nop

在這裏調用函數ZwSetInformationProcess(),而其參數也恰好達到咱們關閉DEP的各項要求.

6.最後跳轉到函數結尾:

0:000> u 7c93cd6d
ntdll!LdrpCheckNXCompatibility+0x5c:
7c93cd6d 5e              pop     esi
7c93cd6e c9              leave
7c93cd6f c20400          ret     4

最後的堆棧佈局應爲:
【AAA……】【al=1地址】【0xffffffff】【LdrpCheckNXCompatibility指令地址】【0xffffffff】【"A" x 54】【call/jmp esp】【shellcode】  
  ▲       ▲            ▲                       ▲                      ▲            ▲
填充數據  返回地址   抵消ret 4的4字節     指令cmp al,0x1 的起始地址      平衡堆棧   調整NX禁用後的堆棧 
 
若是在禁用NX後,又須要讀取esi或ebp,但此時它們又被咱們填充的數據覆蓋掉了,那麼咱們可使用諸如push esp/pop esi/ret或者push esp/pop ebp/ret這樣的指令來調整esi和ebp,以使關閉DEP後還可以正常執行。
輔助工具:ImmDbg pycommand插件(!pvefindaddr depxpsp3  + !findantidep)

3.利用WPN與ROP技術
ROP(Return Oriented Programming):連續調用程序代碼自己的內存地址,以逐步地建立一連串欲執行的指令序列。
WPM(Write Process Memory):利用微軟在kernel32.dll中定義的函數好比:WriteProcess Memory函數可將數據寫入到指定進程的內存中。但整個內存區域必須是可訪問的,不然將操做失敗。
具體實現方法參見我以前翻譯的文章《利用WPN與ROP技術繞過DEP》:http://bbs.pediy.com/showthread.php?t=119300

4.利用SEH 繞過DEP
啓用DEP後,就不能使用pop pop ret地址了,而應採用pop reg/pop reg/pop esp/ret 指令的地址,指令 pop esp 能夠改變堆棧指針,ret將執行流轉移到nseh 中的地址上(用關閉NX 例程的地址覆蓋nseh,用指向pop/pop /pop esp/ret 指令的指針覆蓋異常處理器)。
輔助工具:ImmDbg插件!pvefindaddr

4、ASLR

原理:ASLR(地址空間佈局隨機化)技術的主要功能是經過對系統關鍵地址的隨機化,防止攻擊者在堆棧溢出後利用固定的地址定位到惡意代碼並加以運行。它主要對如下四類地址進行隨機化:
(1)堆地址的隨機化;
(2)棧基址的隨機化;
(3)PE文件映像基址的隨機化;
(4)PEB(Process Environment Block,進程環境塊)地址的隨機化。
它在vista,windows 2008 server,windows7下是默認啓用的(IE7除外),非系統鏡像也能夠經過連接選項 /DYNAMICBASE(Visual Studio 2005 SP1 以上的版本,VS2008 都支持)啓用這種保護,也可手動更改已編譯庫的 dynamicbase 位,使其支持ASLR 技術(把PE 頭中的DllCharacteristics 設置成0x40 -能夠
使用工具PE EXPLORER 打開庫,查看DllCharacteristics 是否包含0x40 就能夠知道是否支持ASLR 技術)。另外,也 可使用Process Explorer來查看是否開啓ASLR。啓用ASLR後,即便你原先已經成功構造出exploit,但在系統重啓後,你在 exploit中使用的一些固定地址就會被改變,進而致使exploit失效。

繞過方法:

1.覆蓋部分返回地址
對比下windows7系統啓動先後OD中loaddll.exe的各模塊基址,啓動前:

可執行模塊
基址       大小       入口       名稱       文件版本          路徑
00400000   00060000   00410070   loaddll                      D:\riusksk\TOOL\Ollydbg\loaddll.exe
6DDE0000   0008C000   6DDE1FFF   AcLayers   6.1.7600.16385 (  C:\Windows\AppPatch\AcLayers.dll
710E0000   00012000   710E1200   mpr        6.1.7600.16385 (  C:\Windows\System32\mpr.dll
71C50000   00051000   71C79834   winspool   6.1.7600.16385 (  C:\Windows\System32\winspool.drv
747F0000   00017000   747F1C89   userenv    6.1.7600.16385 (  C:\Windows\System32\userenv.dll
750A0000   0001A000   750A2CCD   sspicli    6.1.7600.16385 (  C:\Windows\System32\sspicli.dll
750C0000   0004B000   750C2B6C   apphelp    6.1.7600.16385 (  C:\Windows\System32\apphelp.dll
75190000   0000B000   75191992   profapi    6.1.7600.16385 (  C:\Windows\System32\profapi.dll
75420000   0004A000   75427A9D   KERNELBA   6.1.7600.16385 (  C:\Windows\system32\KERNELBASE.dll
75B50000   0000A000   75B5136C   LPK        6.1.7600.16385 (  C:\Windows\system32\LPK.dll
75B60000   0004E000   75B6EC49   GDI32      6.1.7600.16385 (  C:\Windows\system32\GDI32.dll
……

啓動後:

可執行模塊
基址       大小       入口       名稱       文件版本          路徑
00400000   00060000   00410070   loaddll                      D:\riusksk\TOOL\Ollydbg\loaddll.exe
6F510000   0008C000   6F511FFF   AcLayers   6.1.7600.16385 (  C:\Windows\AppPatch\AcLayers.dll
715B0000   00012000   715B1200   mpr        6.1.7600.16385 (  C:\Windows\System32\mpr.dll
72170000   00051000   72199834   winspool   6.1.7600.16385 (  C:\Windows\System32\winspool.drv
74C70000   00017000   74C71C89   userenv    6.1.7600.16385 (  C:\Windows\System32\userenv.dll
75520000   0001A000   75522CCD   sspicli    6.1.7600.16385 (  C:\Windows\System32\sspicli.dll
75540000   0004B000   75542B6C   apphelp    6.1.7600.16385 (  C:\Windows\System32\apphelp.dll
75610000   0000B000   75611992   profapi    6.1.7600.16385 (  C:\Windows\System32\profapi.dll
75690000   0004A000   75697A9D   KERNELBA   6.1.7600.16385 (  C:\Windows\system32\KERNELBASE.dll
759B0000   000CC000   759B168B   msctf      6.1.7600.16385 (  C:\Windows\System32\msctf.dll
75E60000   000AC000   75E6A472   msvcrt     7.0.7600.16385 (  C:\Windows\system32\msvcrt.dll
75F10000   0004E000   75F1EC49   GDI32      6.1.7600.16385 (  C:\Windows\system32\GDI32.dll
……

因而可知,各模塊基址的高位是隨機變化的,而低位是固定不變的,這裏loaddll.exe不受ADSL保護,因此其基址沒有隨機化,若是是 Notepad.exe就有啓用ASLR,還有其它經連接選項/DYNAMICBASE編譯的程序也會啓用ASLR。所以咱們可讓填充字符只覆蓋到返回 地址的一半,因爲小端法機器的緣故,其低位地址在前,所以覆蓋到的一半地址恰好處於低位,而返回地址的高位咱們讓它保持不變,因此咱們必須在返回地址以前 的地址範圍內(至關於漏洞函數所在的255字節空間地址)查找出一個可跳轉到shellcode的指令,好比jmp edx(關鍵看哪一寄存器指向 shellcode)。除此以外,咱們還必須將shellcode放在返回地址以前,否則連返回地址的高位也覆蓋掉了,這是不容許的。縱觀此法,至關的有 侷限性,若是漏洞函數太短,可能就沒有咱們須要的指令了,這時就得另尋他法了。

2.利用未啓用ASLR的模塊地址
這與以前繞過SafeSEH的方法相似,直接在未受ASLR保護的模塊中查找跳轉指令的地址來覆蓋返回地址或者SEH結構,能夠經過 Process Explorer或者ImmDbg命令插件!ASLRdynamicbase或者(!pvefindaddr noaslr):來查看哪 些進程模塊啓用ASLR保護。

5、SEHOP

原理:微軟在Microsoft Windows 2008 SP0、Microsoft Windows Vista SP1和 Microsoft Windows 7中加入了另外一種新的保護機制 SEHOP(Structured Exception Handling Overwrite Protection),它可做爲SEH的擴展,用於檢 測SEH是否被覆寫。SEHOP的核心特性是用於檢測程序棧中的全部SEH結構鏈表的完整性,特別是對最後一個SHE結構的檢測。在最後一個SEH結構中 擁有一個特殊的異常處理函數指針,指向一個位於ntdll中的函數ntdll!FinalExceptHandler()。當咱們用 jmp 06 pop pop ret 來覆蓋SEH結構後,因爲SEH結構鏈表的完整性遭到破壞,SEHOP就能檢測到異常從而阻止shellcode 的運行

繞過方法:

僞造SEH鏈表
因爲SEHOP會檢測SEH鏈表的完整性,那麼咱們能夠經過僞造SEH鏈表來替換原先的SEH鏈表,進而達到繞過的目的。具體實現方法:

(1)查看SEH鏈表結構,可藉助OD實現,而後記住最後一個SEH結構地址,以方便後面的利用;
(2)用JE(0x74) + 最後一個SEH結構的地址(因爲地址開頭是00,故可省略掉,可由0x74替代,共同實現4字節對齊)去覆蓋nexSEH;
(3)用xor pop pop ret指令地址去覆蓋SEH handle,其中的xor指令是用於將ZF置位,使前面的JE = JMP指令,進而實現跳轉;
(4)在這兩個SEH結構以前寫入一跳轉指令(JMP+8),以免數據段被執行;
(5)在這兩個SEH結構之間所有用NOP填充,若是二者之間還有其它SEH結構的話;
(6)將shellcode放置在最後一個SEH結構以後,即ntdll!FinalExceptHandler()函數以後。

此時的堆棧佈局以下:
【NOP…】【JMP 08】【JE XXXXXX】【xor pop pop ret】【NOP…】【JMP 08】【0xFFFFFFFF】【ntdll!FinalExceptHandler】【shellcode】
                        ▲              ▲                                  ▲                   ▲ 
           next SEH(指向0xffffffff)  SEH Handle                          next SEH           SEH Handle

更多信息可參見我以前翻譯的《繞過SEHOP安全機制》:http://bbs.pediy.com/showthread.php?t=104707

結論
本文簡單地敘述了windows平臺上的各種溢出保護機制及其繞過方法,但若結合實例分析的話,沒有幾萬字是不可能完成的,所以這裏概覽一番,讀者若想獲 得相關的實例運用的資料,可參考文中說起一些paper,特別是由看雪論壇上dge兄弟翻譯的《Exploit編寫系列教程6》以及黑客雜誌 《Phrack》、《Uninformed》上的相關論文。微軟與黑客之間的鬥爭是永無休止的,咱們期待着下一項安全機制的出現…… php

相關文章
相關標籤/搜索