SafeSEH原理及繞過技術(shù)淺析

修改整理自 http://blog.csdn.net/magictong/article/details/7517630 侵刪

作者:magictong

時間:2012年3月16日星期五

摘要:主要介紹SafeSEH的基本原理和SafeSEH的繞過技術(shù)仁期,重點在原理介紹越庇。
關(guān)鍵詞:SafeSEH;繞過技術(shù);異常處理

前言

設(shè)計SafeSEH保護(hù)機制的目的,以為了防止那種攻擊者通過覆蓋堆棧上的異常處理函數(shù)句柄,從而控制程序執(zhí)行流程的攻擊。

自Windwos XP SP2之后,微軟就已經(jīng)引入了SafeSEH技術(shù)兑徘。不過由于SafeSEH需要編譯器在編譯PE文件時進(jìn)行特殊支持才能發(fā)揮作用,而xpsp2下的系統(tǒng)文件基本都是不支持SafeSEH的編譯器編譯的羡洛,因此在xpsp2下挂脑,SafeSEH還沒有發(fā)揮作用(VS2003及更高版本的編譯器中已經(jīng)開始支持)藕漱。

從Vista開始,由于系統(tǒng)PE文件基本都是由支持SafeSEH的編譯器編譯的崭闲,因此從Vista開始肋联,SafeSEH開始發(fā)揮他強大的作用,對于以前那種簡單的通過覆蓋異常處理句柄的漏洞利用技術(shù)刁俭,也就基本失效了橄仍。

SafeSEH的保護(hù)原理

SafeSEH的基本原理很簡單,即在調(diào)用異常處理函數(shù)之前牍戚,對要調(diào)用的異常處理函數(shù)進(jìn)行一系列的有效性校驗侮繁,如果發(fā)現(xiàn)異常處理函數(shù)不可靠(被覆蓋了,被篡改了)如孝,立即終止異常處理函數(shù)的調(diào)用宪哩。不過SafeSEH需要編譯器和系統(tǒng)雙重支持,缺少一個則保護(hù)能力基本就喪失了第晰。下面從兩個方面來闡述怎樣來實現(xiàn)SafeSEH锁孟。

(1)二進(jìn)制層面

首先我們先看看編譯器做了些什么事情(通過啟用鏈接選項/SafeSEH即可使編譯出來的二進(jìn)制文件具備SafeSEH功能,微軟VS2003及以后的編譯器已經(jīng)默認(rèn)支持)茁瘦。在編譯器生成二進(jìn)制IMAGE的時候品抽,把所有合法的SEH函數(shù)的地址解析出來,在IMAGE里生成一張合法的SEH函數(shù)表甜熔,用于異常處理時候進(jìn)行嚴(yán)格的匹配檢查圆恤。可以使用VC下面的dumpbin工具查看一個二進(jìn)制文件的config信息腔稀,這樣調(diào)用dumpbin /loadconfig file_all_path_filename盆昙。


這里寫圖片描述

輸出的可能是下面這樣(注:tttt.exe使用vs2005編譯):

Dump of file H:\Prj_N\tttt\Release\tttt.exe

 

File Type: EXECUTABLE IMAGE

 

  Section contains the following load config:

 

            00000048 size

                   0 time date stamp

                0.00 Version

                   0 GlobalFlags Clear

                   0 GlobalFlags Set

                   0 Critical Section Default Timeout

                   0 Decommit Free Block Threshold

                   0 Decommit Total Free Threshold

            00000000 Lock Prefix Table

                   0 Maximum Allocation Size

                   0 Virtual Memory Threshold

                   0 Process Heap Flags

                   0 Process Affinity Mask

                   0 CSD Version

                0000 Reserved

            00000000 Edit list

            00403018 Security Cookie

            00402360 Safe Exception Handler Table

                   1 Safe Exception Handler Count

 

    Safe Exception Handler Table

 

          Address

          --------

          004018A1  __except_handler4

 

  Summary

 

        1000 .data

        1000 .rdata

        1000 .rsrc

        1000 .text

