当前位置:网站首页>任务段&任务门
任务段&任务门
2022-04-22 06:19:00 【Misaka10046】
TSS段用来权限切换的时候,替换原来寄存器的信息。
TSS段的结构,一共104个字节,里面存放了上一个进程中的寄存器,栈和其他的一些信息

任务门的描述符,也存放在IDT表中。其中的Reserved 都是保留位,不需要自己构造。

TSS段的描述符,存放在GDT表中。其中TYPE位为9(1001)的时候,说明这个TSS没有加载到TR寄存器中。当TYPE位为B(1011)的时候,说明这个TSS已经加载到了TR寄存器中。

TR寄存器

构造过程
观察当前的TSS段描述符在GDT表中的哪个位置。

可以到地址去观察该结构,发现全是0,只有esp和ss中存放的有数据。

在其他的位置构造一个TSS段的描述符

然后通过!process 0 0来获取CR3(页基地址)的值填入,然后就实现了成功的切换

代码
#include "stdafx.h"
#include <WINDOWS.H>
typedef struct _KTSS
{
USHORT Backlink; //0x0
USHORT Reserved0; //0x2
ULONG Esp0; //0x4保存 0 环栈指针
USHORT Ss0; //0x8保存 0 环栈段选择子
USHORT Reserved1; //0xa
ULONG NotUsed1[4]; //0xc
ULONG CR3; //0x1c
ULONG Eip; //0x20
ULONG EFlags; //0x24
ULONG Eax; //0x28
ULONG Ecx; //0x2c
ULONG Edx; //0x30
ULONG Ebx; //0x34
ULONG Esp; //0x38
ULONG Ebp; //0x3c
ULONG Esi; //0x40
ULONG Edi; //0x44
USHORT Es; //0x48
USHORT Reserved2; //0x4a
USHORT Cs; //0x4c
USHORT Reserved3; //0x4e
USHORT Ss; //0x50
USHORT Reserved4; //0x52
USHORT Ds; //0x54
USHORT Reserved5; //0x56
USHORT Fs; //0x58
USHORT Reserved6; //0x5a
USHORT Gs; //0x5c
USHORT Reserved7; //0x5e
USHORT LDT; //0x60
USHORT Reserved8; //0x62
USHORT Flags; //0x64
USHORT IoMapBase; //0x66
}KTSS,*PKTSS;
KTSS tss = {
0};
char esp[0x2000] = {
0};
char esp0[0x2000] = {
0};
char buf[] = {
0,0,0,0,0x48,0x00};
char RET[] = {
0,0,0,0,0x28,0x00};
__declspec(naked) void test()
{
__asm
{
int 3
iretd//先检查有无任务嵌套 EFL NT的NT位,然后找TSS的Blink替换寄存器返回 如果NT位为0则会查堆栈返回 所以这个最好先把NT位置1再返回
}
}
int main()
{
printf("%x\r\n",(DWORD)&tss);
system("pause");
memset(esp,0,sizeof(esp));
memset(esp0,0,sizeof(esp0));
tss.Eax = 0;
tss.Ecx = 0;
tss.Edx = 0;
tss.Ebx = 0;
tss.Ebp = 0;
tss.Esi = 0;
tss.Edi = 0;
tss.Cs = 0x8;
tss.Ss = 0x10;
tss.Ds = 0x23;
tss.Es = 0x23;
tss.Fs = 0x30;
tss.Esp = (DWORD)esp + 0x2000 - 4;
tss.Esp0 = (DWORD)esp0 + 0x2000 - 4;
tss.Ss0 = 0x10;
tss.Eip = (DWORD)test;
DWORD dwCR3 = 0;
printf("CR3=");
scanf("%x",&dwCR3);
tss.CR3 = dwCR3;
__asm
{
call fword ptr buf//也可以JUMP过去 再JUMP回来 JUMP会把原TSS置闲 而CALL不会把原TSS置闲
}
return 0;
}
同样也可以通过双重错误,从IDT表跳到任务段中。
// door.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <WINDOWS.H>
//0x20ac bytes (sizeof)
typedef struct _KTSS
{
USHORT Backlink; //0x0
USHORT Reserved0; //0x2
ULONG Esp0; //0x4
USHORT Ss0; //0x8
USHORT Reserved1; //0xa
ULONG NotUsed1[4]; //0xc
ULONG CR3; //0x1c
ULONG Eip; //0x20
ULONG EFlags; //0x24
ULONG Eax; //0x28
ULONG Ecx; //0x2c
ULONG Edx; //0x30
ULONG Ebx; //0x34
ULONG Esp; //0x38
ULONG Ebp; //0x3c
ULONG Esi; //0x40
ULONG Edi; //0x44
USHORT Es; //0x48
USHORT Reserved2; //0x4a
USHORT Cs; //0x4c
USHORT Reserved3; //0x4e
USHORT Ss; //0x50
USHORT Reserved4; //0x52
USHORT Ds; //0x54
USHORT Reserved5; //0x56
USHORT Fs; //0x58
USHORT Reserved6; //0x5a
USHORT Gs; //0x5c
USHORT Reserved7; //0x5e
USHORT LDT; //0x60
USHORT Reserved8; //0x62
USHORT Flags; //0x64
USHORT IoMapBase; //0x66
//struct _KiIoAccessMap IoMaps[1]; //0x68
//UCHAR IntDirectionMap[32]; //0x208c
}KTSS,*PKTSS;
KTSS tss = {
0};
char esp[0x2000] = {
0};
char esp0[0x2000] = {
0};
char buf[] = {
0,0,0,0,0x48,0x00};
char RET[] = {
0,0,0,0,0x28,0x00};
__declspec(naked) void test()
{
__asm
{
int 3
iretd
}
}
int main()
{
printf("%x\r\n",(DWORD)&test);
printf("%x\r\n",(DWORD)&tss);
system("pause");
memset(esp,0xcc,sizeof(esp));
memset(esp0,0xcc,sizeof(esp0));
tss.Eax = 0;
tss.Ecx = 0;
tss.Edx = 0;
tss.Ebx = 0;
tss.Ebp = 0;
tss.Esi = 0;
tss.Edi = 0;
tss.Cs = 0x8;
tss.Ss = 0x10;
tss.Ds = 0x23;
tss.Es = 0x23;
tss.Fs = 0x30;
tss.Esp = (DWORD)esp + 0x2000 - 4;
tss.Esp0 = (DWORD)esp0 + 0x2000 - 4;
tss.Ss0 = 0x10;
tss.Eip = (DWORD)test;
DWORD dwCR3 = 0;
printf("CR3=");
scanf("%x",&dwCR3);
tss.CR3 = dwCR3;
_asm{
int 0x20;
}
return 0;
}
修改IDT表,让报错之后能再报一次错转入任务段中

