Loading... 自由不同特权切换,需要用到几种方式-门描述符。 S为1时-代码段/数据段。 S为0时-系统段 | 门 | TYPE | 描述 | | - | - | - | | 调用门 | 12 | | | 中断门 | 14 | 异常处理的函数地址,中断门执行IF位会清零,屏蔽可以屏蔽的中断,陷阱门不会 | | 陷阱门 | 15 | 中断处理的函数地址 | | 任务门 | 5 | | ![196406-20191230101816343-1359964647.png](http://www.irohane.top/usr/uploads/2021/02/1272484966.png) 结构体 使用unsigned 避免因为符号位干扰到最高位。 ```cpp typedef struct _CALLGATE { unsigned int offset1 : 16; // 提权后执行代码的低地址 unsigned int selector : 16; // 需要提升的权限对应的选择子 unsigned int paramcount : 5; // 提权后执行的代码用到的参数 unsigned int : 3; // 保留位 unsigned int type : 4; // 对于调用门始终是 1100 unsigned int S : 1; // 对于调用门始终是 0 unsigned int DPL : 2; // 访问我需要的权限,应该写 3 unsigned int P : 1; // 必须是有效的段描述符 unsigned int offset2 : 16; // 提权后执行代码的高地址 } CALLGATE, *PCALLGATE; ``` # 手动解析系统段 在之前的表中找到 ![image.png](http://www.irohane.top/usr/uploads/2021/02/3518583143.png) | 高4位 | | 基地址(31-24) | G(23) | D/B(22) | O(21) | AVL(20) | 段限长(19-16) | P(15) | DPL(14-13) | S(12) | TYPE(11-8) | 基地址(7-0) | | - | - | - | - | - | - | - | - | - | - | - | - | - | | 80008b1e | 1000<br />0000<br />0000<br />0000<br />1000<br />1011<br />0001<br />1110 | 1000<br />0000 | 0 | 0 | 0 | 0 | 0000 | 1 | 00 | 0 | 1011 | 00011110 | # 调用门提升权限 # 配置属性 取消随机机制-方便测试调用 ![image.png](http://www.irohane.top/usr/uploads/2021/02/2357991237.png) ``` #include <Windows.h> #include <stdio.h> #include <stdlib.h> typedef struct _CALLGATE { unsigned int offset1 : 16; // 提权后执行代码的低地址 unsigned int selector : 16; // 需要提升的权限对应的选择子 unsigned int paramcount : 5; // 提权后执行的代码用到的参数 unsigned int : 3; // 保留位 unsigned int type : 4; // 对于调用门始终是 1100 unsigned int S : 1; // 对于调用门始终是 0 unsigned int DPL : 2; // 访问我需要的权限,应该写 3 unsigned int P : 1; // 必须是有效的段描述符 unsigned int offset2 : 16; // 提权后执行代码的高地址 } CALLGATE, * PCALLGATE; // 在进行权限切换的过程中,栈也会随之改变 short r0_ss = 0; int r0_esp = 0; // 裸函数,只生成用户编写的代码,在其中操作高地址空间 _declspec(naked) void r0_function() { __asm { int 3 mov r0_ss, ss //; 获取 r0 权限的 ss mov r0_esp, esp //; 获取 r0 权限的 esp retf //; 调用门必须使用 retf 进行返回 //; 实现通过调用门读取到 gdt 中的第 3 项 //; sgdt 可以获取 gdt 的地址 //; 对于中断门和陷阱门必须使用 iretd } } int main() { //1. 利用段描述符使 - 跳转到段描述符位置 // 描述符表索引:13 TI:1 RPL:2 我们必须按照这个格式进行填充 // 在图中第九位为 空借用 0 0000 0000 1001 0 11 11可以低权限调用 1001 = 9 // 0000 0000 0100 1011 // 0x00 0x4B BYTE Dest[] = { 0x00,0x00,0x00,0x00,0x4B,0x00 }; //从小端开始 加载到内存 4B 00 2字节16位 //2. 构建系统段描述符 //Call 构造的地址 0045 3500 构造门 // 0045EC00`00083500 __asm push fs __asm call fword ptr Dest __asm pop fs //输出 printf("%04X:%08X\n", r0_ss, r0_esp); system("pause"); r0_function(); return 0; } ``` ![image.png](http://www.irohane.top/usr/uploads/2021/02/1415716253.png) 在代码中找到位置 ![image.png](http://www.irohane.top/usr/uploads/2021/02/3908290843.png) 查看gdtr 看到第九项 - 全为0 更改一下为代码段地址 0045EC00`00083500 ![image.png](http://www.irohane.top/usr/uploads/2021/02/2727654924.png) ![image.png](http://www.irohane.top/usr/uploads/2021/02/3004633058.png) ![image.png](http://www.irohane.top/usr/uploads/2021/02/3733257229.png) ![image.png](http://www.irohane.top/usr/uploads/2021/02/2931781135.png) 最后修改:2021 年 02 月 02 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