16-任务门实验

《TSS切换实验》中,我们已经完成了使用 call 模拟了 TSS 的第二个功能——替换一堆寄存器。上一篇中,提到了任务门同样可以完成这个功能。

本节主要通过设计任务门描述符以及INT指令来完成TSS的第二个功能。

思路

  • 编写测试入口函数,把它的函数入口地址填写到 TSS 段中
  • 构造 TSS 段
  • 设计 TSS 段描述符,安装到 GDT 表
  • 设计任务门,安装到 IDT 表
  • 编写主函数,使用 INT 指令进入任务门

实验的难点在于 TSS 段,TSS 段描述符和任务门的构造。要想完成这个实验,必须要正确理解这三者之间的关系。

我们要把握这几个关键点:

  • TSS 段是们于内存中的一段数据
  • TSS 段描述符是描述 TSS 段的基址和大小,并且安装在 GDT 表中
  • 任务门中嵌入了TSS段选择子,任务门安装在 IDT 表中


这里写图片描述
图1 TSS 段、TSS 段描述符和任务门间的关系

实验

编写测试入口函数,填写到 TSS 段中

因为之前写过相同的代码,这里就直接搬过来用了。

DWORD g_esp;
DWORD g_cs;

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

        iretd // 在 32 位系统下,这里写 iret 和 iretd 都是一样的
    }
}

这个函数在我的编译里显示的地址是 0x00401020。你需要在你的编译器里调试观察它的地址是多少。

构造 TSS 段


这里写图片描述
图2 tss 段的地址,栈地址

char st[10] = {0}; // 0042ace4

TSS tss = {// 0x00427a30
        0x00000000,//link
        (DWORD)st,//esp0,这里是自己定义的栈地址
        0x00000010,//ss0
        0x00000000,//esp1
        0x00000000,//ss1
        0x00000000,//esp2
        0x00000000,//ss2
        0x00000000,//cr3
        0x00401020,//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 // 这个位置暂时忽略,填这个值就行了
};

设计 TSS 段描述符,安装到 GDT 表

图2 中显示 tss 的地址为 0x00427a30,根据TSS段描述符构造规则,构造如下描述符。

0000e942`7a300068

使用下面的命令安装到 GDT 表。

eq 8003f048 0000e942`7a300068

因为在 8003f048 这个位置是空的,所以我选择安装到这里。你需要根据你的情况选择合适的位置安装。具体见图3和图4.

设计任务门,安装到 IDT 表

TSS段刚刚是安装在8003f048这个位置,它的选择子是 0x48,根据任务门描述符规则,设计任务门描述符如下。

0000e500`00480000

使用下面的命令安装到 IDT 表。

eq 8003f500 0000e500`00480000

因为在我的 IDT 表中,8003f500 这个位置是空的,所以我选择安装在这里。安装在这个位置的话,那么它在 IDT 表中的索引是是 0x20。我的 IDT 表基址是 8003f400.


这里写图片描述
图3 安装TSS段描述符和任务门描述符


这里写图片描述
图3 安装描述符后的GDT表和IDT表

编写主函数,使用 INT 指令进入任务门

  • 代码
int main(int argc, char* argv[])
{
    printf("please input cr3:\n");
    scanf("%x", &(tss.cr3)); // 使用 !process 0 0 在 WinDbg 查看 DirBase

    __asm {
        int 0x20
    }

    // 不出意外,这里打印的值分别是 00000008, 0042ace4
    printf("g_cs = %08x\ng_esp = %08x\n", g_cs, g_esp);
    return 0;
}
  • 运行结果

    这里写图片描述

运行的时候需要注意,CR3 需要在 WinDbg 中查看。在 WinDbg 中使用命令 !process 0 0来查看程序TaskGate.exe 的 DirBase,然后在控制台里输入后回车继续执行。

完整代码

// 文件:TaskGate.cpp
#include <windows.h>
#include "tss.h" // tss.h 文件请移步至第11篇《TSS切换实验》中查看。

char st[10] = {0}; // 0042ace4

DWORD g_esp;
DWORD g_cs;

TSS tss = {// 0x00427a30
        0x00000000,//link
        (DWORD)st,//esp0
        0x00000010,//ss0
        0x00000000,//esp1
        0x00000000,//ss1
        0x00000000,//esp2
        0x00000000,//ss2
        0x00000000,//cr3
        0x00401020,//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) func() {//00401020
    __asm {
        mov g_esp, esp
        mov eax, 0
        mov ax, cs
        mov g_cs, eax

        iretd
    }
}
int main(int argc, char* argv[])
{
    printf("please input cr3:\n"); 
    scanf("%x", &(tss.cr3)); // 使用 !process 0 0 查看

    __asm {
        int 0x20
    }

    // 不出意外,这里打印的值分别是 00000008, 0042ace4
    printf("g_cs = %08x\ng_esp = %08x\n", g_cs, g_esp);
    return 0;
}

总结

本文主要使用任务门模拟了 TSS 的第二个用途。实验中涉及到了一个CR3的东西,大家暂时不用在意,照着做就行了,后面的文章讲会慢慢讲解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值