10.任务门

10.任务门

Reserved保留的填0就行
(TSS Segment Selector)存放TSS段描述符

任务门执行过程:

  1. INT N
  2. 查IDT表,找到中断门描述符
  3. 通过中断门描述符,查GDT表,找到任务段描述符
  4. 使用TSS段中的值修改寄存器
  5. IRETD返回

构造一个TSS先
xx00e9xx`xxxx0068

构造IDT(我代码的选择子是48)
0000e500`00480000

代码:

#include<windows.h>
#include<stdio.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;
	// 这个暂时忽略
	DWORD io_map;
} TSS;

char st[10] = { 0 }; // 0042b034
DWORD g_esp = 0;
DWORD g_cs = 0;

TSS tss = {		// 0x00427b40
	0x00000000,//link
	(DWORD)st, //esp0
	0x00000010,//ss0
	0x00000000,//esp1
	0x00000000,//ss1
	0x00000000,//esp2
	0x00000000,//ss2
	0x00000000,//cr3
	0x0045a0c0,//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
};

void __declspec(naked) func() {//0045a0c0
	__asm {
		int 3

		mov g_esp, esp
		xor eax,eax
		mov ax, cs
		mov g_cs, eax

		iretd
	}
}
int main(int argc, char* argv[])
{
	printf("%x\n", &tss);
	printf("cr3:\n");
	scanf("%x", &(tss.cr3));

	char buffer[6] = { 0, 0, 0, 0, 0x48, 0 };
	__asm 
	{
		int 0x20
	}

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