SEH处理异常
Win32為每個(gè)線程定義了一個(gè)線程信息塊,其中保存了線程的一些屬性數(shù)據(jù),線程信息塊的屬性被定義為NT_TIB結(jié)構(gòu)
typedef struct _NT_TIB {
?? ?struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
?? ?PVOID StackBase;
?? ?PVOID StackLimit;
?? ?PVOID SubSystemTib;
?? ?union {
?? ? ? ?PVOID FiberData;
?? ? ? ?ULONG Version;
?? ?};
?? ?PVOID ArbitraryUserPointer;
?? ?struct _NT_TIB *Self;
} NT_TIB;
ExceptionList指向一個(gè)EXCEPTION_REGISTRATION結(jié)構(gòu)-也就是SEH鏈的入口地址
?
EXCEPTION_REGISTRATION STRUCT
? prev????????? ?dd?????? ??????????????????????? ;前一個(gè)EXCEPTION_REGISTRATION結(jié)構(gòu)的地址
?handler???? dd?????? ???????????????????????? ;異常處理回調(diào)函數(shù)的地址
EXCEPTION_REGISTRATION ends
?所以? 一系列的EXCEPTION_REGISTRATION結(jié)構(gòu)? 就組成了一個(gè)SEH鏈...
?
TIB是放在fs段寄存器指向的數(shù)據(jù)段的0偏移處? 所以 fs;[0]指向TIB結(jié)構(gòu)的ExceptionList字段,由于同一個(gè)進(jìn)程中 有不同的線程,所以不同線程中的fs段寄存器可以使用不同的值,這種特性使得每個(gè)線程都可以設(shè)置不同的回調(diào)函數(shù)
?
如果內(nèi)存是從高到低構(gòu)建...棧則也是從高到低構(gòu)建....那么對(duì)于棧而言
push offset _Handler?????????? ;異常處理程序的回調(diào)函數(shù)地址
push fs:[0]?????????????????????????????? ;上一個(gè)EXCEPTION_REGISTRATION結(jié)構(gòu)的地址
mov?? fs:[0],esp?????????????????????? ;設(shè)置當(dāng)前EXCEPTION_REGISTRATION結(jié)構(gòu)的地址
esp此時(shí) 正好指向你構(gòu)建的EXCEPTION_REGISTRATION結(jié)構(gòu)體
?
SEH異常處理回調(diào)函數(shù)的參數(shù)定義與篩選器器的回調(diào)函數(shù)的參數(shù)定義有所不同,其定義如下,其調(diào)用約定為C格式,
_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
_lpExceptionRecord? 指向EXCEPTION_RECORD結(jié)構(gòu)(保存異常的相關(guān)信息)
_lpContext?????????????????? 指向一個(gè)Thread Context結(jié)構(gòu)-保存線程上下文
_lpSEH?????????????????????????指向注冊(cè)回調(diào)函數(shù)時(shí)EXCEPTION_REGISTRATION結(jié)構(gòu)的首地址--利用這個(gè)字段可以用棧來(lái)傳遞一些自定義數(shù)據(jù)如SafeCode地址
?
回調(diào)函數(shù)的返回值:
ExceptionContinueExecution(等于0):回調(diào)函數(shù)返回后,系統(tǒng)將線程環(huán)境設(shè)置為_(kāi)lpContext參數(shù)指定的CONTEXT結(jié)構(gòu)并繼續(xù)執(zhí)行
ExceptionContinueSearch(等于1):回調(diào)函數(shù)拒絕處理這個(gè)異常,系統(tǒng)將通過(guò) EXCEPTION_REGISTRATION結(jié)構(gòu)的prev字段得到前一個(gè)回調(diào)函數(shù)的地址并調(diào)用他
ExceptionNestedException(等于2):回調(diào)函數(shù)執(zhí)行過(guò)程中,又發(fā)生了新的異常,即觸發(fā)了嵌套異常
ExceptionCollidedUnwind(等于3):發(fā)生了嵌套展開(kāi)操作
?
代碼:
<span style="font-family:Microsoft YaHei;font-size:13px;"> .386.model flat,stdcalloption casemap:none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.libL macro var:VARARGLOCAL @lbl.const@lbl db var,0.codeexitm <offset @lbl> endm ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;Code Segment ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ;SEH Handler ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContextLOCAL @szBuffer[256]:BYTEpushadmov esi,_lpExceptionRecordmov edi,_lpContextassume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXTinvoke wsprintf,addr @szBuffer,L("異常位置:%08x,異常代碼:%08x,異常標(biāo)志:%08x"),[edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlagsinvoke MessageBox,NULL,addr @szBuffer,L("---"),MB_OKmov eax,_lpSEHpush [eax + 8]pop [edi].regEippush [eax + 0ch]pop [edi].regEsp ;這個(gè)是屬于當(dāng)前線程的-而不是當(dāng)前的棧指針assume esi:nothing,edi:nothingpopadmov eax,ExceptionContinueExecution ;這個(gè)會(huì)先返回到內(nèi)核里面去ret_Handler endp start:assume fs:nothingpush ebp ;添加的自定義數(shù)據(jù)push offset _SafePlace ;添加的自定義數(shù)據(jù)......push offset _Handlerpush fs:[0]mov fs:[0],espxor eax,eaxmov dword ptr [eax],0_SafePlace:invoke MessageBox,NULL,L("----"),L("----"),MB_OKpop fs:[0]add esp,0ch ;恢復(fù)棧平衡invoke ExitProcess,NULL end start </span>
?
總結(jié)