SEH in ASM 研究(一)
生活随笔
收集整理的這篇文章主要介紹了
SEH in ASM 研究(一)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
SEH? in ASM 研究(一)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? By Hume/冷雨飄心
為什么老調(diào)重彈:
? ? SEH出現(xiàn)已絕非一日,但很多人可能還不徹底了解Seh的運(yùn)行機(jī)制;有關(guān)seh的知識資料不是很多,asm級的詳細(xì)資料就
更少!seh不僅可以簡化程序錯(cuò)誤處理,使你的程序更加健壯,還被廣泛應(yīng)用于反跟蹤以及加解密中,因此,了解seh非常必要,
但遺憾的是關(guān)于seh詳細(xì)介紹的中文資料非常少,在實(shí)踐的基礎(chǔ)上,把自己學(xué)習(xí)的一點(diǎn)筆記奉獻(xiàn)給大家,希望對喜歡ASM的朋
友有所幫助.如有錯(cuò)誤,請高手不吝指正.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PART? I? 簡單接觸
一、SEH背景知識
SEH("Structured Exception Handling"),即結(jié)構(gòu)化異常處理.是操作系統(tǒng)提供給程序設(shè)計(jì)者的強(qiáng)有力的處理程序錯(cuò)
誤或異常的武器.在VISUAL C++中你或許已經(jīng)熟悉了_try{} _finally{} 和_try{} _except {} 結(jié)構(gòu),這些并不是
編譯程序本身所固有的,本質(zhì)上只不過是對windows內(nèi)在提供的結(jié)構(gòu)化異常處理的包裝,不用這些高級語言編譯器所提供
的包裝 ,照樣可以利用系統(tǒng)提供的強(qiáng)大seh處理功能,在后面你將可以看到,用系統(tǒng)本身提供seh結(jié)構(gòu)和規(guī)則以及ASM語言,
我們將對SEH的機(jī)制以及實(shí)現(xiàn)有一個(gè)徹底的了解.
發(fā)生異常時(shí)系統(tǒng)的處理順序(by Jeremy Gordon):
? ??1.系統(tǒng)首先判斷異常是否應(yīng)發(fā)送給目標(biāo)程序的異常處理例程,如果決定應(yīng)該發(fā)送,并且目標(biāo)程序正在被調(diào)試,則系統(tǒng)
? ??掛起程序并向調(diào)試器發(fā)送EXCEPTION_DEBUG_EVENT消息.呵呵,這不是正好可以用來探測調(diào)試器的存在嗎?
? ??2.如果你的程序沒有被調(diào)試或者調(diào)試器未能處理異常,系統(tǒng)就會繼續(xù)查找你是否安裝了線程相關(guān)的異常處理例程,如果
? ??你安裝了線程相關(guān)的異常處理例程,系統(tǒng)就把異常發(fā)送給你的程序seh處理例程,交由其處理.
? ??3.每個(gè)線程相關(guān)的異常處理例程可以處理或者不處理這個(gè)異常,如果他不處理并且安裝了多個(gè)線程相關(guān)的異常處理例程,
? ? ? ? 可交由鏈起來的其他例程處理.
? ??4.如果這些例程均選擇不處理異常,如果程序處于被調(diào)試狀態(tài),操作系統(tǒng)仍會再次掛起程序通知debugger.
? ??5.如果程序未處于被調(diào)試狀態(tài)或者debugger沒有能夠處理,并且你調(diào)用SetUnhandledExceptionFilter安裝了最后異
? ??常處理例程的話,系統(tǒng)轉(zhuǎn)向?qū)λ恼{(diào)用.
? ??6.如果你沒有安裝最后異常處理例程或者他沒有處理這個(gè)異常,系統(tǒng)會調(diào)用默認(rèn)的系統(tǒng)處理程序,通常顯示一個(gè)對話框,
? ??你可以選擇關(guān)閉或者最后將其附加到調(diào)試器上的調(diào)試按鈕.如果沒有調(diào)試器能被附加于其上或者調(diào)試器也處理不了,系統(tǒng)
? ??就調(diào)用ExitProcess終結(jié)程序.
? ??7.不過在終結(jié)之前,系統(tǒng)仍然對發(fā)生異常的線程異常處理句柄來一次展開,這是線程異常處理例程最后清理的機(jī)會.
如果你看了上面的步驟一頭霧水的話,別著急,化點(diǎn)時(shí)間慢慢理解或者進(jìn)入下一部分實(shí)例操作.
二.初步實(shí)戰(zhàn)演習(xí):
? 安裝異常處理句柄.
?
? 有兩種類型的異常處理句柄,一種是final型的,這是在你的異常未能得到線程相關(guān)處理例程處理操作系統(tǒng)在即將關(guān)閉程序之前會
? 回調(diào)的例程,這個(gè)例程是進(jìn)程相關(guān)的而不是線程相關(guān)的,因此無論是哪個(gè)線程發(fā)生異常未能被處理,都會調(diào)用這個(gè)例程.
? ? I. 見下面的例子1:
;//================================例子1---final型的異常處理=================
;// ex. 1,by Hume,2001,just copy make your own hd.h and compile&link
;//========================================================================
.386
.model flat, stdcall
option casemap :none? ; case sensitive
include hd.h? ? ? ? ? ;//相關(guān)的頭文件,你自己維護(hù)一個(gè)吧
;//============================
.data
szCap? ??db "By Hume[AfO],2001...",0
szMsgOK db "OK,the exceptoin was handled by final handler!",0
szMsgERR1 db "It would never Get here!",0
buff? ? db 200 dup(0)
.code
_start:
;//========prog begin====================
? ??lea? ??eax,Final_Handler
? ??invoke? ??SetUnhandledExceptionFilter,eax? ;//調(diào)用SetUnhandledExceptionFilter來安裝final SEH
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//原型很簡單SetUnhandledExceptionFilter proto
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//pTopLevelExceptionFilter:DWORD
? ? ? ? xor? ? ecx,ecx
? ? ? ? mov? ? eax,200? ??
? ? ? ? cdq
? ??div? ??ecx
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//以下永遠(yuǎn)不會被執(zhí)行
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgERR1,addr szCap,MB_OK+MB_ICONEXCLAMATION
? ? ? ? invoke? ??ExitProcess,NULL
? ? ? ?
;//============================
Final_Handler:
? ??invoke? ??MessageBox,NULL,addr szMsgOK,addr szCap,MB_OK+MB_ICONEXCLAMATION
? ??mov? ??eax,EXCEPTION_EXECUTE_HANDLER? ? ? ? ;//==1 這時(shí)不出現(xiàn)非法操作的討厭對話框
? ??;mov? ??eax,EXCEPTION_CONTINUE_SEARCH? ? ;//==0 出現(xiàn),這時(shí)是調(diào)用系統(tǒng)默認(rèn)的異常處理過程,程序被終結(jié)了
? ? ;mov? ? eax,EXCEPTION_CONTINUE_EXECUTION? ;//==-1 不斷出現(xiàn)對話框,你將陷入死循環(huán),可別怪我
? ??ret? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;因?yàn)槲覀儾]有修復(fù)ecx,所以不斷產(chǎn)生異常,然后不斷調(diào)用這個(gè)例程
;//=============================Prog Ends==============
end _start
COMMENT $
? 簡單來解釋幾句,windows根據(jù)你的異常處理程序的返回值來決定如何進(jìn)一步處理
? ? ? ? EXCEPTION_EXECUTE_HANDLER? ? ? ? ? ? equ 1? ? 表示我已經(jīng)處理了異常,可以優(yōu)雅地結(jié)束了
? ? ? ? EXCEPTION_CONTINUE_SEARCH? ? ? ? ? ? equ 0? ? 表示我不處理,其他人來吧,于是windows調(diào)用默認(rèn)的處理程序
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 顯示一個(gè)錯(cuò)誤框,并結(jié)束
? ? ? ? EXCEPTION_CONTINUE_EXECUTION? ? ? ? equ -1? 表示錯(cuò)誤已經(jīng)被修復(fù),請從異常發(fā)生處繼續(xù)執(zhí)行
? ? ? ? 你可以試著讓程序返回0和-1然后編譯程序,就會理解我所有蒼白無力的語言...
$
;//========================================================================
? ? II.另一種是per_Thread Exception Handler->線程相關(guān)的異常處理,通常每個(gè)線程初始化準(zhǔn)備好運(yùn)行時(shí)fs指向一個(gè)TIB結(jié)構(gòu)
? ? (THREAD INFORMATION BLOCK),這個(gè)結(jié)構(gòu)的第一個(gè)元素fs:[0]指向一個(gè)_EXCEPTION_REGISTRATION結(jié)構(gòu)
? ? 后面_EXCEPTION_REGISTRATION為了簡化,用ERR來代替這個(gè)結(jié)構(gòu)...不要說沒見過啊...
? ? fs:[0]->
? ? _EXCEPTION_REGISTRATION struc
? ? prev dd ?? ? ? ? ? ? ? ? ? ? ? ;前一個(gè)_EXCEPTION_REGISTRATION結(jié)構(gòu)
? ? handler dd ?? ? ? ? ? ? ? ? ? ;異常處理例程入口....呵呵,現(xiàn)在明白該怎么作了吧
? ? _EXCEPTION_REGISTRATION ends
? ? 我們可以建立一個(gè)ERR結(jié)構(gòu)然后將fs:[0]換成指向他的指針,當(dāng)然最常用的是堆棧,如果你用靜態(tài)內(nèi)存區(qū)也可以,沒有人阻止你
? ? 在asm世界,放心地干吧,除了多S幾次之外,通常不會有更大的損失
? ? 把handler域換成你的程序入口,就可以在發(fā)生異常時(shí)調(diào)用你的代碼了,好馬上實(shí)踐一下,見例子2
;//========================================================================
;// ex. 2,by Hume,2001? 線程相關(guān)的異常處理
;//========================================================================
.386
.model flat, stdcall
option casemap :none? ; case sensitive
include hd.h? ? ? ? ? ;//相關(guān)的頭文件,你自己維護(hù)一個(gè)吧
;//============================
.data
szCap? ??db "By Hume[AfO],2001...",0
szMsgOK db "It's now in the Per_Thread handler!",0
szMsgERR1 db "It would never Get here!",0
buff? ? db 200 dup(0)
.code
_start:
;//========prog begin====================
? ASSUME FS:NOTHING
? ? ? ? push? ? offset perThread_Handler
? ??push? ? fs:[0]? ? ?
? ? ? ? mov? ? fs:[0],esp? ? ? ? ? ? ? ? ? ? ? ;//建立SEH的基本ERR結(jié)構(gòu),如果不明白,就仔細(xì)研究一下吧
? ? ? ? xor? ? ecx,ecx? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? mov? ? eax,200? ??
? ? ? ? cdq
? ??div? ??ecx
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//以下永遠(yuǎn)不會被執(zhí)行
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgERR1,addr szCap,MB_OK+MB_ICONINFORMATION
? ? ? ? pop? ? fs:[0]
? ? ? ? add? ? esp,4
? ? ? ? invoke? ??ExitProcess,NULL? ? ? ?
;//============================
perThread_Handler:
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgOK,addr szCap,MB_OK+MB_ICONINFORMATION
? ? ? ? mov? ? eax,1? ? ? ? ? ;//ExceptionContinueSearch,不處理,由其他例程或系統(tǒng)處理
? ? ? ? ;mov? ? eax,0? ? ? ? ? ;//ExceptionContinueExecution,表示已經(jīng)修復(fù)CONTEXT,可從異常發(fā)生處繼續(xù)執(zhí)行
? ??ret? ? ? ? ? ? ? ? ? ? ? ? ;//這里如果返回0,你會陷入死循環(huán),不斷跳出對話框....
;//=============================Prog Ends==============
end _start
COMMENT $
? 嘿嘿,這個(gè)簡單吧,我們由于沒有足夠的資料,暫時(shí)還不能修復(fù)ecx的值使之從異常發(fā)生處繼續(xù)執(zhí)行,只是簡單顯示一個(gè)MSG,然后
? 讓系統(tǒng)處理,自然跳出討厭的對話框了....
? 注意和final返回值的含義不同...
$
;//==================================================================================================
好像到此為止,我們并沒有從異常處理中得到任何好處,除了在異常發(fā)生后可以執(zhí)行一點(diǎn)我們微不足道的代碼,事實(shí)上SEH可以修復(fù)這些
異常或者干我們想干的事情然后從希望的地方繼續(xù)執(zhí)行,嘿嘿,很爽吧,可惜我們沒有足夠的信息,那里找到我們所需要的信息?
欲知后事如何,且看下回分解...
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? PARTII? ? 繼續(xù)深入
? ? ? ? ? ? ? ? ? ? ? ? ? ? ....(待續(xù),睡個(gè)覺先)
三、傳遞給異常處理句柄的參數(shù)
? ? ? 要想明白seh處理例程如何得到感興趣的信息,首先要明白SEH的作用機(jī)制.事實(shí)上,當(dāng)異常
發(fā)生時(shí),系統(tǒng)給了我們一個(gè)處理異常的機(jī)會,他首先會調(diào)用我們自定義的seh處理例程,當(dāng)然也包括
了相關(guān)信息,在調(diào)用之前,系統(tǒng)把包含這些信息結(jié)構(gòu)的指針壓入stack,供我們的異常處理例程調(diào)用,
傳遞給例程的參數(shù)通常是四個(gè),其中只有三個(gè)有明確意義,另一個(gè)到現(xiàn)在為止還沒有發(fā)現(xiàn)有什么作用,
這些參數(shù)是:pExcept:DWORD,pErr:DWORD,pContext:DWORD,pDispatch意義如下:
pExcept:? ---? EXCEPTION_RECORD結(jié)構(gòu)的指針
pErr:? ? ---? 前面ERR結(jié)構(gòu)的指針
pContext: --- CONTEXT結(jié)構(gòu)的指針
pDispatch:---沒有發(fā)現(xiàn)有啥意義
? ? ERR結(jié)構(gòu)是前面介紹的_EXCEPTION_REGISTRATION結(jié)構(gòu),往前翻翻,Dispatch省略,下面介紹
EXCEPTION_RECORD和CONTEXT結(jié)構(gòu)的定義:
?
;//================================以下是兩個(gè)成員的詳細(xì)結(jié)構(gòu)========================================
? ??? ??EXCEPTION_RECORD STRUCT
? ??? ??? ExceptionCode? ? ? ? DWORD? ? ? ?? ? ? ;//異常碼
? ??? ??? ExceptionFlags? ? ? ? DWORD? ? ? ?? ??? ;//異常標(biāo)志
? ??? ??? pExceptionRecord? ? ? DWORD? ? ? ?? ? ? ;//指向另外一個(gè)EXCEPTION_RECORD的指針
? ??? ??? ExceptionAddress? ? ? DWORD? ? ? ?? ? ? ;//異常發(fā)生的地址
? ??? ??? NumberParameters? ? ? DWORD? ? ? ?? ? ? ;//下面ExceptionInformation所含有的dword數(shù)目
? ??? ??? ExceptionInformation? DWORD EXCEPTION_MAXIMUM_PARAMETERS dup(?)
? ??? ??EXCEPTION_RECORD ENDS? ? ? ? ? ? ? ? ? ? ? ;//EXCEPTION_MAXIMUM_PARAMETERS ==15
;//================================具體解釋========================================
ExceptionCode 異常類型,SDK里面有很多類型,你可以在windows.inc里查找STATUS_來找到更多
的異常類型,下面只給出hex值,具體標(biāo)識定義請查閱windows.inc,你最可能遇到的幾種類型如下:
? ? ? ? ? ? ? C0000005h----讀寫內(nèi)存沖突
? ? ? ? ? ? ? C0000094h----非法除0
? ? ? ? ? ? ? C00000FDh----堆棧溢出或者說越界
? ? ? ? ? ? ? 80000001h----由Virtual Alloc建立起來的屬性頁沖突
? ? ? ? ? ? ? C0000025h----不可持續(xù)異常,程序無法恢復(fù)執(zhí)行,異常處理例程不應(yīng)處理這個(gè)異常
? ? ? ? ? ? ? C0000026h----在異常處理過程中系統(tǒng)使用的代碼,如果系統(tǒng)從某個(gè)例程莫名奇妙的返回,則出現(xiàn)此代碼,
? ? ? ? ? ? ? ? ? ? ? ? ? 如果RtlUnwind時(shí)沒有Exception Record參數(shù)也同樣會填入這個(gè)代碼
? ? ? ? ? ? ? 80000003h----調(diào)試時(shí)因代碼中int3中斷
? ? ? ? ? ? ? 80000004h----處于被單步調(diào)試狀態(tài)
? ? ? ? ? ? ? 注:也可以自己定義異常代碼,遵循如下規(guī)則:
? ? ? ? ? ? ? _____________________________________________________________________+
? ? ? ? ? ? ? 位:? ? ? 31~30? ? ? ? ? ? 29~28? ? ? ? ? 27~16? ? ? ? ? 15~0
? ? ? ? ? ? ? _____________________________________________________________________+
? ? ? ? ? ? ? 含義:? ? 嚴(yán)重程度? ? ? ? ? 29位? ? ? ? ? ? 功能代碼? ? ? ? 異常代碼
? ? ? ? ? ? ? ? ? ? ? ? 0==成功? ? ? ? 0==Mcrosoft? ? MICROSOFT定義? 用戶定義
? ? ? ? ? ? ? ? ? ? ? ? 1==通知? ? ? ? 1==客戶
? ? ? ? ? ? ? ? ? ? ? ? 2==警告? ? ? ? ? 28位
? ? ? ? ? ? ? ? ? ? ? ? 3==錯(cuò)誤? ? ? ? 被保留必須為0
ExceptionFlags 異常標(biāo)志
? ? ? ? ? ? ? 0----可修復(fù)異常
? ? ? ? ? ? ? 1----不可修復(fù)異常
? ? ? ? ? ? ? 2----正在展開,不要試圖修復(fù)什么,需要的話,釋放必要的資源
pExceptionRecord 如果程序本身導(dǎo)致異常,指向那個(gè)異常結(jié)構(gòu)
ExceptionAddress 發(fā)生異常的eip地址
ExceptionInformation 附加消息,在調(diào)用RaiseException可指定或者在異常號為C0000005h即內(nèi)存異常時(shí)含義如下
? ? ? ? ? ? ? 第一個(gè)dword 0==讀沖突 1==寫沖突
? ? ? ? ? ? ? 第二個(gè)dword 讀寫沖突地址
;//================================解釋結(jié)束========================================
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? off.
? ??? ??CONTEXT STRUCT? ? ? ? ? ? ? ? ? ? ; _
? ??? ??? ContextFlags? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +0
? ??? ??? iDr0? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +4
? ??? ??? iDr1? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +8
? ??? ??? iDr2? ? ? ? ? DWORD? ? ? ?? ? ? ;? >調(diào)試寄存器? +C
? ??? ??? iDr3? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +10
? ??? ??? iDr6? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +14
? ??? ??? iDr7? ? ? ? ? DWORD? ? ? ?? ? ? ; _|? ? ? ? ? ? +18
? ??? ??? FloatSave? ? FLOATING_SAVE_AREA <>? ;浮點(diǎn)寄存器區(qū) +1C~~~88h
? ??? ??? regGs? ? ? ? DWORD? ? ? ?? ? ? ;--|? ? ? ? ? ? +8C
? ??? ??? regFs? ? ? ? DWORD? ? ? ?? ? ? ;? |/段寄存器? ? +90?
? ??? ??? regEs? ? ? ? DWORD? ? ? ?? ? ? ;? |/? ? ? ? ? ? +94? ? ? ? ? ?
? ??? ??? regDs? ? ? ? DWORD? ? ? ?? ? ? ;--|? ? ? ? ? ? +98
? ??? ??? regEdi? ? ? ? DWORD? ? ? ?? ? ? ;____________? ? +9C
? ??? ??? regEsi? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 通用? +A0
? ??? ??? regEbx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 寄? ? +A4
? ??? ??? regEdx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 存? ? +A8
? ??? ??? regEcx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 器? ? +AC
? ??? ??? regEax? ? ? ? DWORD? ? ? ?? ? ? ;_______|___組_? +B0? ? ?
? ??? ??? regEbp? ? ? ? DWORD? ? ? ?? ? ? ;++++++++++++++++ +B4
? ??? ??? regEip? ? ? ? DWORD? ? ? ?? ? ? ;? ? |控制? ? ? ? +B8
? ??? ??? regCs? ? ? ? DWORD? ? ? ?? ? ? ;? ? |寄存? ? ? ? +BC
? ??? ??? regFlag? ? ? DWORD? ? ? ?? ? ? ;? ? |器組? ? ? ? +C0
? ??? ??? regEsp? ? ? ? DWORD? ? ? ?? ? ? ;? ? |? ? ? ? ? ? +C4
? ??? ??? regSs? ? ? ? DWORD? ? ? ?? ? ? ;++++++++++++++++ +C8
? ??? ??? ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?)
? ??? ??CONTEXT ENDS
;//================================以上是兩個(gè)成員的詳細(xì)結(jié)構(gòu)========================================
? ?
? ? ? ? I、傳遞給final句柄的參數(shù),只有兩個(gè)可描述為EXCEPTION_POINTERS結(jié)構(gòu),定義如下:
? ? ? ? ? ? EXCEPTION_POINTERS STRUCT
? ? ? ? ? ? ? pExceptionRecord? DWORD? ? ? ?? ? ? ? ? ? ?
? ? ? ? ? ? ? ContextRecord? ? DWORD? ? ? ?
? ? ? ? ? ? EXCEPTION_POINTERS ENDS
? ? ? ? ? ? 在call xHandler之前,堆棧結(jié)構(gòu)如下:
? ? ? ? ? ? esp? ? -> *EXCEPTION_RECORD
? ??? ? ? ? esp+4? -> *CONTEXT record? ;//具體結(jié)構(gòu)見下面
? ? ? ? ? ? ? ? 然后執(zhí)行call _Final_Handler,這樣在程序里要調(diào)用什么不輕而易舉了嗎?
? ?
? ? II、 傳遞給per_thread句柄的參數(shù),如下:
? ? 在call xHandler之前,在堆棧中形成如下結(jié)構(gòu)
? ? ? ? ? ? esp? ? -> *EXCEPTION_RECORD
? ??? ? ? ? esp+4? -> *ERR? ? ? ? ? ? ? ? ? ? ;//注意這也就是fs:[0]的指向
? ??? ? ? ? esp? ? -> *CONTEXT record? ? ? ? ? ;//point to registers
? ??? ? ? ? esp? ? -> *Param? ? ? ? ? ? ? ? ? ? ;//呵呵,沒有啥意義
? ? ? ? ? 然后執(zhí)行 call _Per_Thread_Handler
調(diào)用handler的原型是這樣
? ??? ??invoke HANDLER,*EXCEPTION_RECORD,*_EXCEPTION_REGISTRATION,*CONTEXT record,*Param
? ??? ??即編譯代碼如下:
? ??? ??PUSH *Param? ? ? ? ? ? ? ? ? ? ;//通常不重要,沒有什么意義
? ??? ??push *CONTEXT record? ? ? ? ? ? ;//上面的結(jié)構(gòu)
? ??? ??push *ERR? ? ? ? ? ? ? ? ? ? ? ;//the struc above
? ??? ??push *EXCEPTION_RECORD? ? ? ? ? ;//see above
? ??? ??CALL HANDLER
? ??? ??ADD ESP,10h
好現(xiàn)在你明白了應(yīng)該如何訪問具體有關(guān)系統(tǒng)信息的細(xì)節(jié)了吧,下一部分,讓我們來看看如何應(yīng)用...(待續(xù))
SEH不僅僅是加殼者的寶刀,也是脫殼者的利箭。 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? By Hume/冷雨飄心
為什么老調(diào)重彈:
? ? SEH出現(xiàn)已絕非一日,但很多人可能還不徹底了解Seh的運(yùn)行機(jī)制;有關(guān)seh的知識資料不是很多,asm級的詳細(xì)資料就
更少!seh不僅可以簡化程序錯(cuò)誤處理,使你的程序更加健壯,還被廣泛應(yīng)用于反跟蹤以及加解密中,因此,了解seh非常必要,
但遺憾的是關(guān)于seh詳細(xì)介紹的中文資料非常少,在實(shí)踐的基礎(chǔ)上,把自己學(xué)習(xí)的一點(diǎn)筆記奉獻(xiàn)給大家,希望對喜歡ASM的朋
友有所幫助.如有錯(cuò)誤,請高手不吝指正.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? PART? I? 簡單接觸
一、SEH背景知識
SEH("Structured Exception Handling"),即結(jié)構(gòu)化異常處理.是操作系統(tǒng)提供給程序設(shè)計(jì)者的強(qiáng)有力的處理程序錯(cuò)
誤或異常的武器.在VISUAL C++中你或許已經(jīng)熟悉了_try{} _finally{} 和_try{} _except {} 結(jié)構(gòu),這些并不是
編譯程序本身所固有的,本質(zhì)上只不過是對windows內(nèi)在提供的結(jié)構(gòu)化異常處理的包裝,不用這些高級語言編譯器所提供
的包裝 ,照樣可以利用系統(tǒng)提供的強(qiáng)大seh處理功能,在后面你將可以看到,用系統(tǒng)本身提供seh結(jié)構(gòu)和規(guī)則以及ASM語言,
我們將對SEH的機(jī)制以及實(shí)現(xiàn)有一個(gè)徹底的了解.
發(fā)生異常時(shí)系統(tǒng)的處理順序(by Jeremy Gordon):
? ??1.系統(tǒng)首先判斷異常是否應(yīng)發(fā)送給目標(biāo)程序的異常處理例程,如果決定應(yīng)該發(fā)送,并且目標(biāo)程序正在被調(diào)試,則系統(tǒng)
? ??掛起程序并向調(diào)試器發(fā)送EXCEPTION_DEBUG_EVENT消息.呵呵,這不是正好可以用來探測調(diào)試器的存在嗎?
? ??2.如果你的程序沒有被調(diào)試或者調(diào)試器未能處理異常,系統(tǒng)就會繼續(xù)查找你是否安裝了線程相關(guān)的異常處理例程,如果
? ??你安裝了線程相關(guān)的異常處理例程,系統(tǒng)就把異常發(fā)送給你的程序seh處理例程,交由其處理.
? ??3.每個(gè)線程相關(guān)的異常處理例程可以處理或者不處理這個(gè)異常,如果他不處理并且安裝了多個(gè)線程相關(guān)的異常處理例程,
? ? ? ? 可交由鏈起來的其他例程處理.
? ??4.如果這些例程均選擇不處理異常,如果程序處于被調(diào)試狀態(tài),操作系統(tǒng)仍會再次掛起程序通知debugger.
? ??5.如果程序未處于被調(diào)試狀態(tài)或者debugger沒有能夠處理,并且你調(diào)用SetUnhandledExceptionFilter安裝了最后異
? ??常處理例程的話,系統(tǒng)轉(zhuǎn)向?qū)λ恼{(diào)用.
? ??6.如果你沒有安裝最后異常處理例程或者他沒有處理這個(gè)異常,系統(tǒng)會調(diào)用默認(rèn)的系統(tǒng)處理程序,通常顯示一個(gè)對話框,
? ??你可以選擇關(guān)閉或者最后將其附加到調(diào)試器上的調(diào)試按鈕.如果沒有調(diào)試器能被附加于其上或者調(diào)試器也處理不了,系統(tǒng)
? ??就調(diào)用ExitProcess終結(jié)程序.
? ??7.不過在終結(jié)之前,系統(tǒng)仍然對發(fā)生異常的線程異常處理句柄來一次展開,這是線程異常處理例程最后清理的機(jī)會.
如果你看了上面的步驟一頭霧水的話,別著急,化點(diǎn)時(shí)間慢慢理解或者進(jìn)入下一部分實(shí)例操作.
二.初步實(shí)戰(zhàn)演習(xí):
? 安裝異常處理句柄.
?
? 有兩種類型的異常處理句柄,一種是final型的,這是在你的異常未能得到線程相關(guān)處理例程處理操作系統(tǒng)在即將關(guān)閉程序之前會
? 回調(diào)的例程,這個(gè)例程是進(jìn)程相關(guān)的而不是線程相關(guān)的,因此無論是哪個(gè)線程發(fā)生異常未能被處理,都會調(diào)用這個(gè)例程.
? ? I. 見下面的例子1:
;//================================例子1---final型的異常處理=================
;// ex. 1,by Hume,2001,just copy make your own hd.h and compile&link
;//========================================================================
.386
.model flat, stdcall
option casemap :none? ; case sensitive
include hd.h? ? ? ? ? ;//相關(guān)的頭文件,你自己維護(hù)一個(gè)吧
;//============================
.data
szCap? ??db "By Hume[AfO],2001...",0
szMsgOK db "OK,the exceptoin was handled by final handler!",0
szMsgERR1 db "It would never Get here!",0
buff? ? db 200 dup(0)
.code
_start:
;//========prog begin====================
? ??lea? ??eax,Final_Handler
? ??invoke? ??SetUnhandledExceptionFilter,eax? ;//調(diào)用SetUnhandledExceptionFilter來安裝final SEH
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//原型很簡單SetUnhandledExceptionFilter proto
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//pTopLevelExceptionFilter:DWORD
? ? ? ? xor? ? ecx,ecx
? ? ? ? mov? ? eax,200? ??
? ? ? ? cdq
? ??div? ??ecx
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//以下永遠(yuǎn)不會被執(zhí)行
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgERR1,addr szCap,MB_OK+MB_ICONEXCLAMATION
? ? ? ? invoke? ??ExitProcess,NULL
? ? ? ?
;//============================
Final_Handler:
? ??invoke? ??MessageBox,NULL,addr szMsgOK,addr szCap,MB_OK+MB_ICONEXCLAMATION
? ??mov? ??eax,EXCEPTION_EXECUTE_HANDLER? ? ? ? ;//==1 這時(shí)不出現(xiàn)非法操作的討厭對話框
? ??;mov? ??eax,EXCEPTION_CONTINUE_SEARCH? ? ;//==0 出現(xiàn),這時(shí)是調(diào)用系統(tǒng)默認(rèn)的異常處理過程,程序被終結(jié)了
? ? ;mov? ? eax,EXCEPTION_CONTINUE_EXECUTION? ;//==-1 不斷出現(xiàn)對話框,你將陷入死循環(huán),可別怪我
? ??ret? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;因?yàn)槲覀儾]有修復(fù)ecx,所以不斷產(chǎn)生異常,然后不斷調(diào)用這個(gè)例程
;//=============================Prog Ends==============
end _start
COMMENT $
? 簡單來解釋幾句,windows根據(jù)你的異常處理程序的返回值來決定如何進(jìn)一步處理
? ? ? ? EXCEPTION_EXECUTE_HANDLER? ? ? ? ? ? equ 1? ? 表示我已經(jīng)處理了異常,可以優(yōu)雅地結(jié)束了
? ? ? ? EXCEPTION_CONTINUE_SEARCH? ? ? ? ? ? equ 0? ? 表示我不處理,其他人來吧,于是windows調(diào)用默認(rèn)的處理程序
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 顯示一個(gè)錯(cuò)誤框,并結(jié)束
? ? ? ? EXCEPTION_CONTINUE_EXECUTION? ? ? ? equ -1? 表示錯(cuò)誤已經(jīng)被修復(fù),請從異常發(fā)生處繼續(xù)執(zhí)行
? ? ? ? 你可以試著讓程序返回0和-1然后編譯程序,就會理解我所有蒼白無力的語言...
$
;//========================================================================
? ? II.另一種是per_Thread Exception Handler->線程相關(guān)的異常處理,通常每個(gè)線程初始化準(zhǔn)備好運(yùn)行時(shí)fs指向一個(gè)TIB結(jié)構(gòu)
? ? (THREAD INFORMATION BLOCK),這個(gè)結(jié)構(gòu)的第一個(gè)元素fs:[0]指向一個(gè)_EXCEPTION_REGISTRATION結(jié)構(gòu)
? ? 后面_EXCEPTION_REGISTRATION為了簡化,用ERR來代替這個(gè)結(jié)構(gòu)...不要說沒見過啊...
? ? fs:[0]->
? ? _EXCEPTION_REGISTRATION struc
? ? prev dd ?? ? ? ? ? ? ? ? ? ? ? ;前一個(gè)_EXCEPTION_REGISTRATION結(jié)構(gòu)
? ? handler dd ?? ? ? ? ? ? ? ? ? ;異常處理例程入口....呵呵,現(xiàn)在明白該怎么作了吧
? ? _EXCEPTION_REGISTRATION ends
? ? 我們可以建立一個(gè)ERR結(jié)構(gòu)然后將fs:[0]換成指向他的指針,當(dāng)然最常用的是堆棧,如果你用靜態(tài)內(nèi)存區(qū)也可以,沒有人阻止你
? ? 在asm世界,放心地干吧,除了多S幾次之外,通常不會有更大的損失
? ? 把handler域換成你的程序入口,就可以在發(fā)生異常時(shí)調(diào)用你的代碼了,好馬上實(shí)踐一下,見例子2
;//========================================================================
;// ex. 2,by Hume,2001? 線程相關(guān)的異常處理
;//========================================================================
.386
.model flat, stdcall
option casemap :none? ; case sensitive
include hd.h? ? ? ? ? ;//相關(guān)的頭文件,你自己維護(hù)一個(gè)吧
;//============================
.data
szCap? ??db "By Hume[AfO],2001...",0
szMsgOK db "It's now in the Per_Thread handler!",0
szMsgERR1 db "It would never Get here!",0
buff? ? db 200 dup(0)
.code
_start:
;//========prog begin====================
? ASSUME FS:NOTHING
? ? ? ? push? ? offset perThread_Handler
? ??push? ? fs:[0]? ? ?
? ? ? ? mov? ? fs:[0],esp? ? ? ? ? ? ? ? ? ? ? ;//建立SEH的基本ERR結(jié)構(gòu),如果不明白,就仔細(xì)研究一下吧
? ? ? ? xor? ? ecx,ecx? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? mov? ? eax,200? ??
? ? ? ? cdq
? ??div? ??ecx
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ;//以下永遠(yuǎn)不會被執(zhí)行
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgERR1,addr szCap,MB_OK+MB_ICONINFORMATION
? ? ? ? pop? ? fs:[0]
? ? ? ? add? ? esp,4
? ? ? ? invoke? ??ExitProcess,NULL? ? ? ?
;//============================
perThread_Handler:
? ? ? ? invoke? ??MessageBox,NULL,addr szMsgOK,addr szCap,MB_OK+MB_ICONINFORMATION
? ? ? ? mov? ? eax,1? ? ? ? ? ;//ExceptionContinueSearch,不處理,由其他例程或系統(tǒng)處理
? ? ? ? ;mov? ? eax,0? ? ? ? ? ;//ExceptionContinueExecution,表示已經(jīng)修復(fù)CONTEXT,可從異常發(fā)生處繼續(xù)執(zhí)行
? ??ret? ? ? ? ? ? ? ? ? ? ? ? ;//這里如果返回0,你會陷入死循環(huán),不斷跳出對話框....
;//=============================Prog Ends==============
end _start
COMMENT $
? 嘿嘿,這個(gè)簡單吧,我們由于沒有足夠的資料,暫時(shí)還不能修復(fù)ecx的值使之從異常發(fā)生處繼續(xù)執(zhí)行,只是簡單顯示一個(gè)MSG,然后
? 讓系統(tǒng)處理,自然跳出討厭的對話框了....
? 注意和final返回值的含義不同...
$
;//==================================================================================================
好像到此為止,我們并沒有從異常處理中得到任何好處,除了在異常發(fā)生后可以執(zhí)行一點(diǎn)我們微不足道的代碼,事實(shí)上SEH可以修復(fù)這些
異常或者干我們想干的事情然后從希望的地方繼續(xù)執(zhí)行,嘿嘿,很爽吧,可惜我們沒有足夠的信息,那里找到我們所需要的信息?
欲知后事如何,且看下回分解...
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? PARTII? ? 繼續(xù)深入
? ? ? ? ? ? ? ? ? ? ? ? ? ? ....(待續(xù),睡個(gè)覺先)
標(biāo) 題:SEH in ASM 研究(二) (6千字)
發(fā)信人:hume
時(shí) 間:2001-12-29 11:54:47
詳細(xì)信息:
三、傳遞給異常處理句柄的參數(shù)
? ? ? 要想明白seh處理例程如何得到感興趣的信息,首先要明白SEH的作用機(jī)制.事實(shí)上,當(dāng)異常
發(fā)生時(shí),系統(tǒng)給了我們一個(gè)處理異常的機(jī)會,他首先會調(diào)用我們自定義的seh處理例程,當(dāng)然也包括
了相關(guān)信息,在調(diào)用之前,系統(tǒng)把包含這些信息結(jié)構(gòu)的指針壓入stack,供我們的異常處理例程調(diào)用,
傳遞給例程的參數(shù)通常是四個(gè),其中只有三個(gè)有明確意義,另一個(gè)到現(xiàn)在為止還沒有發(fā)現(xiàn)有什么作用,
這些參數(shù)是:pExcept:DWORD,pErr:DWORD,pContext:DWORD,pDispatch意義如下:
pExcept:? ---? EXCEPTION_RECORD結(jié)構(gòu)的指針
pErr:? ? ---? 前面ERR結(jié)構(gòu)的指針
pContext: --- CONTEXT結(jié)構(gòu)的指針
pDispatch:---沒有發(fā)現(xiàn)有啥意義
? ? ERR結(jié)構(gòu)是前面介紹的_EXCEPTION_REGISTRATION結(jié)構(gòu),往前翻翻,Dispatch省略,下面介紹
EXCEPTION_RECORD和CONTEXT結(jié)構(gòu)的定義:
?
;//================================以下是兩個(gè)成員的詳細(xì)結(jié)構(gòu)========================================
? ??? ??EXCEPTION_RECORD STRUCT
? ??? ??? ExceptionCode? ? ? ? DWORD? ? ? ?? ? ? ;//異常碼
? ??? ??? ExceptionFlags? ? ? ? DWORD? ? ? ?? ??? ;//異常標(biāo)志
? ??? ??? pExceptionRecord? ? ? DWORD? ? ? ?? ? ? ;//指向另外一個(gè)EXCEPTION_RECORD的指針
? ??? ??? ExceptionAddress? ? ? DWORD? ? ? ?? ? ? ;//異常發(fā)生的地址
? ??? ??? NumberParameters? ? ? DWORD? ? ? ?? ? ? ;//下面ExceptionInformation所含有的dword數(shù)目
? ??? ??? ExceptionInformation? DWORD EXCEPTION_MAXIMUM_PARAMETERS dup(?)
? ??? ??EXCEPTION_RECORD ENDS? ? ? ? ? ? ? ? ? ? ? ;//EXCEPTION_MAXIMUM_PARAMETERS ==15
;//================================具體解釋========================================
ExceptionCode 異常類型,SDK里面有很多類型,你可以在windows.inc里查找STATUS_來找到更多
的異常類型,下面只給出hex值,具體標(biāo)識定義請查閱windows.inc,你最可能遇到的幾種類型如下:
? ? ? ? ? ? ? C0000005h----讀寫內(nèi)存沖突
? ? ? ? ? ? ? C0000094h----非法除0
? ? ? ? ? ? ? C00000FDh----堆棧溢出或者說越界
? ? ? ? ? ? ? 80000001h----由Virtual Alloc建立起來的屬性頁沖突
? ? ? ? ? ? ? C0000025h----不可持續(xù)異常,程序無法恢復(fù)執(zhí)行,異常處理例程不應(yīng)處理這個(gè)異常
? ? ? ? ? ? ? C0000026h----在異常處理過程中系統(tǒng)使用的代碼,如果系統(tǒng)從某個(gè)例程莫名奇妙的返回,則出現(xiàn)此代碼,
? ? ? ? ? ? ? ? ? ? ? ? ? 如果RtlUnwind時(shí)沒有Exception Record參數(shù)也同樣會填入這個(gè)代碼
? ? ? ? ? ? ? 80000003h----調(diào)試時(shí)因代碼中int3中斷
? ? ? ? ? ? ? 80000004h----處于被單步調(diào)試狀態(tài)
? ? ? ? ? ? ? 注:也可以自己定義異常代碼,遵循如下規(guī)則:
? ? ? ? ? ? ? _____________________________________________________________________+
? ? ? ? ? ? ? 位:? ? ? 31~30? ? ? ? ? ? 29~28? ? ? ? ? 27~16? ? ? ? ? 15~0
? ? ? ? ? ? ? _____________________________________________________________________+
? ? ? ? ? ? ? 含義:? ? 嚴(yán)重程度? ? ? ? ? 29位? ? ? ? ? ? 功能代碼? ? ? ? 異常代碼
? ? ? ? ? ? ? ? ? ? ? ? 0==成功? ? ? ? 0==Mcrosoft? ? MICROSOFT定義? 用戶定義
? ? ? ? ? ? ? ? ? ? ? ? 1==通知? ? ? ? 1==客戶
? ? ? ? ? ? ? ? ? ? ? ? 2==警告? ? ? ? ? 28位
? ? ? ? ? ? ? ? ? ? ? ? 3==錯(cuò)誤? ? ? ? 被保留必須為0
ExceptionFlags 異常標(biāo)志
? ? ? ? ? ? ? 0----可修復(fù)異常
? ? ? ? ? ? ? 1----不可修復(fù)異常
? ? ? ? ? ? ? 2----正在展開,不要試圖修復(fù)什么,需要的話,釋放必要的資源
pExceptionRecord 如果程序本身導(dǎo)致異常,指向那個(gè)異常結(jié)構(gòu)
ExceptionAddress 發(fā)生異常的eip地址
ExceptionInformation 附加消息,在調(diào)用RaiseException可指定或者在異常號為C0000005h即內(nèi)存異常時(shí)含義如下
? ? ? ? ? ? ? 第一個(gè)dword 0==讀沖突 1==寫沖突
? ? ? ? ? ? ? 第二個(gè)dword 讀寫沖突地址
;//================================解釋結(jié)束========================================
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? off.
? ??? ??CONTEXT STRUCT? ? ? ? ? ? ? ? ? ? ; _
? ??? ??? ContextFlags? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +0
? ??? ??? iDr0? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +4
? ??? ??? iDr1? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +8
? ??? ??? iDr2? ? ? ? ? DWORD? ? ? ?? ? ? ;? >調(diào)試寄存器? +C
? ??? ??? iDr3? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +10
? ??? ??? iDr6? ? ? ? ? DWORD? ? ? ?? ? ? ;? |? ? ? ? ? ? +14
? ??? ??? iDr7? ? ? ? ? DWORD? ? ? ?? ? ? ; _|? ? ? ? ? ? +18
? ??? ??? FloatSave? ? FLOATING_SAVE_AREA <>? ;浮點(diǎn)寄存器區(qū) +1C~~~88h
? ??? ??? regGs? ? ? ? DWORD? ? ? ?? ? ? ;--|? ? ? ? ? ? +8C
? ??? ??? regFs? ? ? ? DWORD? ? ? ?? ? ? ;? |/段寄存器? ? +90?
? ??? ??? regEs? ? ? ? DWORD? ? ? ?? ? ? ;? |/? ? ? ? ? ? +94? ? ? ? ? ?
? ??? ??? regDs? ? ? ? DWORD? ? ? ?? ? ? ;--|? ? ? ? ? ? +98
? ??? ??? regEdi? ? ? ? DWORD? ? ? ?? ? ? ;____________? ? +9C
? ??? ??? regEsi? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 通用? +A0
? ??? ??? regEbx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 寄? ? +A4
? ??? ??? regEdx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 存? ? +A8
? ??? ??? regEcx? ? ? ? DWORD? ? ? ?? ? ? ;? ? ? |? 器? ? +AC
? ??? ??? regEax? ? ? ? DWORD? ? ? ?? ? ? ;_______|___組_? +B0? ? ?
? ??? ??? regEbp? ? ? ? DWORD? ? ? ?? ? ? ;++++++++++++++++ +B4
? ??? ??? regEip? ? ? ? DWORD? ? ? ?? ? ? ;? ? |控制? ? ? ? +B8
? ??? ??? regCs? ? ? ? DWORD? ? ? ?? ? ? ;? ? |寄存? ? ? ? +BC
? ??? ??? regFlag? ? ? DWORD? ? ? ?? ? ? ;? ? |器組? ? ? ? +C0
? ??? ??? regEsp? ? ? ? DWORD? ? ? ?? ? ? ;? ? |? ? ? ? ? ? +C4
? ??? ??? regSs? ? ? ? DWORD? ? ? ?? ? ? ;++++++++++++++++ +C8
? ??? ??? ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?)
? ??? ??CONTEXT ENDS
;//================================以上是兩個(gè)成員的詳細(xì)結(jié)構(gòu)========================================
? ?
? ? ? ? I、傳遞給final句柄的參數(shù),只有兩個(gè)可描述為EXCEPTION_POINTERS結(jié)構(gòu),定義如下:
? ? ? ? ? ? EXCEPTION_POINTERS STRUCT
? ? ? ? ? ? ? pExceptionRecord? DWORD? ? ? ?? ? ? ? ? ? ?
? ? ? ? ? ? ? ContextRecord? ? DWORD? ? ? ?
? ? ? ? ? ? EXCEPTION_POINTERS ENDS
? ? ? ? ? ? 在call xHandler之前,堆棧結(jié)構(gòu)如下:
? ? ? ? ? ? esp? ? -> *EXCEPTION_RECORD
? ??? ? ? ? esp+4? -> *CONTEXT record? ;//具體結(jié)構(gòu)見下面
? ? ? ? ? ? ? ? 然后執(zhí)行call _Final_Handler,這樣在程序里要調(diào)用什么不輕而易舉了嗎?
? ?
? ? II、 傳遞給per_thread句柄的參數(shù),如下:
? ? 在call xHandler之前,在堆棧中形成如下結(jié)構(gòu)
? ? ? ? ? ? esp? ? -> *EXCEPTION_RECORD
? ??? ? ? ? esp+4? -> *ERR? ? ? ? ? ? ? ? ? ? ;//注意這也就是fs:[0]的指向
? ??? ? ? ? esp? ? -> *CONTEXT record? ? ? ? ? ;//point to registers
? ??? ? ? ? esp? ? -> *Param? ? ? ? ? ? ? ? ? ? ;//呵呵,沒有啥意義
? ? ? ? ? 然后執(zhí)行 call _Per_Thread_Handler
調(diào)用handler的原型是這樣
? ??? ??invoke HANDLER,*EXCEPTION_RECORD,*_EXCEPTION_REGISTRATION,*CONTEXT record,*Param
? ??? ??即編譯代碼如下:
? ??? ??PUSH *Param? ? ? ? ? ? ? ? ? ? ;//通常不重要,沒有什么意義
? ??? ??push *CONTEXT record? ? ? ? ? ? ;//上面的結(jié)構(gòu)
? ??? ??push *ERR? ? ? ? ? ? ? ? ? ? ? ;//the struc above
? ??? ??push *EXCEPTION_RECORD? ? ? ? ? ;//see above
? ??? ??CALL HANDLER
? ??? ??ADD ESP,10h
好現(xiàn)在你明白了應(yīng)該如何訪問具體有關(guān)系統(tǒng)信息的細(xì)節(jié)了吧,下一部分,讓我們來看看如何應(yīng)用...(待續(xù))
標(biāo) 題:一家之言,一種利用SEH技術(shù)脫殼的思路。 (699字)
發(fā)信人:idtemu
時(shí) 間:2001-12-29 17:30:24
詳細(xì)信息:
SEH不僅僅是加殼者的寶刀,也是脫殼者的利箭。 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的SEH in ASM 研究(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 菜鸟也能搞定C++内存泄漏
- 下一篇: linux卸载python3.6,当py