抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

调用门提权

调用门知识点

当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
    24
    kd> 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
    6
    00401080 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
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
// 10_10_CallGate(调用门).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>

void __declspec(naked) test()
{
__asm
{
int 3;

retf;
}
}

int main()
{
char bufcode[6] = { 0,0,0,0,0x4b,0 };
printf("%p\r\n", test);

system("pause");

__asm
{
push fs;
call fword ptr bufcode;
pop fs;
}

system("pause");
return 0;
}

跨段不提权只压两个值(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位的压栈;
  • 确定调用门描述符是否有效;

作业

  1. 使用jmp跨段跳转调用门;
  • 在调用门上不支持改cs寄存器的值;
  • jmp在调用门只能同权限跳转;
  1. 既然ret也能跳转, 那么是否可以提权;
  • 无法修改cs寄存器的值, 无法提权, 也没有提权的悬念
  1. 既然retf也能跳转, 那么是否可以提权;
  • 英特尔规定retf只能同权限或向低权限跳转;

补充

  • call是同权限或者提权跳转

评论