1. 程式人生 > >第八章——Windows下異常處理-SEH的概念及基本知識

第八章——Windows下異常處理-SEH的概念及基本知識

1.SEH相關結構     ①TIB         TIB是儲存執行緒基本資訊結構體,它位於TEB頭部,而TEB在FS:[0]處(0X7FFDE000)之前的筆記中提及過。具體的TIB結構如下:         typedef struct _NT_TIB {            //sizeof 1ch                  00h     struct _EXCEPTION_REGISTRATION *ExceptionList; //SEH鏈入口                  04h     PVOID StackBase; //執行緒所使用的棧的棧底                  08h     PVOID StackLimit; //執行緒所使用的棧的棧頂                  0ch     PVOID SubSystemTib;                    union {                     PVOID FiberData;                     10h DWORD Version;                     };                 14h     PVOID ArbitraryUserPointer;                 18h     struct _NT_TIB *Self; //本NT_TIB結構自身的線性地址         }NT_TIB; 其中的第一個欄位就是指向異常處理鏈的入口指標,它位於TIB位移0處,而TEB的偏移0處也是它。       ②_EXCEPTION_REGISTRATION_RECORD         這個結構體主要描述了TEB為0處的異常處理鏈         typedef struct _EXCEPTION_REGISTRATION_RECORD {         struct _EXCEPTION_REGISTRATION_RECORD *Next;      //指向下一個 EXCEPTION_REGISTRATION_RECORD,由此構成一個異常註冊資訊連結串列。         PEXCEPTION_ROUTINE Handler;  //指向異常處理函式       //連結串列中的最後一個結點會將 Next 置為 EXCEPTION_CHAIN_END,表示連結串列到此結束。 } EXCEPTION_REGISTRATION_RECORD;         其中next指向下一個ERR指標,形成一鏈狀,Handler為異常處理函式,當有異常發生的時候,系統會在fs:[0]處獲取異常處理鏈的表頭,然後依次查詢各個異常處理回撥函式,由於TEB是執行緒的私有資料結構,SEH的處理機制也是使用與當前執行緒       ③_EXCEPTION_POINTERS結構         typedef struct _EXCEPTION_POINTERS         {             PEXCEPTION_RECORD ExceptionRecord; //指向一個EXCEPTION_RECORD結構             PCONTEXT ContextRecord;                     //指向向一個CONTEXT結構         }          當有異常發生時候,系統會將異常資訊交給使用者態的異常處理過程。但是在這個過程中,同一個執行緒在使用者態和核心態使用的是兩個不同的棧,為了讓使用者態能夠處理和訪問異常相關資料,作業系統就將   PEXCEPTION_RECORD和PCONTEXT封裝在一個結構體中,這樣使用者態處理程式就能夠取得異常的資訊和發生異常時執行緒的狀態來具體處理異常。     2.SEH處理程式的安裝與解除安裝     由於FS:[0]指向異常處理的表頭,所以這裡只需要安裝一個新的SEH異常處理程式,填寫一個新的_EXCEPTION_REGISTRATION_RECORD結構,將其插入該連結串列的頭部即可     push  offset SEHandler     push  fs:[0]     push  fs:[0],esp 上述三行意思為,現將新的異常回調函式以及fs:[0]構造出一個_EXCEPTION_REGISTRATION_RECORD結構,此時它的位置就在棧頂,就是esp的位置,在將esp儲存到fs:[0]中,這樣就構造好一個新的SEH表頭   解除安裝表頭:     mov esp , fs:[0]     pop  fs:[0]     先將鏈中第二個放入棧頂,接著將表頭刪除