Windows保护模式学习笔记(四)—— 中断门&陷阱门
要点回顾
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 //暂定
由上述参数构造出的门描述符为:0000EF
00`00080000
第二步~第四步:参考中断门
之后的实验过程不再记录,可以参考中断门,基本相同
陷阱门与中断门的区别:
中断门执行时,会将IF标志位
清零,但陷阱门不会
IF=0 时:程序不再接收可屏蔽中断
可屏蔽中断:比如程序正在运行时,我们通过键盘敲击了锁屏的快捷键,若IF位为1,CPU就能够接收到我们敲击键盘的指令并锁屏
不可屏蔽中断:断电时,电源会向CPU发出一个请求,这个请求叫作不可屏蔽中断,此时不管IF位是否为0,CPU都要去处理这个请求
IF位是否会被清零是陷阱门与中断门唯一的区别