注意里面 Safe Exception Handler Table 部分,這就是該二進(jìn)制文件里面的SEH異常處理函數(shù)地址表烧颖。上面的輸出實際上涉及如下的一個結(jié)構(gòu)弱左,是保存在二進(jìn)制文件里面的一份配置表:

#include <windows.h>

extern DWORD_PTR __security_cookie;  /* /GS security cookie */

 

/*

 * The following two names are automatically created by the linker for any

 * image that has the safe exception table present.

*/

 

extern PVOID __safe_se_handler_table[]; /* base of safe handler entry table */

extern BYTE  __safe_se_handler_count;  /* absolute symbol whose address is

                                           the count of table entries */

typedef struct {

    DWORD       Size;

    DWORD       TimeDateStamp;

    WORD        MajorVersion;

    WORD        MinorVersion;

    DWORD       GlobalFlagsClear;

    DWORD       GlobalFlagsSet;

    DWORD       CriticalSectionDefaultTimeout;

    DWORD       DeCommitFreeBlockThreshold;

    DWORD       DeCommitTotalFreeThreshold;

    DWORD       LockPrefixTable;            // VA

    DWORD       MaximumAllocationSize;

    DWORD       VirtualMemoryThreshold;

    DWORD       ProcessHeapFlags;

    DWORD       ProcessAffinityMask;

    WORD        CSDVersion;

    WORD        Reserved1;

    DWORD       EditList;                   // VA

    DWORD_PTR   *SecurityCookie;

    PVOID       *SEHandlerTable;

    DWORD       SEHandlerCount;

} IMAGE_LOAD_CONFIG_DIRECTORY32_2;

 

const IMAGE_LOAD_CONFIG_DIRECTORY32_2 _load_config_used = {

    sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_2),

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    0,

    &__security_cookie,

    __safe_se_handler_table,

    (DWORD)(DWORD_PTR) &__safe_se_handler_count

};

(2)系統(tǒng)層面

基本過程如下(XP SP2和VISTA一樣)窄陡。

加載準(zhǔn)備過程:

加載PE文件時炕淮,定位和讀出合法SEH函數(shù)表的地址(如果該IMAGE是不支持SafeSEH的,則這個SEH函數(shù)表的地址為0)跳夭,并使用共享內(nèi)存中的一個隨機數(shù)加密涂圆。將加密后的SEH函數(shù)表地址,IMAGE的開始地址币叹,IMAGE的長度润歉,合法SEH函數(shù)的個數(shù),作為一條記錄放入ntdll(ntdll模塊是進(jìn)行異常分發(fā)的模塊)的加載模塊數(shù)據(jù)內(nèi)存中颈抚。

異常發(fā)生后踩衩,異常處理過程如下(RtlDispatchException框架偽碼):

void RtlDispatchException(...)

{

if (exception record is not on the stack)

goto corruption;

if (handler is on the stack)

goto corruption;

if (RtlIsValidHandler(handler, process_flags) == FALSE)

goto corruption;

// execute handler

RtlpExecuteHandlerForException(handler, ...)

...

}

RtlDispatchException()這個函數(shù)的檢測主要分三步,首先檢查異常處理節(jié)點是否在棧上,如果不在棧上程序?qū)⒔K止異常處理驱富,其次檢查異常處理句柄是否在棧上锚赤,如果在棧上程序?qū)⒅巩惓L幚恚@兩個檢測可以防止那種在堆上偽造異常鏈和把shellcode放置在棧上的情況褐鸥。最后檢測handler的有效性线脚,這才是SafeSEH的重點。

下面看一下RtlIsValidHandler的偽碼(vista sp1):

BOOL RtlIsValidHandler(handler)

