14.[保护模式]TSS任务段

1.TSS的结构:

  TSS不是寄存器,它是一个内存;(包含所有寄存器的值)

 2.TSS的作用:

如果切换一个线程那么一定需要切换寄存器;

 3.CPU怎么找到TSS内存块呢? 通过TaskRegister段寄存器 

  

TaskRegister段寄存器 的值是CPU启动的时候通过GDT表中 TSS Descrptor (段描述符)加载出来的;

4.TSS Descriptor (TSS段描述符)

那么高字节BASE两个组合

+

低字节31-16位

0000e900~7b400068

0x68为结构体长度!104个字节

如果Type 为 1001  (9)的时候说明这个段描述符没有加载到TR寄存器中

如果Type 为 1011  (B)的时候说明这个段描述符加载到TR寄存器中

5.TR寄存器的读写:
  

6.修改TR寄存器:

测试实验:

7.实验思路

  • 编写测试入口函数
  • 构造TSS
  • 设计TSS段描述符并安装

一、构造TSS:

 



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};   //定义一个堆栈切换的
TSS tss = {// tss的地址根据执行代码自己组合
    0x00000000,//link
    (DWORD)st,//esp0
    0x00000010,//ss0
    0x00000000,//esp1
    0x00000000,//ss1
    0x00000000,//esp2
    0x00000000,//ss2
    0x00000000,//cr3
    0x0040fad0,//eip   必填项,不然执行完后cpu不知道回来从哪开始执行
    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  //IO权限位图
};

二、 准备TSS段描述符:

0040e900~7b400068  //加载的地址在你自己的VC6中看!

三、写入准备好的TSS段描述符到GDT空白位置

1: kd> r gdtr
gdtr=fffff8800470b4c0
1: kd> dq fffff8800470b4c0
fffff880`0470b4c0 00000000`00000000 00000000`00000000
fffff880`0470b4d0 00209b00`00000000 00cf9300`0000ffff
fffff880`0470b4e0 00cffb00`0000ffff 00cff300`0000ffff
fffff880`0470b4f0 0020fb00`00000000 00000000`00000000
fffff880`0470b500 04008b70`4ec00067 00000000`fffff880
fffff880`0470b510 ff40f3f9`e0007c00 00000000`00000000
fffff880`0470b520 00cf9a00`0000ffff 00000000`00000000
fffff880`0470b530 00000000`00000000 00000000`00000000
1: kd> eq fffff8800470b4f8 0040e9007b400068
1: kd> dq fffff8800470b4c0
fffff880`0470b4c0 00000000`00000000 00000000`00000000
fffff880`0470b4d0 00209b00`00000000 00cf9300`0000ffff
fffff880`0470b4e0 00cffb00`0000ffff 00cff300`0000ffff
fffff880`0470b4f0 0020fb00`00000000 0040e900`7b400068
fffff880`0470b500 04008b70`4ec00067 00000000`fffff880
fffff880`0470b510 ff40f3f9`e0007c00 00000000`00000000
fffff880`0470b520 00cf9a00`0000ffff 00000000`00000000
fffff880`0470b530 00000000`00000000 00000000`00000000

 
   

四.修改TR寄存器

CALL FAR或者JMP FAR 

char buff[6];
*(DWORD*)&buff[0]= 0x12345678;
*(DWORD*)&buff[4]= 0xC0;

__asm
{
  call fword ptd[buff]      
}
原文地址:https://www.cnblogs.com/hanhandaren/p/11206460.html