日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

SEH(结构化异常处理)

發布時間:2025/3/21 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SEH(结构化异常处理) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 內容回顧:
    • 總結:
    • 程序代碼
    • 實現截圖
    • 具體流程

內容回顧:

當用戶異常產生后,內核函數KiDispatchException并不是像處理內核異常那樣在0環直接處理,而是修正3環EIP為KiUSerExceptionDispatcher函數后就結束了。
這樣,當線程再次回到3環時,將會從KiUserExceptionDispatcher函數開始執行。

KiUserExceptionDispatcher會調用RtlDispatchException函數來查找并調用異常處理函數,查找的順序:

  • 先查全局鏈表:VEH
  • 再查句柄鏈表:SEH

  • 它是與線程有關的,存儲在當前線程的堆棧中。

    3環的FS寄存器指向TEB


    下圖中兩個call,第一個是VEH,第二個是SEH

    然后進入后查看第一批代碼:

    首先取出fs+8,和fs+4位置的參數

    當前堆棧的界面和起始位置,利用這兩個值,進行如下代碼檢測:

    看看堆棧是否屬于當前線程(也就是說異常處理函數必須位于當前線程堆棧)

    繼續看,fs指向Teb,fs:0指向SEH:

    真正開始調用異常處理的函數如下(也就是說所寫異常處理函數必須符合調用約定,不能隨便寫):

    由內核發起調用的函數都一樣,都是必須符合調用約定,寫成規范形式。

    總結:

  • fs:[0]指向的是SEH鏈表的第一個成員
  • SEH的異常處理函數必須在當前線程的堆棧中
  • 只有在VEH中的處理函數不存在或者不處理才會到SEH鏈表中查找
  • 程序代碼

    #include<Windows.h> #include <iostream> //0環異常處理時講過這個結構體 /* typedef struct _EXCEPTION_REGISTRATION_RECORD {struct _EXCEPTION_REGISTRATION_RECORD* next;PEXCEPTION_ROUTINE Handler; }; */ struct MyException {struct MyException* prev;DWORD handle; };EXCEPTION_DISPOSITION _cdecl MyException_handler(struct _EXCEPTION_RECORD* ExceptionRecord,//ExceptionRecord存儲異常信息,什么類型,異常產生位置void* EstablishFrame,//MyException結構體地址(指向堆棧中的結構體)struct _CONTEXT* ContextRecord,//Context結構體,存儲異常發生時的各種寄存器值,堆棧位置等void* DispatcherContext ) {::MessageBoxA(NULL, "SEH異常處理函數執行了", "SEH異常", MB_OK);if (ExceptionRecord->ExceptionCode == 0xC0000094) {ContextRecord->Eip = ContextRecord->Eip + 2;// ContextRecord->Ecx=1;return ExceptionContinueExecution;}return ExceptionContinueSearch; }int main() {DWORD temp;//插入異常處理函數,必須在當前線程的堆棧中;MyException myException;//(只能在堆棧中創建,不能定義為全局變量)__asm {mov eax,fs:[0]mov temp,eaxlea ecx,myExceptionmov fs:[0],ecx}myException.prev = (MyException*)temp;myException.handle = (DWORD)&MyException_handler;//創造異常__asm{xor edx,edxxor ecx,ecxmov eax,0x10idiv ecx //EDX:EAX除以ECX}//摘掉異常處理函數__asm{mov eax,tempmov fs:[0],eax}printf("函數正常執行了"); }

    實現截圖

    具體流程

    idiv ecx //EDX:EAX除以ECX

    產生異常:

    CPU指令檢測到異常(例:除0)------>查IDT表,執行中斷處理函數--------->CommonDispatchException

    然后異常分發:KiDispatchException

  • 把Trap_frame(當前線程3環進入0環時,那些寄存區環境,也就是eip運行地方那些值)備份到context里(為返回3環做準備)(也就是把3環代碼eip保存,不能破壞原來的執行流程
  • 第二步:判斷先前模式,0是內核調用,1是用戶調用,用戶層異常呢,緊接著就是跳轉
  • 把KeUserExceptionDispatcher里面的值覆蓋到Eip
  • 回到三環的KiUserExceptionDispatcher會調用RtlDispatchException函數來查找并調用異常處理函數,查找的順序:先查全局鏈表:VEH; 再查句柄鏈表:SEH
  • 找到解決之后呢,調用ZwContine再次進入0環,
    主要作用就是恢復_TRAP_FRAME(也就是第一步中的EIP恢復原來執行流程)然后通過_KiServiceExit返回到3環。
  • 在跳轉CommonDispatchException之前,還傳了兩個參數

    if (ExceptionRecord->ExceptionCode == 0xC0000094) {ContextRecord->Eip = ContextRecord->Eip + 2;// ContextRecord->Ecx=1;return ExceptionContinueExecution;}

    記住,這里的返回并非直接回到下面這行代碼:

    printf("函數正常執行了");

    總結

    以上是生活随笔為你收集整理的SEH(结构化异常处理)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。