首先,CUP在执行代码的时候.是按照任务执行的
每个任务有一个任务状态段TSS
用于保护任务的有关信息.在任务内变换特权级和任务切换的时候.要用到这些信息.
这个就是TSS任务状态段.
而在windows 80386中.有两种系统段.一种就是TSS,另一种就是LDT
系统段描述符格式:
这个系统段和存储段相同.
当DT = 1 表示这是个存储段
当DT = 0 则表示这个是系统段.
而如果是系统段.那么Type属性就很重要了.
而TR寄存器,就是保存了当前任务段的选择子.
而且是存放在GDT表中的.
当属性为C的是否.则是门描述符.
格式:
门描述符的作用就是描述某个子程序的入口. 用门内的选择子.还有偏移.利用Call或者Jmp可以调用.
也就是说当我们三环调用API的是否,内部会使用门来进行特权级转换.而且门描述符记录了参数的个数. 还会保存 ring0的栈,
从栈里面获取参数信息.
当返回的是否,调用 retf汇编指令,从0环切换到3环.
查看TSS属性段.
当输入命令 dg 0 100 则会显示100项GDT表的内容.
其中,操作系统在做API的时候,并没有使用门描述符来做.
我们自己可以构建一个门描述符 .这样当我们的三环调用我们的API的时候.
就可以调用到这个我们自己构造的门描述符了.
首先,什么是中断?
在我们的8086的年代里面. 调用API的是否是 int 21来进行调用的.
这就是一个中断.中断是什么? 其实中断就是一个电信号.
比如用户操作键盘,键当被按下就会产生一个中断. 但是CPU能接受到这个中断.但是不能去处理. 这个要操作系统去处理.
所以当有中断产生, CPU就会查表 . 表内容是固定的. 操作系统会填写函数指针. 当我们按键,产生中断了. 那么就会查表进行操作.
中断其实也是CPU和操作系统通信的一种机制.
比如我们的 int 3指令. 就产生一个异常.而在CPU接受到了,就会去查表.这样就可以处理int 3的指令了.
中断我们说过了,是电信号. 而表则是CPU和操作系统的通信机制.
那么说下异常把. 其实异常也是中断. 只不过,我们的软件调试的时候.当我们的程序用内联汇编写的int 3的时候,就会产生断点功能.
其实软件产生的中断,就叫做异常. 而且int 3指令在ring3调用的时候.会产生特权级改变. CPU也会固定的去查表.
在80386里面.有两个银脚,是专门接受中断信号的.
而且80386最多接受256种中断或者异常.
引脚:
INTR 专门接受中断或者异常, 当我们调用CLI汇编指令的时候.其实屏蔽的就是INTR.不让其接受中断信号.
NMI 这个也是接受的.但是不能屏蔽的. 比如我们的系统在运行中,你把内存条拔了.那么就会产生电信号.有NMI引脚发送.
我们上面说过,中断是CPU和操作系统通信的一种机制.
CPU接受中断. 那么就要查表.而操作系统要往这个表中填写函数指针.让CPU去执行.
比如我们的8086CPU,调用API的是否,其实就是 int 21h,其实21h就是在查表.查表中的第21项.可以把表看作成数组.
上面说的中断表.其实就是IDT表. IDT表因为在80386下,最多处理256个,所以这个IDT表只有256项.
而IDT表和GDT一样.只不过IDT表中存储的是门描述符.
比如:
我们的int 3断点产生了. 那么就回去IDT表中寻找第三项.进行操作.
WinDbg调试查看.
IDT表的首地址会存放在IDTR寄存器中. 然后每一项都是按照门描述符来管理. 所以当我们拆出来的地址拼接成一个完整的地址,就可以查看完整的处理int 3断点的代码了.
当我们HOOK了这个第三项.那么你的程序将永运不会产生int 3断点.
其中,IDT表中每一项都是8个字节,因为不光要描述函数地址,还要藐视额外的属性信息.