Windows保護模式學習筆記(四)—— 中斷門&陷阱門
-
- 要點回顧
- 中斷描述符表(IDT)
-
- 一、中斷門
-
- 實驗:構造一個中斷門
-
- 第一步:初步構造參數
- 第二步:确定 Offset in Segment
- 第三步:将門描述符寫入IDT表
- 第四步:繼續執行第二步的代碼
- 二、陷阱門
-
- 實驗:構造一個陷阱門
-
- 第一步:初步構造參數
- 第二步~第四步:參考中斷門
- 陷阱門與中斷門的差別:
要點回顧
Windows實際上并沒有使用調用門,但是使用了中斷門
學習調用門是為了更好地了解中斷門
注意:老式CPU會使用中斷門,新式CPU使用的是快速調用
中斷描述符表(IDT)
描述:
IDT即中斷描述符表,同GDT一樣,IDT也是由一系列描述符組成的,每個描述符占8個位元組
但要注意的是,IDT表中的第一個元素不是NULL
使用WinDbg檢視IDT表的基址和大小:
IDT表可以包含三種門描述符:
- 任務門描述符
- 中斷門描述符
- 陷阱門描述符
一、中斷門
結構圖:
中斷門執行前後堆棧變化:
實驗:構造一個中斷門
第一步:初步構造參數
Offset in Segment 31:16 = 0x0000 //暫定
P = 1
DPL = 二進制:11
Segment Selector = 0x0008
Offset in Segment 15:00 = 0x0000 //暫定
由上述參數構造出的門描述符為:0000EE00`00080000
第二步:确定 Offset in Segment
在VC6中執行以下代碼并中斷
#include <windows.h>
DWORD dwH2GValue;
void __declspec(naked) GetH2GValue()
{
__asm
{
pushad
pushfd
mov eax,[0x8003f00c]
mov ebx,[eax] // 擷取高2G位址的值
mov dwH2GValue,ebx
popfd
popad
iretd
}
}
void PrintH2GValue()
{
printf("%x \n", dwH2GValue);
}
int main(int argc, char* argv[])
{
__asm
{
int 0x20 // 中斷門位置在IDT[20]
}
PrintH2GValue();
getchar();
return 0;
}
右鍵進入反彙編視窗,檢視GetH2GValue函數起始位址,我這裡是00401030
至此,門描述符的最終确定為:0040EE00`00081030
第三步:将門描述符寫入IDT表
檢視IDT表
紅框标注處描述符無效,将構造的描述符寫入
第四步:繼續執行第二步的代碼
執行結果:
成功讀取了高2G記憶體的值,構造中斷門實驗成功!
二、陷阱門
結構圖:
實驗:構造一個陷阱門
第一步:初步構造參數
Offset in Segment 31:16 = 0x0000 //暫定
P = 1
DPL = 二進制:11
Segment Selector = 0x0008
Offset in Segment 15:00 = 0x0000 //暫定
由上述參數構造出的門描述符為:0000E
F
00`00080000
第二步~第四步:參考中斷門
之後的實驗過程不再記錄,可以參考中斷門,基本相同
陷阱門與中斷門的差別:
中斷門執行時,會将
IF标志位
清零,但陷阱門不會
IF=0 時:程式不再接收可屏蔽中斷
可屏蔽中斷:比如程式正在運作時,我們通過鍵盤敲擊了鎖屏的快捷鍵,若IF位為1,CPU就能夠接收到我們敲擊鍵盤的指令并鎖屏
不可屏蔽中斷:斷電時,電源會向CPU發出一個請求,這個請求叫作不可屏蔽中斷,此時不管IF位是否為0,CPU都要去處理這個請求
IF位是否會被清零是陷阱門與中斷門唯一的差別