1.IDT中断描述符表
IDT中包含了三种门描述符:
任务门描述符
中断门描述符
陷阱门描述符
2.任务门描述符
3.任务门执行过程
INT N
通过N查IDT表,找到任务门描述符
通过任务门描述符查GDT表,找到任务段描述符
使用TSS段中的值修改寄存器
IRETD返回
接下来我们先做一个用任务段一次切换一堆寄存器的值的实验,实验代码如下:
#include <stdio.h>
#include <windows.h>
_declspec(naked)Fun()
{
_asm{
int 3
}
}
int main()
{
char stack[0x10];//用分配的内存当做栈用
int iCr3;
printf("please input CR3:\n");
scanf("%x",&iCr3);
//准备104个字节并赋初值
DWORD iTss[0x68] = {
0x00000000,//link 存放切换前的段选择子
0x00000000,//esp
0x00000000,//ss
0x00000000,//esp1
0x00000000,//ss1
0x00000000,//esp2
0x00000000,//ss2
(DWORD)iCr3,//Cr3
0x00401020,//eip切换Fun()
0x00000000,//eFlags
0x00000000,//eax
0x00000000,//ecx
0x00000000,//edx
0x00000000,//ebx
(DWORD)stack,//esp
0x00000000,//ebp
0x00000000,//esi
0x00000000,//edi
0x00000023,//es
0x00000008,//cs
0x00000010,//ss
0x00000023,//ds
0x00000030,//fs
0x00000000,//gs
0x00000000,//idt
0x20ac0000//I/O权限位图
};
char buffer[6];
*(DWORD*)&buffer[0] = 0x12345678;
*(WORD*)&buffer[4] = 0xC0;
_asm{
call fword ptr[buffer]
}
return 0;
}
实验设计思路:
1.分配一块104字节的内存
2.TSS赋值
3.准备TSS段描述符(结构可以参考上一篇中的结构图,注意此时的G位为0)
4.修改TR寄存器(可以用LTR、JMP FAR、CALL FAR)
5.构造GDT段描述符(eq 8003f0c0 0000e912`FDCC0068(根据实际情况构造))
6.执行然后提示输入CR3时,我们切换到真机在Windbg中点击debug->break,然后输入指令!process 0 0,找到我们的TSS.exe的DirBase值如下图:
7.然后输入g继续运行虚拟机,并在虚拟机中输入DirBase值,如下:
8.回车继续运行后断到windbg中,这时我们输入r命令来查看寄存器可以看到都被改成了我们定义的Tss中的值,如下图:
接下来我们将上面的代码稍微做一下修改,如下:
#include <stdio.h>
#include <windows.h>
DWORD dwOK;
DWORD dwESP;
WORD dwCS;
_declspec(naked)Fun()
{
dwOK = 1;
_asm{
mov eax,esp
mov dwESP,eax
mov ax,cs
mov dwCS,ax
iretd
}
}
int main()
{
char stack[0x10];//用分配的内存当做栈用
int iCr3;
printf("please input CR3:\n");
scanf("%x",&iCr3);
//准备104个字节并赋初值
DWORD iTss[0x68] = {
0x00000000,//link 存放切换前的段选择子
0x00000000,//esp
0x00000000,//ss
0x00000000,//esp1
0x00000000,//ss1
0x00000000,//esp2
0x00000000,//ss2
(DWORD)iCr3,//Cr3
0x00401020,//eip切换Fun()
0x00000000,//eFlags
0x00000000,//eax
0x00000000,//ecx
0x00000000,//edx
0x00000000,//ebx
(DWORD)stack,//esp
0x00000000,//ebp
0x00000000,//esi
0x00000000,//edi
0x00000023,//es
0x00000008,//cs
0x00000010,//ss
0x00000023,//ds
0x00000030,//fs
0x00000000,//gs
0x00000000,//idt
0x20ac0000//I/O权限位图
};
char buffer[6];
*(DWORD*)&buffer[0] = 0x12345678;
*(WORD*)&buffer[4] = 0xC0;
_asm{
int 0x20//这里稍作修改
}
printf("OK: %x, ESP: %x, CS: %x", dwOK, dwESP, dwCS);
return 0;
}
我们这时构造任务门描述符写入IDT中,并构造TSS描述符写入GDT中,如下图:
重复上面的步骤输入CR3
可以看到执行结果如下