Win32為每個線程定義了一個線程信息塊,其中保存了線程的一些屬性數據,線程信息塊的屬性被定義為NT_TIB結構
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指向一個EXCEPTION_REGISTRATION結構-也就是SEH鏈的入口地址
?
EXCEPTION_REGISTRATION STRUCT
? prev????????? ?dd?????? ??????????????????????? ;前一個EXCEPTION_REGISTRATION結構的地址
?handler???? dd?????? ???????????????????????? ;異常處理回調函數的地址
EXCEPTION_REGISTRATION ends
?所以? 一系列的EXCEPTION_REGISTRATION結構? 就組成了一個SEH鏈...
?
TIB是放在fs段寄存器指向的數據段的0偏移處? 所以 fs;[0]指向TIB結構的ExceptionList字段,由于同一個進程中 有不同的線程,所以不同線程中的fs段寄存器可以使用不同的值,這種特性使得每個線程都可以設置不同的回調函數
?
如果內存是從高到低構建...棧則也是從高到低構建....那么對于棧而言
push offset _Handler?????????? ;異常處理程序的回調函數地址
push fs:[0]?????????????????????????????? ;上一個EXCEPTION_REGISTRATION結構的地址
mov?? fs:[0],esp?????????????????????? ;設置當前EXCEPTION_REGISTRATION結構的地址
esp此時 正好指向你構建的EXCEPTION_REGISTRATION結構體
?
SEH異常處理回調函數的參數定義與篩選器器的回調函數的參數定義有所不同,其定義如下,其調用約定為C格式,
_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
_lpExceptionRecord? 指向EXCEPTION_RECORD結構(保存異常的相關信息)
_lpContext?????????????????? 指向一個Thread Context結構-保存線程上下文
_lpSEH?????????????????????????指向注冊回調函數時EXCEPTION_REGISTRATION結構的首地址--利用這個字段可以用棧來傳遞一些自定義數據如SafeCode地址
?
回調函數的返回值:
ExceptionContinueExecution(等于0):回調函數返回后,系統將線程環境設置為_lpContext參數指定的CONTEXT結構并繼續執行
ExceptionContinueSearch(等于1):回調函數拒絕處理這個異常,系統將通過 EXCEPTION_REGISTRATION結構的prev字段得到前一個回調函數的地址并調用他
ExceptionNestedException(等于2):回調函數執行過程中,又發生了新的異常,即觸發了嵌套異常
ExceptionCollidedUnwind(等于3):發生了嵌套展開操作
?
代碼:
<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,異常標志:%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 ;這個是屬于當前線程的-而不是當前的棧指針assume esi:nothing,edi:nothingpopadmov eax,ExceptionContinueExecution ;這個會先返回到內核里面去ret_Handler endp
start:assume fs:nothingpush ebp ;添加的自定義數據push offset _SafePlace ;添加的自定義數據......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 ;恢復棧平衡invoke ExitProcess,NULL
end start
</span>
?