9.任务段(TSS)

在调用门、中断门与陷阱门中,一旦出现权限切换,那么就会有堆栈的 ,切换。而且,由于CS的CPL发生改变,也导致了SS也必须要切换。

切换时,会有新的ESP和SS(CS是由中断门或者调用门指定)这2个值从哪里来的呢?

答案: TSS (Task-state segment ),任务状态段

TSS就是一块内存,大小104个节。
在这里插入图片描述

不要把TSS与任务切换联系到一起
TSS的意义就在于可以同时换掉一堆寄存器

在这里插入图片描述
TSS是段描述符,从GDT表中的加载出来的
系统启动-》从GDT表中的加载出的TSS-》放到TR寄存器里,系统要用直接找TR寄存器

在这里插入图片描述
TSS是系统段,s位为0,TYPE域为:1001或者1011
这两特征说明他是一个TSS段描述符,type为1001说明这个tss没有加载到TR寄存器中,1011说明已经加载到TR寄存器中
tss的颗粒位为0(G位)

TR寄存器读写:
1)将TSS段描述符加载到TR寄存器
指令: LTR
说明:
用LTR指令去装载的话仅仅是改变TR寄存器的值(96位)并没有真正改变TSS
LTR指令只能在系统层使用
加载后TSS段描述符会状态位会发生改变(1001变1011)

2)读TR寄存器
指令: STR
说明:如果用STR去读的话,只读了TR的16位也就是选择子(可见部分)

修改TR寄存器
1)在Ringo我们可以通过LTR临令去修改TR寄存器
2)在Ring3我们可以通过CALL FAR或者JMP FAR指令来修改

用JMP去访问一个代码段的时候,改变的是CS和EIP:
JMP 0x48:0x123456如果0x48是代码段
执行后: CS->0x48 ElP.-x123456

用JMP去访问一个任务段的时候:
如果0x48是TSS段描述符,先修改TR寄存器,在用TR.Base指向的TSS中的值修改当前的器存器

TSS存在的意义
提权时栈切换用到了 TSS
切换一堆寄存器

测试

修改gdt。
xx00e9xx`xxxx0068
xx为base,填TSS的

#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
		mov eax, 0
		mov ax, cs
		mov g_cs, eax

		iret//中断返回指令
	}
}
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 
	{
		call fword ptr[buffer]
	}

	
	printf("g_cs = %08x\ng_esp = %08x\n", g_cs, g_esp);
	getchar();
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值