Int 2e 與 Sysenter區別


參考:張銀奎《軟件調試》第八章

Int 2e:

 

Windows將2e號向量專門用作系統調用,在啟動早起初始化中斷描述表時便注冊好了適合的服務例程。因此當NtDll中的NtReadFile發出int 2e指令后,cpu便會通過idt表找到KisystemService函數。因為KiSystemService函數是位於內核空間的,所以cpu在把執行權交給KiSystemService函數前,會做好從用戶態換到內核態的各種工作,包括:

  1:權限檢查 即檢查源位置和目標位置所在的代碼段權限,核實是否可以轉移。

  2:准備內核態使用的棧,為了保證內核安全,所有線程在內核態執行時都必須使用位於內核的內核棧(kernel stack),內核棧的大小一般為8KB或者12KB.

KiSystemService會根據服務ID從系統服務分發表(System Service Dispatch Table)中查找到需要的服務函數地址和參數描述,然后將參數從用戶態復制到該線程的內核棧中,最后KiSystemService調用內核中真正的NtReadFile()函數,執行讀文件操作,操作結束后會返回到KiSystemService(),KISystemService()會將操作結果復制回線程用戶態棧,最后通過IRET指令將執行權交回給NtDll.dll中的NtReadFile()函數,繼續執行INT 2E后面的那條指令。

快速系統調用(Sysenter)

准備工作:

  1,在GDT中建立4個段描述符,分別用來描述供SYSENTER指令進入內核模式時使用的代碼段(CS)和棧段(SS),以及分別用來描述供SYSENTER指令進入內核模式時使用的代碼段(CS)和棧(SS).這四個描述符在GDT表中的排列應該嚴格按照以上順序,這樣只要指定一個段描述符的位置便能計算出其他的。

  2,設置專門用於系統調用的MSR寄存器。

  3,將一小段名為SystemCallStub的代碼復制到SharedUserData內存區,該內存區會被映射到每個Win32進程的進程空間中。這樣當應用程序每次進入系統調用時,NtDll中的殘根(stub)函數便調用這段SystemCallStub代碼。SystemCallStub中的內容會因系統硬件的不同而不同。

 

逆向調用(Ring0 -> Ring3)

     首先內核代碼使用內核函數KiCallUserMode發起調用。接下來的執行過程與從系統調用返回(KiServiceExit)時類似,不過進入用戶態時執行的是NtDll中的KiUserCallbackDispatcher。而后KiUserCallbackDispatcher會調用內核希望調用的內核態函數。當用戶態的工作完成后,執行返回動作的函數會執行INT 2B指令,也就是觸發一個0x2B異常。這個異常的處理函數是內核態的KiCallbackReturn函數。於是,通過INT 2B異常,CPU便又跳回到內核態繼續執行了。

lkd>!idt 2b

Dumping IDT:

2b:8053d070 nt!KiCallbackReturn

 


免責聲明!

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



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