{

if (handler is in an image)

{

         // 在加載模塊的進(jìn)程空間

if (image has the IMAGE_DLLCHARACTERISTICS_NO_SEH flag set)

return FALSE; // 該標(biāo)志設(shè)置叫榕,忽略異常處理浑侥,直接返回FALSE

if (image has a SafeSEH table) // 是否含有SEH表

if (handler found in the table)

return TRUE; // 異常處理handle在表中,返回TRUE

else

return FALSE; // 異常處理handle不在表中晰绎,返回FALSE

if (image is a .NET assembly with the ILonly flag set)

return FALSE; // .NET 返回FALSE

// fall through

}

 

if (handler is on a non-executable page)

{

         // handle在不可執(zhí)行頁上面

if (ExecuteDispatchEnable bit set in the process flags)

return TRUE; // DEP關(guān)閉寓落,返回TRUE;否則拋出異常

else

raise ACCESS_VIOLATION; // enforce DEP even if we have no hardware NX

}

 

if (handler is not in an image)

{

         // 在加載模塊內(nèi)存之外寒匙,并且是可執(zhí)行頁

if (ImageDispatchEnable bit set in the process flags)

return TRUE; // 允許在加載模塊內(nèi)存空間外執(zhí)行零如,返回驗證成功

else

return FALSE; // don't allow handlers outside of images

}

 

// everything else is allowed

return TRUE;

}

對上面的偽碼的理解,請看代碼注釋和流程圖:


這里寫圖片描述

偽碼里面的ExecuteDispatchEnable和ImageDispatchEnable位標(biāo)志是內(nèi)核KPROCESS結(jié)構(gòu)的一部分锄弱,這兩個位用來控制當(dāng)異常處理函數(shù)在不可以執(zhí)行內(nèi)存或者不在異常模塊的映像(IMAGE)內(nèi)時考蕾,是否執(zhí)行異常處理函數(shù)。這兩個位的值可以在運行時修改会宪,不過默認(rèn)情況下如果進(jìn)程的DEP被關(guān)閉肖卧,則這兩個位置1,如果進(jìn)程的DEP是開啟狀態(tài)掸鹅,則這兩個位被置0塞帐。

在進(jìn)程的DEP是開啟的情況,有兩種異常處理函數(shù)被異常分發(fā)器認(rèn)為是有效的:

  • 異常處理函數(shù)在進(jìn)程映像的SafeSEH表中巍沙,并且沒有NO_SEH標(biāo)志葵姥。
  • 異常處理函數(shù)在進(jìn)程映像的可執(zhí)行頁,并且沒有NO_SEH標(biāo)志句携,沒有SafeSEH表榔幸,沒有.NET的ILonly標(biāo)志。

在進(jìn)程的DEP關(guān)閉的情況下矮嫉,有三種情況異常處理函數(shù)被異常分發(fā)器認(rèn)為是有效的:

  • 異常處理函數(shù)在進(jìn)程映像的SafeSEH表中削咆,并且沒有NO_SEH標(biāo)志。
  • 異常處理函數(shù)在進(jìn)程映像的可執(zhí)行頁蠢笋,并且沒有NO_SEH標(biāo)志拨齐,沒有SafeSEH表,沒有.NET的ILonly標(biāo)志昨寞。
  • 異常處理函數(shù)不在當(dāng)前進(jìn)程的映像里面瞻惋,但是不在當(dāng)前線程的堆棧上厦滤。

這里的偽碼是非常簡單的,還有很多值得探討的問題歼狼,譬如ntdll里面馁害,當(dāng)前異常處理句柄是怎么和SEH表進(jìn)行對比的等等,不過這暫時不列入討論蹂匹。

怎么關(guān)掉編譯器的SafeSEH支持

雖然我不知道你為什么要這么做碘菜,而且我覺得很瘋狂,但是方法還是有的限寞。以 VC6 為例忍啸,在編譯器的屬性框Liker|CommandLine的Additional options 加入/SAFESEH:NO即可,見下圖履植。


這里寫圖片描述

怎樣檢測一個PE文件是否啟用了SafeSEH

前面介紹過數(shù)據(jù)目錄里面的一個結(jié)構(gòu)(IMAGE_LOAD_CONFIG_DIRECTORY)计雌,該結(jié)構(gòu)的成員SEHandlerTable是指向合法SEH處理程序地址列表的指針,成員SEHandlerCount是數(shù)目玫霎。而IMAGE_LOAD_CONFIG_DIRECTORY這個結(jié)構(gòu)體只有/SAFESEH選項設(shè)置了才存在凿滤,因此,就可以根據(jù)它來判斷PE文件是否加了/SAFESEH鏈接選項庶近。這個結(jié)構(gòu)在PE中的偏移由PE附加頭IMAGE_DATA_DIRECTORY 數(shù)組的第11項指定翁脆。

