Windows Debugging and Exploiting Part 4: NTQuerySystemInformation
Introduction
Hello again! We are back with more Windows internals and it's time to get real. We already covered how to set up an environment, WinDBG basics and discussed WinDBG Time Travel Debugging. In this part 4 of my blog series, I'll briefly describe an internal API that is widely used to leak kernel information for most of the Windows LPE (Local Privilege Escalation) exploits. We will talk about the function NTQuerySystemInformation.
NTQuerySystemInformation & System Information Classes
The function NTQuerySystemInformation is implemented on NTDLL. And as a kernel API, it is always being updated during the Windows versions with no short notice. As mentioned, this is a private function, so not officially documented by Microsoft. It has been used since early days from Windows NT-family systems with different syscall IDs as you can see on the table below [https://j00ru.vexillium.org/syscalls/nt/64/].
Windows XP to Windows 7 |
Windows 8 & 2012 SP0 |
Windows 8.1 & 2012 R2 |
Windows 10 |
|
NTQuerySystemInformation |
0x0033 |
0x0034 |
0x0035 |
0x0036 |
The function basically retrieves specific information from the environment and its structure is very simple:
NtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
In the first argument, SYSTEM_INFORMATION_CLASS (ULONG) we will set which information we want to retrieve. These classes are named Windows System Information Classes and are defined in winternl.h.
There are numerous data that can be retrieved using these classes along with the function. Information regarding the system, the processes, objects and others.
Below, the list of some classes that could be used:
Note:
- late 5.0 starts with Windows 2000 SP4;
- late 5.1 starts with Windows XP SP2;
- very late 5.1 starts with Windows XP SP3;
- late 5.2 starts with Windows Server 2003 SP1;
- late 6.0 starts with Windows Vista SP1;
- late 6.1 starts with Windows 7 SP1.
Numeric Value |
Symbolic Name |
Versions |
0x00 |
SystemBasicInformation |
3.10 and higher |
0x01 |
SystemProcessorInformation |
3.10 and higher |
0x02 |
SystemPerformanceInformation |
3.10 and higher |
0x03 |
SystemTimeOfDayInformation |
3.10 and higher |
0x04 |
SystemPathInformation |
3.10 and higher |
0x05 |
SystemProcessInformation |
3.10 and higher |
0x06 |
SystemCallCountInformation |
3.10 and higher |
0x07 |
SystemDeviceInformation |
3.10 and higher |
... |
... |
... |
0x40 |
SystemExtendedHandleInformation |
5.1 and higher |
0x41 |
SystemLostDelayedWriteInformation |
5.1 and higher |
0x42 |
unknown |
late 5.1 only |
SystemBigPoolInformation |
5.2 and higher |
|
0x43 |
SystemSessionPoolTagInformation |
5.2 and higher |
0x44 |
SystemSessionMappedViewInformation |
5.2 and higher |
... |
... |
... |
0x58 |
SystemProcessIdInformation |
6.0 and higher |
0x59 |
SystemErrorPortInformation |
6.0 and higher |
0x5A |
SystemBootEnvironmentInformation |
6.0 and higher |
0x5B |
SystemHypervisorInformation |
6.0 and higher |
0x5C |
SystemVerifierInformationEx |
6.0 and higher |
0x5D |
SystemTimeZoneInformation |
6.0 and higher |
0x5E |
SystemImageFileExecutionOptionsInformation |
6.0 and higher |
0x5F |
SystemCoverageInformation |
6.0 and higher |
0x60 |
SystemPrefetchPatchInformation |
6.0 and higher |
... |
... |
... |
0xA8 |
SystemAllowedCpuSetsInformation |
10.0 and higher |
0xA9 |
SystemDmaProtectionInformation |
10.0 and higher |
0xAA |
SystemInterruptCpuSetsInformation |
10.0 and higher |
0xAB |
SystemSecureBootPolicyFullInformation |
10.0 and higher |
0xAC |
SystemCodeIntegrityPolicyFullInformation |
10.0 and higher |
0xAD |
SystemAffinitizedInterruptProcessorInformation |
10.0 and higher |
0xAE |
SystemRootSiloInformation |
10.0 and higher |
... |
... |
... |
0xC7 |
SystemCodeIntegrityVerificationInformation |
1803 and higher |
0xC8 |
SystemFirmwarePartitionInformation |
1803 and higher |
0xC9 |
SystemSpeculationControlInformation |
1803 and higher |
0xCA |
SystemDmaGuardPolicyInformation |
1803 and higher |
0xCB |
SystemEnclaveLaunchControlInformation |
1803 and higher |
Source: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/class.htm?tx=65,67&ts=0,268
Usage
There are multiple information classes that we could use and part of the process, it is to discover which one will be useful in our exploitation method. If we need to discover an EPROCESS or a driver base address, for each one there is a specific class that we could implement. For every class, we will need to define its structures. Some samples:
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];
}
At SYSTEM_MODULE_INFORMATION->ModulesCount[i].ImageBase, you will find the base address of any kernel module. That could be used to calculate the HalDispatchTable for example, using the kernel base address. This table contains function pointers that could be overwritten during exploitation.
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];
}
In this case, at SYSTEM_HANDLE_INFORMATION->Handles[i].Object you may find the address of the object in kernel space from a specific handle that could be filtered by the process ID for example (See Proof-Of-Concept).
These are only two examples of information classes that can be utilized on an exploitation, however there are much more useful classes like SystemExtendedHandledInformation, SystemLockInformation, SystemExtendedProcessInformation, etc.
It is valid to note, that all these structures are undocumented and thanks to the great work from researchers like Mateusz Jurcyzk, Alex Ionescu and others we now have this accurately described.
More information about information classes: https://j00ru.vexillium.org/papers/2011/address_protection.pdf
Proof-Of-Concept
I've developed a simple code to retrieve the open handle addresses from the running process using SystemHandleInformation. I tried to be as simple as possible for your education. So you may want to explore this and others information classes for discovering their functionality and identify what else can be done.
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 source-code available on: https://github.com/bmphx2/PoC-codes/blob/master/NTQuerySystemInformation-PoC.cpp
Checking the address on WinDBG:
lkd> !object 0xFFFFC90441603180
Object: ffffc90441603180 Type: (ffffc904384f8380) File
ObjectHeader: ffffc90441603150 (new version)
HandleCount: 2 PointerCount: 65536
Directory Object: 00000000 Name: \Reference {ConDrv}
Exploitation
This information leak is extremely useful for bypassing the kernel randomization KASLR (Kernel Address Space Layout Randomization). Supposing we already have control in kernel with some write-what-where exploitation primitive, we need to know where exactly we should modify in order to elevate our privileges. By utilizing this API, we are now able to locate multiple objects on the kernel space and calculate offsets for any possible other that we might need. What makes this function very special, is the fact that it can be called by an unprivileged user. In other words, you don't need to be SYSTEM to request internal information from the OS. There are multiple exploits that take advantage of this fact for running. Browsing LPE exploits for Windows is easy to identify. Feel free to do some analysis on your own.
Curiosity
In 2017 and 2018, Google Project Zero found vulnerabilities on NTQuerySystemInformation function itself.
https://bugs.chromium.org/p/project-zero/issues/detail?id=1395
https://bugs.chromium.org/p/project-zero/issues/detail?id=1513
The vulnerabilities occur in some specific information classes and disclose more than they are supposed to do. The irony, a function that is well-known used as a resource for exploit developers, being vulnerable ¯\_(ツ)_/¯.
Conclusion
Once more I tried to bring some information to set a basic knowledge while discussing exploitation on Windows systems. At this time, I explained a little bit about this important function for leaking kernel space information using any unprivileged user, such data is fundamental for most of the LPE exploits, being inevitable to discuss while explaining the topic.
Hopefully, we will start to get things more excited in each post! Again, if there is any doubt or anything that you want me to know, ping me and happy hacking!
ABOUT TRUSTWAVE
Trustwave is a globally recognized cybersecurity leader that reduces cyber risk and fortifies organizations against disruptive and damaging cyber threats. Our comprehensive offensive and defensive cybersecurity portfolio detects what others cannot, responds with greater speed and effectiveness, optimizes client investment, and improves security resilience. Learn more about us.