SpiderLabs Blog

Windows Debugging and Exploiting Part 4: NTQuerySystemInformation

Written by Bruno Oliveira | Mar 2, 2020 11:55:00 PM

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 environmentWinDBG basics and discussed WinDBG Time Travel DebuggingIn 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!