#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG  10  // Load Configuration Directory

繞過方法簡介

(1)利用堆地址覆蓋SEH結(jié)構(gòu)繞過SafeSEH

上面講過,在禁用DEP的進(jìn)程中鼻种,異常分發(fā)器允許SEH handler位于除椃捶空間之外的非映像頁面。也就是說我們可以把shellcode放置在堆中叉钥,然后通過覆蓋SEH跳至堆空間以執(zhí)行shellcode罢缸,這樣即可繞過SafeSEH保護(hù)。

(2)利用沒有啟用SafeSEH保護(hù)的模塊繞過SafeSEH

在介紹原理時講過投队,在國內(nèi)枫疆,目前大部分的PC都是安裝的Windows XP,也就是說對于大部分Windows操作系統(tǒng)敷鸦,其系統(tǒng)模塊都沒有受到SafeSEH保護(hù)息楔,可以選用未開啟SafeSEH保護(hù)的模塊來利用,另外轧膘,現(xiàn)在還有很多VC6編譯的軟件钞螟,這些軟件本身和自帶的dll文件兔甘,都是可能沒有SafeSEH保護(hù)的谎碍。這時就可以使用它里面的指令作為跳板來繞過SafeSEH。

(3)利用加載模塊之外的地址繞過SafeSEH

同樣是根據(jù)SafeSEH的原理可知洞焙,對于加載模塊之外的地址蟆淀,SafeSEH同樣是不進(jìn)行有效性檢測的(當(dāng)然假設(shè)是DEP是關(guān)閉的拯啦,或者DEP已經(jīng)被繞過)。

注:繞過方法這里沒有細(xì)講熔任,原因是沒有找到很好的例子褒链,在《0day安全:軟件漏洞分析技術(shù)》上面有自己書籍作者自己寫的例子。以后這塊再詳說疑苔。

參考文獻(xiàn)

[1] Preventing the Exploitation of Structured Exception Handler (SEH) Overwrites with SEHOP

http://blogs.technet.com/b/srd/archive/2009/02/02/preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx

[2] SafeSEH筆記http://pstgroup.blogspot.com/2007/08/tipssafeseh.html

[3] /SAFESEH (Image has Safe Exception Handlers)

http://msdn.microsoft.com/en-us/library/9a89h429(VS.80).aspx

[4] 0day安全:軟件漏洞分析技術(shù)(第二版)

[5] Bypassing Browser Memory Protections

[6] pecoff_v8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甫匹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惦费,更是在濱河造成了極大的恐慌兵迅,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薪贫,死亡現(xiàn)場離奇詭異恍箭,居然都是意外死亡,警方通過查閱死者的電腦和手機瞧省,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門扯夭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鞍匾,你說我怎么就攤上這事交洗。” “怎么了橡淑?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵藕筋,是天一觀的道長。 經(jīng)常有香客問我梳码,道長隐圾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任掰茶,我火速辦了婚禮暇藏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘濒蒋。我一直安慰自己盐碱,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布沪伙。 她就那樣靜靜地躺著瓮顽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪围橡。 梳的紋絲不亂的頭發(fā)上暖混,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機與錄音翁授,去河邊找鬼拣播。 笑死晾咪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贮配。 我是一名探鬼主播谍倦,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泪勒!你這毒婦竟也來了昼蛀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤圆存,失蹤者是張志新(化名)和其女友劉穎曹洽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辽剧,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡送淆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了怕轿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偷崩。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撞羽,靈堂內(nèi)的尸體忽然破棺而出阐斜,到底是詐尸還是另有隱情,我是刑警寧澤诀紊,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布谒出,位于F島的核電站,受9級特大地震影響邻奠,放射性物質(zhì)發(fā)生泄漏笤喳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一碌宴、第九天 我趴在偏房一處隱蔽的房頂上張望杀狡。 院中可真熱鬧,春花似錦贰镣、人聲如沸呜象。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恭陡。三九已至,卻和暖如春上煤,著一層夾襖步出監(jiān)牢的瞬間休玩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哥捕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓嘉熊,卻偏偏與公主長得像遥赚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子阐肤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容