任务门描述符
我们知道,TSS描述符指向TSS表
这个任务门描述符,则是指向TSS描述符的
为什么要指来指去的,直白一点不好吗?
最后再说这个
整个描述符最关键的地方:
TSS段选择子(16-31) : 这个段选择子指向一个TSS描述符
其他的照着填就行,reserved全部填0
小实验
上一次实验的代码直接抄过来,稍作修改
#include <windows.h>
int tss[] = {
0x00000000,//link
0x00000000, //esp0 1
0x00000010,//ss0 2
0x00000000,//esp1
0x00000000,//ss1
0x00000000,//esp2
0x00000000,//ss2
0x00000000,//cr3 7
0x00000000,//eip 8 func addrs
0x00000000,//eflags
0x11111111,//eax
0x22222222,//ecx
0x33333333,//edx
0x44444444,//ebx
0x00000000, //esp 14
0x00000000,//ebp
0x00000000,//esi
0x00000000,//edi
0x00000023,//es
0x00000008,//cs 19
0x00000010,//ss
0x00000023,//ds
0x00000030,//fs
0x00000000,//gs
0x00000000,//ldt
0x20ac0000 // IO map
};
BYTE stack[0x100];
void __declspec(naked) func(){
_asm{
pushf
int 3 //int3一定记得保存eflags
popf
iretd
}
}
int main(){
memset(stack, 0, 0x100); //init stack
printf("TSS addrs: %x\n", tss);
printf("input CR3:\n");
scanf("%x", &tss[7]); //cr3
tss[8] = (DWORD)&func; //eip
tss[14] = stack + 0x100; //esp
_asm{
int 0x24 //调用任务门
}
}
任务门是写在IDT表里的,所以可以用int xx
来调用
书上写了还可以放在LDT表里,但是windows都没有用这个表,所以我们也不用
先执行程序
获得了TSS的地址,我们就可以构造任务门了
在此之前,先写TSS描述符,因为任务门描述符需要TSS描述符的选择子
TSS描述符相信大家已经很熟悉了,不再赘述
eq 8003f048 0000e941`20300068
eq 8003f520 0000e500`00480000
根据上面的位置写入任务门描述符
用 !process 0 0
获取CR3,并输入
程序成功断在我们写的函数里了,g
继续执行,程序结束,没有蓝屏,成功返回了
拓展
为什么要有任务门?
原文中写:为了发生中断或异常时,能够开辟一个独立的任务进行处理
Need for an interrupt or exception to be handled by an independent task
书上写了,TSS描述符里的DPL不在生效,好奇的我自然忍不住要试试
eq 8003f048 0000a941`20300068 //e --> a
重复上面的操作,依旧不会蓝屏
疑问:
看到有一位同学写了
//任务段不变,TSS不变
eq 8003f520 0000e500`004b0000 //任务门 0048-->004b
然后就是蓝屏,别问为什么,因为我试过了
因为TSS表里的段寄存器写的是0环的,而我们跳转过去用的是3环的权限,想要改写这个寄存器成为0环寄存器,权限不够
//调用门执行之前写上,即可正确执行
tss[18] = 0x23;//es
tss[19] = 0x1b;//cs
tss[20] = 0x23;//ss
tss[21] = 0x23;//ds
tss[22] = 0x3b;//fs
tss[23] = 0x00;//gs
所以这里写了3环的权限,段寄存器就得是3环的
如果这里写的是1环的权限,段寄存器权限就得是1,2,3环的