[windows内核]任务门

任务门存在于IDT表中,下面是任务门的段描述符
在这里插入图片描述
下图是任务门触发的时候的执行过程

在这里插入图片描述
下面总体概述一下如何使用任务门来进行任务切换:

1.当中断发生时,处理器用中断号乘以8作为索引访问中断描述符表。当它发现这是一个任务门描述符时,就知道应当发起任务切换。
2.取出任务门描述符。
3.从任务门描述符中取出新任务的TSS选择子;
4.再用TSS选择子访问GDT,取出新任务的TSS描述符
5.在执行新任务前,处理器会把当前任务状态保存起来。也就是将当前任务的状态保存到TR寄存器指向的TSS状态段。
6.然后处理器访问新任务的状态段TSS,并从中恢复各个寄存器的内容,包括通用寄存器、标志寄存器EFLAGS、段寄存器、指令指针寄存器EIP、栈指针寄存器ESP,以及局部描述符表寄存器LDTR等。
7.最终任务寄存器TR指向新任务的TSS,而处理器开始新任务的执行。
8.一旦新任务开始执行,处理器固件会自动将其TSS描述符的B位置1,表示该任务状态为忙。

这里可能有个小问题,既然我们可以直接访问任务段了,为什么要有任务门呢?

一个“TSS描述符”指代了一个TSS结构,按理来说,这已经完全足够使用了,但是用于Intel允许在中断的时候也可以进行任务切换,这样,我们就可以把中断处理程序作为一个专门的任务,然而,中断描述符表中存放的只能是门描述符,而上面的“TSS描述符”并不是一种门描述符,因此,它不能被放在中断描述符表中,于是Intel又定义了一种“任务门”,它其实指向的是一个“TSS描述符”,但由于它是一种门描述符,因此,它可以被放在中断描述符表中,这样当发生中断的时候,CPU通过中断号查询中断描述符表,得到相应的门描述符,如果发现它是一个“任务门”,则通过它找到相应的“TSS描述符”,再通过相应的“TSS描述符”找到相应的“TSS结构”

NT flag in the EFLAGS register
NT(Nested Task):控制中断返回指令IRET,它宽度为1位。NT=0,用堆栈中保存的值恢复EFLAGS,CS和EIP从而实现中断返回;NT=1,则通过任务切换实现中断返回,这里也是我们之前说过代码里加入int3中断返回会卡死的问题。
在这里插入图片描述
任务门的作用
当CPU出现双重错误,其就会通过任务门,调到08到中断去。

下面来做一个任务门小实验

先构造一个任务门 假设TSS段在GTD 0x48位置

						  P   DPL             
000000000000 00001   11   00101 0000 0000
TSS Segment Selector        
‭0000 0000 0100 1000‬     ‭  0000 0000 0000 0000

在这里插入图片描述
编译如下程序

#include <iostream>
#include <windows.h>




typedef struct TSS {
	DWORD link; // 保存前一个 TSS 段选择子,使用 call 指令切换寄存器的时候由CPU填写。
	// 这 6 个值是固定不变的,用于提权,CPU 切换栈的时候用
	DWORD esp0; // 保存 0 环栈指针
	DWORD ss0;  // 保存 0 环栈段选择子
	DWORD esp1; // 保存 1 环栈指针
	DWORD ss1;  // 保存 1 环栈段选择子
	DWORD esp2; // 保存 2 环栈指针
	DWORD ss2;  // 保存 2 环栈段选择子
	// 下面这些都是用来做切换寄存器值用的,切换寄存器的时候由CPU自动填写。
	DWORD cr3;
	DWORD eip;
	DWORD eflags;
	DWORD eax;
	DWORD ecx;
	DWORD edx;
	DWORD ebx;
	DWORD esp;
	DWORD ebp;
	DWORD esi;
	DWORD edi;
	DWORD es;
	DWORD cs;
	DWORD ss;
	DWORD ds;
	DWORD fs;
	DWORD gs;
	DWORD ldt;
	// I/O 位图基地址域
	DWORD io_map;
} TSS;

char st[10] = { 0 }; 

DWORD g_esp;
DWORD g_cs;

TSS tss = {
		0x00000000,//link
		(DWORD)st,//esp0
		0x00000010,//ss0
		0x00000000,//esp1
		0x00000000,//ss1
		0x00000000,//esp2
		0x00000000,//ss2
		0x00000000,//cr3
		0x0040fad0,//eip
		0x00000000,//eflags
		0x00000000,//eax
		0x00000000,//ecx
		0x00000000,//edx
		0x00000000,//ebx
		(DWORD)st,//esp
		0x00000000,//ebp
		0x00000000,//esi
		0x00000000,//edi
		0x00000023,//es  
		0x00000008,//cs  
		0x00000010,//ss
		0x00000023,//ds
		0x00000030,//fs
		0x00000000,//gs
		0x00000000,//ldt
		0x20ac0000
};

  __declspec(naked) void func() {
	__asm {
		mov g_esp, esp;
		mov eax, 0;
		mov ax, cs;
		mov g_cs, eax;

		iretd;
	}
}


int main(int argc, char* argv[])
{
	tss.eip = (DWORD)func;
	printf("TSS:%x\n", &tss);
	printf("func:%x\n", tss.eip);
	printf("please input cr3:\n");
	scanf("%x", &(tss.cr3));
	

	__asm 
	{
		int 0x20;
	}
	
	printf("g_cs = %08x\ng_esp = %08x\n", g_cs, g_esp);
	getchar();
	return 0;
}

根据显示的TSS位置构造任务段
在这里插入图片描述

Base 31:24  G     AVL  Limit19:16  P   DPL     Type   Base 23:16        
000000000 00  0    00001110  1001   0100 0001
Base Address 15:00      Segment Limit 15:001110 0000 0000 0000‬     ‭ 0000 0000 01101000

写入GDT表中

在这里插入图片描述
输入!process 0 0找到相应进程cr3,记下,也就是DirBase
在这里插入图片描述
成功调用
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值