日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用户层和内核层异常的处理流程

發布時間:2025/3/21 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用户层和内核层异常的处理流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 內核層異常的處理流程
      • 用戶層異常和內核層異常
      • KiDispatchException函數詳解
      • RtlDispatchException函數的執行流程
    • 用戶層異常的處理流程
      • 用戶異常的處理流程

內核層異常的處理流程

之前已經了解過異常處理機制的執行流程:異常記錄 異常分發 異常的處理。這次我們學習一下內核異常的分發與處理。

用戶層異常和內核層異常

異常可以發生在用戶空間,也可以發生在內核空間。無論是CPU異常還是模擬異常,是用戶層異常還是內核層異常,都要通過KiDispatchException函數進行分發。

我們首先來了解內核異常是如何分發的。

KiDispatchException函數詳解

用IDA打開ntkrnlpa.exe,找到KiDispatchException函數

核心的功能從這里開始,這個函數做的第一件事就是將Trap_frame備份到context 為返回三環做準備

接著判斷先前模式,如果是0,則說明是內核層產生的異常,如果是1,則說明是用戶層產生的異常。

這個函數用于處理用戶層和內核層所有的異常,這個地方用于區分是三環的異常還是零環的異常。

接著判斷是否是第一次調用

接著判斷是否有內核調試器,如果有內核調試器,會先調用內核調試器。

如果這個函數的返回值為1,說明內核調試器已經處理,就將CONTEXT再轉成Trap_Frame直接返回。

如果調試器沒有處理,也就是返回0,直接跳轉

如果沒有內核調試器,或者內核調試器沒有處理,就會調用RtlDispatchException函數,這個函數專門負責調用異常處理函數來處理異常

接下來會判斷RtlDispatchException這個函數的返回值,如果返回失敗,會再次判斷是否有內核調試器。如果有內核調試器就調用這個內核調試器,如果沒有的話則會進行跳轉

系統直接藍屏

KiDispatchException函數執行流程總結

  • 將Trap_Frame備份到context為返回三環做準備
  • 判斷先前模式 0是內核調用 1是用戶層調用
  • 判斷是否是第一次調用
  • 判斷是否有內核調試器
  • 如果沒有內核調試器則不處理
  • 調用RtlDispatchException處理異常
  • 如果RtlDispatchException返回FALSE,再次判斷是否有內核調試器,沒有直接藍屏
  • RtlDispatchException函數的執行流程

    RtlDispatchException在內部會調用RtlpGetRegistrationHead,繼續跟進這個函數

    RtlpGetRegistrationHead將FS:0保存到eax之后返回。我們知道FS:0在零環的時候指向的是KPCR,而KPCR的第一個成員就是ExceptionList

    ExceptionList這個成員是一個指針,,它指向了一個結構體 _EXCEPTION_REGISTRATION_RECORD

    typedef struct _EXCEPTION_REGISTRATION_RECORD {struct _EXCEPTION_REGISTRATION_RECORD *Next;PEXCEPTION_ROUTINE Handler; } EXCEPTION_REGISTRATION_RECORD;

    這個結構體有兩個成員,第一個成員指向下一個_EXCEPTION_REGISTRATION_RECORD,如果沒有下一個_EXCEPTION_REGISTRATION_RECORD結構體,那么這個地方的值是-1。第二個成員是異常處理函數。

    RtlDispatchException的作用就是遍歷異常鏈表,調用異常處理函數,如果異常被正確處理了,該函數返回1。如果當前異常處理函數不能處理該異常,那么調用下一個異常處理函數,以此類推。如果到最后也沒有函數能處理這個異常,返回0。

    用戶層異常的處理流程

    異常如果發生在內核層,處理起來比較簡單,因為異常處理函數也在0環,不用切換堆棧,但是如果異常發生在3環,就意味著必須要切換堆棧,回到三環執行異常處理函數。

    切換堆棧的處理方式與用戶APC的執行過程幾乎是一樣的,唯一的區別就是執行用戶APC時返回3環后執行的函數是KiUserApcDispatcher,而異常處理時返回3環后執行的函數是KiUserExceptionDispatcher

    用戶異常的處理流程

    下面來分析KiDispatchException對于用戶層異常是如何處理的。

    VOID KiDispatchException(ExceptionRecord, ExceptionFrame, TrapFrame, PreviousMode, FirstChance)

    首先將Trap_Frame備份到Context結構體

    .text:004256C3 cmp byte ptr [ebp+arg_C], 0

    再接著判斷先前模式,如果是0 說明是用戶層的異常,如果是1 就是用戶層的異常

    .text:0042572E cmp [ebp+FirstChance_1], 1

    接著會判斷是否是第一次調用

    .text:00425738 cmp _KiDebugRoutine, edi ; 判斷是否存在內核調試器

    再次判斷是否存在內核調試器

    .text:00425777 call _KiDebugRoutine ; 調用內核調試器

    如果存在內核調試器則調用內核調試器,將異常信息發給內核調試器

    .text:004257AD push edi .text:004257AE push 1 .text:004257B0 push esi .text:004257B1 call _DbgkForwardException@12 ; DbgkForwardException(x,x,x)

    如果沒有內核調試器,或者內核調試器沒有處理,就會調用DbgkForwardException函數將異常發送給3環調試器。3環調試器如果不存在或者沒有處理的話,就會開始修改寄存器,準備返回3環

    .text:004258C7 mov eax, _KeUserExceptionDispatcher; .text:004258CC mov [ebx+68h], eax ;

    其中最關鍵的修改是這兩行,這里eax的值是一個全局變量KeUserExceptionDispatcher;在操作系統初始化的時候,會給這個全局變量賦一個值,這個值就是ntdll.KiUserExceptionDispatcher函數

    流程總結:

  • _KeContextFromKframes 將Trap_frame備份到context 為返回3環做準備
  • 判斷先前模式 0是內核調用 1是用戶層調用
  • 是否是第一次機會
  • 是否有內核調試器
  • 發送給3環調試器
  • 如果3環調試器沒有處理 這個異常 修正EIP為KiUserExceptionDispatcher
  • KiDispatchException函數執行結束:CPU異常與模擬異常返回地點不同
  • 無論通過那種方式,但線程再次回到3環時,將執行KiUserExceptionDispatcher函數
  • 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的用户层和内核层异常的处理流程的全部內容,希望文章能夠幫你解決所遇到的問題。

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