中断门陷阱门提权

2a6f748e12edacf1417515c3e462c415.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

#ifndef _WIN64
typedef struct _GeneralRegisters
{
DWORD eax;
DWORD ecx;
DWORD edx;
DWORD ebx;
DWORD esp;
DWORD ebp;
DWORD esi;
DWORD edi;

}GeneralRegisters, * pGeneralRegisters;
#else
typedef struct _GeneralRegisters
{
QWORD eax;
QWORD eax;
QWORD eax;
QWORD eax;
QWORD eax;
QWORD eax;
QWORD eax;
QWORD eax;

}GeneralRegisters, * pGeneralRegisters;
#endif

typedef struct _SegmentRegisters
{
WORD cs;
WORD ds;
WORD es;
WORD fs;
WORD gs;
WORD ss;
WORD ldtr;
WORD tr;

}SegmentRegisters, * pSegmentRegisters;


GeneralRegisters gr_r0 = { 0 };
GeneralRegisters gr_r3 = { 0 };

SegmentRegisters sr_r0 = { 0 };
SegmentRegisters sr_r3 = { 0 };

BYTE GDT[6] = { 0 };


void GetGRs(GeneralRegisters* gr)
{
_asm
{
mov ecx, [gr]
mov dword ptr[ecx + 0x0], eax
mov dword ptr[ecx + 0x4], ecx
mov dword ptr[ecx + 0x8], edx
mov dword ptr[ecx + 0xC], ebx
mov dword ptr[ecx + 0x10], esp
mov dword ptr[ecx + 0x14], ebp
mov dword ptr[ecx + 0x18], esi
mov dword ptr[ecx + 0x1C], edi
}
}

void GetSRs(SegmentRegisters* sr)
{
_asm
{
mov ecx,[sr]
mov word ptr [ecx+0x0], cs
mov word ptr [ecx+0x2], ds
mov word ptr [ecx+0x4], es
mov word ptr [ecx+0x6], fs
mov word ptr [ecx+0x8], gs
mov word ptr [ecx+0xA], ss
}
}

//读取选择子为0008的段描述符
BYTE Buf[0x8] = { 0 };
void __declspec(naked) ReadGDT()
{
_asm
{
//int 3
pushad
pushfd

sgdt GDT
mov eax, dword ptr[GDT + 0x2]
mov ebx, dword ptr[eax + 0x8]
mov dword ptr[Buf], ebx
mov ebx, dword ptr[eax + 0xC]
mov dword ptr[Buf+0x4],ebx

popfd
popad
ret
}
}

void PrintGRs(GeneralRegisters* gr)
{
printf("EAX=%x\n", gr->eax);
printf("ECX=%x\n", gr->ecx);
printf("EDX=%x\n", gr->edx);
printf("EBX=%x\n", gr->ebx);
printf("ESP=%x\n", gr->esp);
printf("EBP=%x\n", gr->ebp);
printf("ESI=%x\n", gr->esi);
printf("EDI=%x\n", gr->edi);
}

void PrintSRs(SegmentRegisters* sr)
{
printf("CS=%x\n", sr->cs);
printf("DS=%x\n", sr->ds);
printf("ES=%x\n", sr->es);
printf("FS=%x\n", sr->fs);
printf("GS=%x\n", sr->gs);
printf("SS=%x\n", sr->ss);
}

//中断门调用
void __declspec(naked) INTGate()
{
_asm
{
//int 3
//中断门中调用int3,会改变fs寄存器的值,iret/iretd后fs不会恢复,弹异常
//解决方法:中断调用前push fs保存fs的值,调用结束后再pop fs手动恢复
//此处引用https://www.cnblogs.com/onetrainee/p/12436327.html看法
/*
这个错误的原因并不是Intel的问题,我们之后嵌套调用门,int20 --> int21 并没有发现这个问题;
     并且查阅intel手册,里面重点强调NT、IF、VM等Eflags位,并没有提到FS寄存器;
     因此这里可以推断是Windows的处理机制存在的问题,怀疑是先前模式搞得鬼,我们在三环,但是使用
零环的权限,而系统以为我们在内核调用int3;
     这问题先放一下,之后如果有时间再来研究这个问题。
*/
pushad
pushfd
}
GetSRs(&sr_r0);
ReadGDT();
_asm
{
popfd
popad
iretd
}

}

//陷阱门调用
void __declspec(naked) TrapGate()
{
_asm
{
int 3
pushad
pushfd
}
GetSRs(&sr_r0);
GetGRs(&gr_r0);
ReadGDT();
_asm
{
popfd
popad
iretd
}
}

//中断门和陷阱门唯一的区别就是通过中断门时eflags的IF位被清零以屏蔽可屏蔽中断,而陷阱门不会

int main(int argc, char* argv[])
{
GetGRs(&gr_r3);
GetSRs(&sr_r3);

puts("Ring3 General Registers:");
PrintGRs(&gr_r3);
puts("Ring3 Segment Registers:");
PrintSRs(&sr_r3);

_asm
{
push fs
int 0x20
pop fs
}

puts("Ring0 General Registers:");
PrintGRs(&gr_r0);
puts("Ring0 Segment Registers:");
PrintSRs(&sr_r0);

putchar('\n');
printf("%x`%x\n", *(DWORD*)Buf, *(DWORD*)&Buf[4]);

getchar();

return 0;
}

3345082b4db7225f65f3b857830ceb95.png


中断门陷阱门提权
https://rogxo.github.io/2021/12/16/2021-12-16-中断门陷阱门提权/
作者
Rogxo
发布于
2021年12月16日
许可协议
CC BY-NC-SA 4.0