0%

IDT

IDT表

这个就是中断服务表,例如我们使用int 3软终端,我们就会跳到3这个表指向的内存地址去执行代码:
IDT3
这个中段描述表如果要返回的话呢,我们需要用iretd函数进行返回,这样子就不会处理中断,但是程序却会崩溃。这样子可以避免断点。
一般对这个地址进行inline hook。
可以起到烦cc断点的效果。

可以使用汇编指令:_asm sidt idtr;将idtr这个变量进行赋值,这个变量是一个结构体对象。

1
2
3
4
5
6
#pragma pack(push, 1)
//从sidt指令获得一个如下的结构,从这里可以得到IDT的开始地址
typedef struct P2C_IDTR_ {
P2C_U16 limit; // 范围
P2C_U32 base; //基地址
}P2C_IDTR, *PP2C_IDTR;

这个base其实是一个结构体的指针:

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma pack(push, 1)
//IDT的内存空间是一个数组。每个元素都有如下的结构
typedef struct P2C_IDT_ENTRY_ {
P2C_U16 offset_low;
P2C_U16 selector;
P2C_U8 reserved;
P2C_U8 type:4;
P2C_U8 always0:1;
P2C_U8 dpl:2;
P2C_U8 present:1;
P2C_U16 offset_high;
}P2C_IDTENTRY, *PP2C_IDTENTRY;
#pragma pack(pop)

#pragma pack(push, 1)
这个的意思就是说压入对齐方式一个字节
#pragma pack(pop)
这个意思弹出之前压入的对齐方式

结构体后面的冒号代表占几位,这四个加起来才8位一个字节。

中断和陷阱的区别就是一个是主动的,类似于int,另一个是异常的。

因为我们每个CPU有一个IDT表,所以我们需要修改每一个CPU的IDT表,比较麻烦,我们最好是使用inline hook的方法比较好。

在内联hook的时候最好是用pushad,pushf保存寄存器,最后popf,popad弹出来。