原文地址:www.trustwave.com/en-us/resou…
原文作者:
发布时间:2020年3月2日
简介
又见面了! 我们又回来了,有更多的Windows内部知识,现在是时候进入正题了。我们已经介绍了如何设置环境,WinDBG基础知识,并讨论了WinDBG时间旅行调试。在我博客系列的第四部分,我将简要介绍一个内部API,它被广泛用于泄露内核信息,用于大多数Windows LPE(本地特权升级)漏洞。我们将谈一谈NTQuerySystemInformation这个函数。
NTQuerySystemInformation和系统信息类
函数NTQuerySystemInformation是在NTDLL上实现的。作为一个内核API,它在Windows版本中总是在不经意间被更新。如前所述,这是一个私有函数,所以没有被微软正式记录下来。从早期的Windows NT-family系统开始,它就被用于不同的系统调用ID,你可以在下表中看到[j00ru.vexillium.org/syscalls/nt…
/ | Windows XP到Windows 7 | Windows 8 & 2012 SP0 | Windows 8.1 & 2012 R2 | Windows 10 |
---|---|---|---|---|
NTQuerySystemInformation | 0x0033 | 0x0034 | 0x0035 | 0x0036 |
该函数基本上从环境中检索特定信息,其结构非常简单。
NtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
复制代码
在第一个参数SYSTEM_INFORMATION_CLASS(ULONG)中,我们将设置要检索的信息。这些类被命名为Windows系统信息类,并在 winternl.h中定义。
有许多数据可以和函数一起使用这些类来检索。关于系统、进程、对象和其他的信息。
下面,列出了一些可以使用的类。
注意。
- late 5.0从Windows 2000 SP4开始。
- 5.1后期从Windows XP SP2开始。
- 非常晚的5.1版本从Windows XP SP3开始。
- 5.2后期从Windows Server 2003 SP1开始。
- 晚期6.0版本从Windows Vista SP1开始。
- 6.1后期开始于Windows 7 SP1。
数值 | 符号名称 | 版本 | 备注 |
---|---|---|---|
0x00 | 系统基本信息 | 3.10及以上版本 | |
0x01 | 系统处理器信息 | 3.10及以上版本 | |
0x02 | 系统性能信息 | 3.10及以上版本 | |
0x03 | 系统时间信息 | 3.10及更高版本 | |
0x04 | 系统路径信息 | 3.10及更高版本 | |
0x05 | 系统进程信息 | 3.10 及以上版本 | |
0x06 | 系统呼叫次数信息 | 3.10及更高版本 | |
0x07 | 系统设备信息 | 3.10及更高版本 | |
… | … | … | … |
0x40 | 系统扩展手柄信息 | 5.1及以上版本 | |
0x41 | 系统丢失延迟写入信息 | 5.1及更高版本 | |
0x42 | 未知数 | 晚期5.1独有 | |
0x42 | SystemBigPoolInformation | 5.2及以上 | |
0x43 | SystemSessionPoolTagInformation | 5.2及更高版本 | |
0x44 | SystemSessionMappedViewInformation | 5.2及更高版本 | |
… | … | … | … |
0x58 | 系统进程标识信息 | 6.0及以上版本 | |
0x59 | SystemErrorPortInformation | 6.0及更高版本 | |
0x5A | 系统启动环境信息 | 6.0 及以上版本 | |
0x5B | 系统管理员信息 | 6.0 及以上版本 | |
0x5C | 系统验证器信息 | 6.0及更高版本 | |
0x5D | 系统时区信息 | 6.0及更高版本 | |
0x5E | 系统图像文件执行选项信息 | 6.0及以上版本 | |
0x5F | 系统覆盖信息 | 6.0及更高版本 | |
0x60 | 系统取样信息 | 6.0及更高版本 | |
… | … | … | … |
0xA8 | SystemAllowedCpuSetsInformation | 10.0 及以上 | |
0xA9 | 系统Dma保护信息 | 10.0及更高版本 | |
0xAA | 系统中断CpuSets信息 | 10.0及更高版本 | |
0xAB | 系统安全启动政策完整信息 | 10.0及更高版本 | |
0xAC | 系统代码完整性政策完整信息 | 10.0 及更高版本 | |
0xAD | 系统化中断处理器信息 | 10.0及更高版本 | |
0xAE | 系统根基信息 | 10.0及更高版本 | |
… | … | … | … |
0xC7 | SystemCodeIntegrityVerificationInformation | 1803以上 | |
0xC8 | 系统固件分区信息 | 1803以上 | |
0xC9 | 系统配置控制信息 | 1803以上 | |
0xCA | SystemDmaGuardPolicyInformation | 1803以上 | |
0xCB | 系统飞地启动控制信息 | 1803以上 |
来源:www.geoffchappell.com/studies/win…
使用方法
我们可以使用多个信息类,而这个过程的一部分,就是要发现哪一个在我们的开发方法中会有用。如果我们需要发现一个EPROCESS或一个驱动程序的基本地址,对于每一个都有一个特定的类,我们可以实现。对于每一个类,我们都需要定义其结构。一些例子。
SystemModuleInformation (0x0b)
typedef struct SYSTEM_MODULE {
PVOID Reserved1;
PVOID Reserved2;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT PathLength;
CHAR ImageName[256];
}
typedef struct SYSTEM_MODULE_INFORMATION {
ULONG ModulesCount;
SYSTEM_MODULE Modules[0];
}
复制代码
在SYSTEM_MODULE_INFORMATION->ModulesCount[i].ImageBase,你会发现任何内核模块的基础地址。这可以用来计算HalDispatchTable,例如,使用内核基址。这个表包含了在利用过程中可能被覆盖的函数指针。
SystemHandleInformation (0x10)
typedef struct SYSTEM_HANDLE {
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
}
typedef struct SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
}
复制代码
在这种情况下,在SYSTEM_HANDLE_INFORMATION->Handles[i].Object中,你可以从一个特定的手柄中找到内核空间中的对象地址,例如,可以通过进程ID进行过滤(参见概念验证)。
这只是两个可以利用的信息类的例子,然而还有更多有用的类,如SystemExtendedHandledInformation、SystemLockInformation、SystemExtendedProcessInformation等等。
值得注意的是,所有这些结构都是没有记录的,感谢Mateusz Jurcyzk、Alex Ionescu和其他研究人员的伟大工作,我们现在有了准确的描述。
关于信息类的更多信息:j00ru.vexillium.org/papers/2011…
概念验证
我开发了一个简单的代码,使用SystemHandleInformation从运行中的进程中检索出打开的句柄地址。我试图尽可能的简单,以便对你进行教育。因此,你可能想探索这个和其他信息类,以发现它们的功能并确定还能做什么。
C:\>NTQuerySystemInformation-PoC1.exe
NTQuerySystemInformation() PoC -- Bruno Oliveira @mphx2
Address: 0xFFFFC90441603180, Object Type: 37, Handle: 4
Address: 0xFFFFC9043F8B7E60, Object Type: 16, Handle: 8
Address: 0xFFFFC9043F8B7F60, Object Type: 16, Handle: c
Address: 0xFFFFC90444662D50, Object Type: 36, Handle: 10
Address: 0xFFFFC90440581C40, Object Type: 35, Handle: 14
Address: 0xFFFFC90440096D70, Object Type: 30, Handle: 18
Address: 0xFFFFC90446352290, Object Type: 21, Handle: 1c
Address: 0xFFFFC904446633D0, Object Type: 36, Handle: 20
Address: 0xFFFFC90446353060, Object Type: 21, Handle: 24
Address: 0xFFFFC90444662EF0, Object Type: 36, Handle: 28
Address: 0xFFFFC9043FD7A0F0, Object Type: 50, Handle: 2c
Address: 0xFFFFC9043FDA1450, Object Type: 50, Handle: 30
Address: 0xFFFFC9043FDA0730, Object Type: 50, Handle: 34
Address: 0xFFFFA204CB57A840, Object Type: 3, Handle: 38
Address: 0xFFFFC9043F8B9EE0, Object Type: 16, Handle: 3c
Address: 0xFFFFC9043F8C0B60, Object Type: 16, Handle: 40
Address: 0xFFFFC90446A4EBD0, Object Type: 37, Handle: 44
Address: 0xFFFFC90446A4D140, Object Type: 37, Handle: 48
Address: 0xFFFFC9043FDA0E30, Object Type: 50, Handle: 4c
Address: 0xFFFFC90440074710, Object Type: 37, Handle: 50
Address: 0xFFFFC90440073C20, Object Type: 37, Handle: 54
Address: 0xFFFFC90440073C20, Object Type: 37, Handle: 58
Address: 0xFFFFC9043ED774F0, Object Type: 46, Handle: 5c
Address: 0xFFFFC9043FDA18B0, Object Type: 50, Handle: 60
Address: 0xFFFFC9043FDA1A70, Object Type: 50, Handle: 64
Address: 0xFFFFC9043FDA0810, Object Type: 50, Handle: 68
Address: 0xFFFFC9043FDA2B00, Object Type: 35, Handle: 6c
Address: 0xFFFFC90445354740, Object Type: 30, Handle: 70
Address: 0xFFFFC904463602C0, Object Type: 21, Handle: 74
Address: 0xFFFFC90444663090, Object Type: 36, Handle: 78
Address: 0xFFFFC904463603D0, Object Type: 21, Handle: 7c
Address: 0xFFFFC90444662460, Object Type: 36, Handle: 80
Address: 0xFFFFA204E5D57670, Object Type: 44, Handle: 84
Address: 0xFFFFA204E5D83E70, Object Type: 44, Handle: 8c
C:\>
复制代码
PoC源码可在:github.com/bmphx2/PoC-…
检查WinDBG上的地址。
lkd> !object 0xFFFFC90441603180
Object: ffffc90441603180 Type: (ffffc904384f8380) File
ObjectHeader: ffffc90441603150 (new version)
HandleCount: 2 PointerCount: 65536
Directory Object: 00000000 Name: \Reference {ConDrv}
复制代码
漏洞
这种信息泄露对于绕过内核随机化KASLR(内核地址空间布局随机化)非常有用。假设我们已经通过一些 “写什么 “的漏洞控制了内核,我们需要知道我们到底应该在哪里修改,以提升我们的权限。通过利用这个API,我们现在能够定位内核空间上的多个对象,并计算出我们可能需要的任何其他对象的偏移量。使得这个函数非常特别的是,它可以被一个没有特权的用户调用。换句话说,你不需要是SYSTEM来请求操作系统的内部信息。有多个利用这一事实运行的漏洞。浏览Windows的LPE漏洞很容易识别。请随意自己做一些分析。
好奇心
2017年和2018年,Google Project Zero在NTQuerySystemInformation函数本身上发现了漏洞。
bugs.chromium.org/p/project-z…
bugs.chromium.org/p/project-z…
这些漏洞发生在一些特定的信息类中,并且披露的内容超过了它们应该做的。具有讽刺意味的是,一个众所周知的被用作漏洞开发者资源的函数,竟然存在漏洞¯_(ツ)_/¯。
总结
在讨论Windows系统上的漏洞利用时,我再一次试图带来一些信息来设定一个基本的知识。在这个时候,我解释了一点关于这个使用任何无特权用户泄露内核空间信息的重要功能,这种数据对于大多数LPE漏洞来说是最基本的,在解释这个话题的时候不可避免地要讨论。
希望我们在每一篇文章中都能开始让事情变得更加精彩! 再次强调,如果有任何疑问或你想让我知道的事情,请联系我,祝你黑客攻击愉快