任务段call 与jmp实验

任务段

前言

在调用门和中断门还有陷阱门中,会有压栈操作,由于cs和cpl会发生改变,导致ss也必须切换,切换时候,esp和ss是从任务段中获得的,也及时TSS

 

TSS结构

 

 

 大小共104字节

TR寄存器

了解任务段一定要知道TR寄存器,这是CPU找到TSS的关键,TR寄存器总共有98个位(其实是16位,跟段选择子一样)

流程:

1、tr寄存器通过段选择子

2、在gdt表里面找到段描述符,并且通过段描述符的结构,找到BaseAddress地址,找到BaseAddress地址后,相当于找到了TSS任务段

3、并且从段描述符中还获得了lmit其实就是TSS段的大小在32位的情况下一般是0x68字节的,如图

 

 

 TSS段描述符结构

其实这里本应该在放一张开发Intel手册的图的,这样更清晰

Type 1001代表着是可用的任务段,如果B为1则是繁忙状态

 

 TR寄存器的读写

将段描述符加载到TR寄存器

LTR指令

说明:

1、用LTR指令去装载的话,仅仅是改变TR寄存器的值(96位),并没有真正改变TSS(原来的TSS还在那)

2、LTR指令只能在系统层使用

3、加载后TSS段描述符会状态位会发生改变

 

读TR寄存器

STR指令

说明:

如果用STR去读的话,只读了TR寄存器的16为,也就是选择子

 

实验流程

先构造TSS任务段,然后在将任务段的eip改为你要执行函数的地址,其他的可以根据你自己的改,其次就是需要让cs和ss指向的是同一个(因为他们是一对),在去执行就可以调用成功了,不过我这里有个问题,希望有大佬可以指出

放代码,如下:

 1 // Task_Segment.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include "stdafx.h"
 5 #include<windows.h>
 6 DWORD dwOK;
 7 DWORD dwESP;
 8 DWORD dwCS;
 9 __declspec(naked) void func()
10 {
11     dwOK=1;
12     __asm{
13         int 3
14         mov eax,esp
15         mov dwESP,eax
16         mov ax,cs
17         mov word ptr [dwCS],ax
18         iretd
19         //go back code don't write
20     }
21 }
22 
23 int main(int argc, char* argv[])
24 {
25     char bu[0x10];//0x12ff70
26     int iCr3;
27     printf("input CR3:\n");
28     scanf("%x",&iCr3);
29 
30     DWORD iTss[0x68]={
31         0x00000000,//link
32         (DWORD)bu,//esp0
33         0x00000010,//ss0
34         0x00000000,//esp1
35         0x00000000,//ss1
36         0x00000000,//esp2
37         0x00000000,//ss2
38         (DWORD)iCr3,//cr3
39         0x00401020,//eip
40         0x00000000,//eflags
41         0x00000000,//eax
42         0x00000000,//ecx
43         0x00000000,//edx
44         0x00000000,//ebx
45         (DWORD)bu,//esp
46         0x00000000,//ebp
47         0x00000000,//esi
48         0x00000000,//edi
49         0x00000023,//es
50         0x00000008,//cs 0x0000001B
51         0x00000010,//ss 0x00000023
52         0x00000023,//ds
53         0x00000030,//fs 0x0000003B
54         0x00000000,//ldt
55         0x20ac0000
56     };
57     printf("iTss: %x\n",iTss);
58     /*
59     __asm{
60         int 0x20
61       }
62     */
63     char buff[6];
64 
65     *(DWORD*)&buff[0]=0x12345678;
66     *(WORD*)&buff[4]=0x48;
67     _asm
68     {
69         call fword ptr [buff]
70     }
71     printf("ok = %d ESP = %x CS = %x \n",dwOK,dwESP,dwCS);
72     return 0;
73 }

 

根据函数地址,创建段描述符

 

 

修改段描述符

 

 通过指令!process 0 0输入CR3

 

输入0aac0320 

 

 输入g运行,可以看到,已经运行了

 

 为了方便在来看下寄存器

 

 

 

 观察寄存器可以发现,所有的寄存器已经被换掉了

但不知道为啥 运行到这里之后,运行了in3后,接着运行到iretd就开始报错了,所以我怀疑我跳回去的代码是有问题的,如果不是用iretd这个指令跳回去,那我应该怎么跳回去呢?

在网上也查了别人的执行流程,感觉是一个道理,沉淀依然不够,得把实验实力加深点,再来看看这个错误了,还得接着实验才行了

 

提问

 

 

 1:)8号中断是什么?

 

8003f440  00008500`00501198
将其分解

 

 在去查找其相对应的段选择子

 

 8003f050  80008955`27000068

接着分解

 

 可以知道base

用命令dt  _KTSS 查看该地址检查

0: kd> dt _KTSS 80552700
nt!_KTSS
   +0x000 Backlink         : 0
   +0x002 Reserved0        : 0
   +0x004 Esp0             : 0x8054f700
   +0x008 Ss0              : 0x10
   +0x00a Reserved1        : 0
   +0x00c NotUsed1         : [4] 0
   +0x01c CR3              : 0xb0d000
   +0x020 Eip              : 0x80544509
   +0x024 EFlags           : 0
   +0x028 Eax              : 0
   +0x02c Ecx              : 0
   +0x030 Edx              : 0
   +0x034 Ebx              : 0
   +0x038 Esp              : 0x8054f700
   +0x03c Ebp              : 0
   +0x040 Esi              : 0
   +0x044 Edi              : 0
   +0x048 Es               : 0x23
   +0x04a Reserved2        : 0
   +0x04c Cs               : 8
   +0x04e Reserved3        : 0
   +0x050 Ss               : 0x10
   +0x052 Reserved4        : 0
   +0x054 Ds               : 0x23
   +0x056 Reserved5        : 0
   +0x058 Fs               : 0x30
   +0x05a Reserved6        : 0
   +0x05c Gs               : 0
   +0x05e Reserved7        : 0
   +0x060 LDT              : 0
   +0x062 Reserved8        : 0
   +0x064 Flags            : 0
   +0x066 IoMapBase        : 0x20ac
   +0x068 IoMaps           : [1] _KiIoAccessMap
   +0x208c IntDirectionMap  : [32]  ""

2:)做了什么事情?

替换当前环境的值

3:)替换了哪些寄存器?

查看了idtr表后可以知道,其切换了cs段,在学习调用门的时候就知道,提权会保存之前的环境的,所以在运行时,可以知道寄存器更改了cs、ss、esp、ip

在来看看任务门替换的,可以发现都是由于ss与ds必须是一对,cs又都是一样的,所以只有ip变了

4:)替换后的值是多少?

0x80544509

 

5:)为什么这样设计

程序出现异常,进行任务的切换

 

posted @ 2020-10-15 15:05  PYozo_free  阅读(408)  评论(0编辑  收藏  举报