在《TSS切换实验》中,我们已经完成了使用 call 模拟了 TSS 的第二个功能——替换一堆寄存器。上一篇中,提到了任务门同样可以完成这个功能。
本节主要通过设计任务门描述符以及INT指令来完成TSS的第二个功能。
思路
- 编写测试入口函数,把它的函数入口地址填写到 TSS 段中
- 构造 TSS 段
- 设计 TSS 段描述符,安装到 GDT 表
- 设计任务门,安装到 IDT 表
- 编写主函数,使用 INT 指令进入任务门
实验的难点在于 TSS 段,TSS 段描述符和任务门的构造。要想完成这个实验,必须要正确理解这三者之间的关系。
我们要把握这几个关键点:
- TSS 段是们于内存中的一段数据
- TSS 段描述符是描述 TSS 段的基址和大小,并且安装在 GDT 表中
- 任务门中嵌入了TSS段选择子,任务门安装在 IDT 表中
图1 TSS 段、TSS 段描述符和任务门间的关系
实验
编写测试入口函数,填写到 TSS 段中
因为之前写过相同的代码,这里就直接搬过来用了。
这个函数在我的编译里显示的地址是 0x00401020。你需要在你的编译器里调试观察它的地址是多少。
构造 TSS 段
图2 tss 段的地址,栈地址
设计 TSS 段描述符,安装到 GDT 表
图2 中显示 tss 的地址为 0x00427a30,根据TSS段描述符构造规则,构造如下描述符。
使用下面的命令安装到 GDT 表。
因为在 8003f048 这个位置是空的,所以我选择安装到这里。你需要根据你的情况选择合适的位置安装。具体见图3和图4.
设计任务门,安装到 IDT 表
TSS段刚刚是安装在8003f048这个位置,它的选择子是 0x48,根据任务门描述符规则,设计任务门描述符如下。
使用下面的命令安装到 IDT 表。
因为在我的 IDT 表中,8003f500 这个位置是空的,所以我选择安装在这里。安装在这个位置的话,那么它在 IDT 表中的索引是是 0x20。我的 IDT 表基址是 8003f400.
图3 安装TSS段描述符和任务门描述符
图3 安装描述符后的GDT表和IDT表
编写主函数,使用 INT 指令进入任务门
- 代码
- 运行结果
运行的时候需要注意,CR3 需要在 WinDbg 中查看。在 WinDbg 中使用命令 !process 0 0
来查看程序TaskGate.exe 的 DirBase,然后在控制台里输入后回车继续执行。
完整代码
总结
本文主要使用任务门模拟了 TSS 的第二个用途。实验中涉及到了一个CR3的东西,大家暂时不用在意,照着做就行了,后面的文章讲会慢慢讲解。