10.任务门
Reserved保留的填0就行
(TSS Segment Selector)存放TSS段描述符
任务门执行过程:
- INT N
- 查IDT表,找到中断门描述符
- 通过中断门描述符,查GDT表,找到任务段描述符
- 使用TSS段中的值修改寄存器
- 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;
}