修改GDT表

输入CR3的页基址,实现提权

TIPS
int 3 断下时,如果不恢复eflags寄存器,其就会卡死。
因为当进行TSS跳转时,其会将老的TSS保存在新的TSS头部(上面我们看到),当我们使用iretd返回时,其不是像中断那样根据返回地址,而是根据TSS段选择子找旧的TSS段内存,然后将里面的寄存器全部加载进去。
而INT 3 会清空 VM、NT、IF、TF四个位,其中NT表示嵌套任务段(nested task),如果清空,其就认为不存在任务段嵌套,直接像常规那样,根据返回地址返回,此时就会出错。
因此就会存在下面一段代码来修改elfags寄存器中的NT位。
pushfd;
pop eax;
or eax,0x4000;
push eax;
popfd;
版权声明
本文为[Misaka10046]所创,转载请带上原文链接,感谢
https://blog.csdn.net/Misaka10046/article/details/116205808
边栏推荐
- Kotlin 协程Flow、StateFlow、ShareFlow
- Kotlin Flow实现线程切换
- Codeforces Round #780 (Div. 3)
- 15 · 全排列
- Longest ascending sequence
- The art of concurrent programming (9): the use and principle of final
- Dom 文档对象模型
- Leetcode - 1 - (substructure, combination, spiral matrix and full arrangement of tree < Ⅰ Ⅲ >)
- L2-002 链表去重(测试点1的坑)
- C language | array
猜你喜欢

Redis的设计与实现(3):持久化策略RDB、AOF

C language | pointer

Minimum circle coverage (basis of computational geometry)

L2-004 is this a binary search tree? (first order input & judgment search Binary Tree & second order output)

L2-001 emergency rescue (extension of shortest Dijkstra - number of shortest paths & maximum weight of paths)

L2-002 linked list weight removal (pit of test point 1)

Redis的设计与实现(1):了解数据结构与对象

H. Happy number (binary conversion / nth special number) (2021 Niuke summer multi school training camp 9)

Abstract classes and abstract methods

LeetCode -3 - (字符串相加、最大连续1的个数<ⅠⅢ>、考试的最大困扰度、删除链表的倒数第N个结点)
随机推荐
Cache hit rate of sequential table
X64基础(一)
Redis的设计与实现(3):持久化策略RDB、AOF
FFmpeg命令(七)、 音频与视频合并成视频
并发编程的艺术(3):深入理解Synchronized的原理
H.Happy Number (进制转换/第n个特殊数)(2021牛客暑期多校训练营9 )
Leetcode - 3 - (string addition, maximum number of consecutive 1 < Ⅰ Ⅲ >, maximum difficulty of the exam, deletion of the penultimate node of the linked list)
System log collection series
并发编程的艺术(2):Synchronized的使用场景
1242 · non overlapping interval
2019.1.2 idea usage tutorial
Links summary qwq
Kotlin协程+Flow+Retrofit实现网络请求
系统日志文件过大优化
并发编程的艺术(5):ReentrantLock的使用
Codeforces Round #779 (Div. 2)
L1-071 previous life files (20 points) (similar two points)
437. Path sum III
1005 monopoly congruence solution (2021 Chinese college student programming competition CCPC network trial replay)
Use of ansible