SEH異常處理


SEH是應用最為廣泛,卻沒有被微軟公開技術之一,所有不同windows版本,SEH可能有所不同。

SEH鏈表位置:fs:[0]->線程信息塊TIB,TIB.ExceptionList->SEH鏈表

一)有關SEH鏈表結構:

1)線程信息塊TIB結構

kd> dt _NT_TIB
nt!_NT_TIB
   +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD            ;SEH鏈表頭
   +0x004 StackBase        : Ptr32 Void
   +0x008 StackLimit       : Ptr32 Void
   +0x00c SubSystemTib     : Ptr32 Void
   +0x010 FiberData        : Ptr32 Void
   +0x010 Version          : Uint4B
   +0x014 ArbitraryUserPointer : Ptr32 Void
   +0x018 Self             : Ptr32 _NT_TIB

2)鏈表節點

_EXCEPTION_REGISTRATION struc

    prev           dd ?                   ;下一個_EXCEPTION_REGISTRATION結構

    handler       dd ?                   ;異常處理函數地址

_EXCEPTION_REGISTRATION ends

3)異常處理函數約定

_Exception_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

  ret

_Exception_Handler endp

3.1)異常處理函數為系統回調,調用方式不是stdcall而是C方式調用。

3.2)參數說明

參數類型分別為:(一般只用前3個參數)

struct _EXCEPTION_RECORD * pExceptionRecord,

struct EXCEPTION_REGISTRATION * pRegistrationFrame,

struct _CONTEXT *pContextRecord,

void * pDispatcherContext

第一個參數

kd> dt _EXCEPTION_RECORD
nt!_EXCEPTION_RECORD
   +0x000 ExceptionCode    : Int4B                                    ;異常代碼
   +0x004 ExceptionFlags   : Uint4B                                    ;異常標志
   +0x008 ExceptionRecord  : Ptr32 _EXCEPTION_RECORD
   +0x00c ExceptionAddress : Ptr32 Void                             ;產生異常的地址
   +0x010 NumberParameters : Uint4B
   +0x014 ExceptionInformation : [15] Uint4B

 第二參數

為新插入到SEH鏈表的新節點,利用此參數,既可恢復ebp、esp寄存器,也可通過堆棧傳遞數據。如:

線程代碼為:

_Test  proc

;********************************************************************
; 在堆棧中構造一個 EXCEPTION_REGISTRATION 結構
;********************************************************************
  assume fs:nothing
  push ebp
  push offset _SafePlace
  push offset _Handler
  push fs:[0]
  mov fs:[0],esp
;********************************************************************
; 會引發異常的指令
;********************************************************************
  pushad
  xor ebp,ebp
  xor eax,eax
  mov dword ptr [eax],0
  popad  ;這一句將無法被執行
_SafePlace:
  invoke MessageBox,NULL,addr szSafe,addr szCaption,MB_OK
;********************************************************************
; 恢復原來的 SEH 鏈
;********************************************************************
  pop fs:[0]
  add esp,0ch
  ret

_Test  endp

異常處理函數為:

_Handler proc C _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
  local @szBuffer[256]:byte

  pushad
  mov esi,_lpExceptionRecord
  mov edi,_lpContext
  assume esi:ptr EXCEPTION_RECORD,edi:ptr CONTEXT
  invoke wsprintf,addr @szBuffer,addr szMsg,\
   [edi].regEip,[esi].ExceptionCode,[esi].ExceptionFlags
  invoke MessageBox,NULL,addr @szBuffer,NULL,MB_OK
;********************************************************************
; 將 EIP 指向安全的位置並恢復堆棧
;********************************************************************
  mov eax,_lpSEH
  push [eax + 8]
  pop [edi].regEip
  push [eax + 0ch]
  pop [edi].regEbp
  push eax
  pop [edi].regEsp
  assume esi:nothing,edi:nothing
  popad
  mov eax,ExceptionContinueExecution
  ret

_Handler endp

 第三個參數,cpu寄存器狀態值

kd> dt _CONTEXT
nt!_CONTEXT
   +0x000 ContextFlags     : Uint4B
   +0x004 Dr0              : Uint4B
   +0x008 Dr1              : Uint4B
   +0x00c Dr2              : Uint4B
   +0x010 Dr3              : Uint4B
   +0x014 Dr6              : Uint4B
   +0x018 Dr7              : Uint4B
   +0x01c FloatSave        : _FLOATING_SAVE_AREA
   +0x08c SegGs            : Uint4B
   +0x090 SegFs            : Uint4B
   +0x094 SegEs            : Uint4B
   +0x098 SegDs            : Uint4B
   +0x09c Edi              : Uint4B
   +0x0a0 Esi              : Uint4B
   +0x0a4 Ebx              : Uint4B
   +0x0a8 Edx              : Uint4B
   +0x0ac Ecx              : Uint4B
   +0x0b0 Eax              : Uint4B
   +0x0b4 Ebp              : Uint4B
   +0x0b8 Eip              : Uint4B
   +0x0bc SegCs            : Uint4B
   +0x0c0 EFlags           : Uint4B
   +0x0c4 Esp              : Uint4B
   +0x0c8 SegSs            : Uint4B
   +0x0cc ExtendedRegisters : [512] UChar

 3.3)返回值

EXCEPTION_CONTINUE_SEARCH表示本異常處理函數不處理,系統將沿着鏈表查找下一個異常處理函數。

ExceptionContinueExecution表示返回到_lpContext.Eip指定的安全位置繼續運行程序。

二)SEH鏈表圖解

 

三)SEH調試

OD調試方法:在異常處理函數下斷,當執行到異常指令的時候,根據狀態欄提示按F9,就可以調試到達異常處理函數斷點處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM