调用门提权
调用门知识点
当S位为0, TYPE位为C, 这个就是调用门;
cs.DPL == ss.DPL == 调用门.DPL;
前期准备
- 填充调用门描述符(参数暂时为0个); 函数地址为00401080;
0040ec00`00081080 - 修改gdtr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24kd> r gdtr
gdtr=80b98800
kd> dq 80b98800
ReadVirtual: 80b98800 not properly sign extended
80b98800 00000000`00000000 00cf9b00`0000ffff
80b98810 00cf9300`0000ffff 00cffb00`0000ffff
80b98820 00cff300`0000ffff 80008bb9`8c0020ab
80b98830 804093b9`b0004fff 0040f300`00000fff
80b98840 0000f200`0400ffff 00000000`00000000
80b98850 800089b9`ad200067 800089b9`acb00067
80b98860 00000000`00000000 00000000`00000000
80b98870 800092b9`880003ff 00000000`00000000
kd> eq 80b98848 0040ec02`00081080
WriteVirtual: 80b98848 not properly sign extended
kd> dq 80b98800
ReadVirtual: 80b98800 not properly sign extended
80b98800 00000000`00000000 00cf9b00`0000ffff
80b98810 00cf9300`0000ffff 00cffb00`0000ffff
80b98820 00cff300`0000ffff 80008bb9`8c0020ab
80b98830 804093b9`b0004fff 0040f300`00000fff
80b98840 0000f200`0400ffff 0040ec02`00081080
80b98850 800089b9`ad200067 800089b9`acb00067
80b98860 00000000`00000000 00000000`00000000
80b98870 800092b9`880003ff 00000000`00000000 - cs寄存器为0008, ss寄存器为0010
cs + 8 = ss
1
2
3
4
5
600401080 cc int 3
kd> r
eax=00000000 ebx=7ffd6000 ecx=4a36ab6a edx=0052017c esi=0012fe28 edi=0012ff08
eip=00401080 esp=89b49c98 ebp=0012ff08 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
00401080 cc int 3 - 返回时报错
进入0环前fs寄存器为0x3b, 进入0环后会将fs修改成0x30, 在返回时未进行修复;
代码实验
1 | // 10_10_CallGate(调用门).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 |
跨段不提权只压两个值(eip, cs); 跨段提权会压四个值(eip, cs, esp, ss);
retf有参数时需要加上参数, 两个参数retf 8;
系统描述符类型
当段描述符的S标志(描述符类型)为0, 则描述符为系统描述符。处理器可以识别以下类型的系统描述符:
- 局部描述符表(LDT)段描述符;
- 任务状态段(TSS)描述符;
- 调用门描述符;
- 中断门描述符;
- 陷阱门描述符;
- 任务门描述符;
这些描述符又可以分为两类: 系统段描述符和门描述符。系统段描述符指向系统段(LDT和TSS段)。门描述符它们自身就是”门”, 它们或者持有指向放置在代码段中的过程入口点的指针, 或者持有TSS(任务门)的段选择子。
调用门格式
4.8.3, 页码是93;
调用门为不同特权级间的进程控制转移提供了便利。它们一般只用在使用特权级保护机制的操作系统或管理程序中。调用门也可用于16位和32位代码段之间进程控制转移, 这在17.4.“混合尺寸代码段之间的控制转移”中进行描述。
调用门描述符可用在GDT或LDT中, 但是不能在中断描述符表(IDT)中。它具有六个方面的功能:
- 确定将要访问的代码段;
- 定义例程在指定代码段的入口;
- 指定调用例程的所应当有的特权级;
- 如果有栈切换, 就确定在栈之间拷贝的可选参数的个数;
- 定义压入目标栈的值的尺寸: 16位的门执行16位的压栈, 32位的门执行32位的压栈;
- 确定调用门描述符是否有效;
作业
- 使用jmp跨段跳转调用门;
- 在调用门上不支持改cs寄存器的值;
- jmp在调用门只能同权限跳转;
- 既然ret也能跳转, 那么是否可以提权;
- 无法修改cs寄存器的值, 无法提权, 也没有提权的悬念
- 既然retf也能跳转, 那么是否可以提权;
- 英特尔规定retf只能同权限或向低权限跳转;
补充
- call是同权限或者提权跳转