Obtaining SYSTEM privilege via a vulnerable driver using a Userland program

Note: Article generated by Paper generation AI

Concepts

IOCTL (Input/Output Control) is an interface used by user-mode programs to send commands and data directly to kernel-mode drivers, allowing control or requesting specific operations.

IRPs (I/O Request Packets) are structures used in the kernel to represent and manage I/O operations, including requests sent via IOCTL.

When a user-mode program sends an IOCTL, the kernel converts this request into an IRP, which is delivered to the driver for processing. Thus, IOCTLs are the means of communication, while IRPs are the processing units in the kernel that make this communication functional.

Obtaining SYSTEM Token - Debugging with WinDbg

We will explore how to debug a Windows system using WinDbg to analyze processes, locate the SYSTEM process, and identify the Token field necessary for privilege escalation. Debugging is an essential step in understanding kernel structures and offsets, which is critical when exploiting a vulnerable driver.

1. Setting Up WinDbg for Kernel Debugging

WinDbg is a powerful tool for analyzing both user-mode and kernel-mode processes. To start debugging a system with WinDbg:

  1. Set Up Kernel Debugging:

    • Configure a virtual machine or target machine for kernel debugging.

    • Use a debugging connection method (e.g., network or serial). For example, configure network debugging using:

      bcdedit /debug on
      bcdedit /dbgsettings net hostip:<Windbg_host_debugger_ip> port:50000
    • Launch WinDbg on the host system and connect using:

      Ctrl+K -> Enter the connection string (e.g., `key:port`).
  2. Load Symbols:

    • Ensure that symbols are loaded for the kernel and system modules:

      .sympath srv*c:\symbols*http://msdl.microsoft.com/download/symbols
      .reload

2. Listing Active Processes

To find the SYSTEM process (PID 4), you can list all processes currently running on the system:

  1. Command to Dump Active Processes: Use the !process command:

    This command lists all processes with their addresses, PIDs, and names.

  2. Locate the SYSTEM Process: Look for the process with:

    • PID: 4

    • Name: System

    Example output:

    • The PROCESS structure for SYSTEM is at the address ffff820931a8d040.

3. Analyzing the _EPROCESS Structure

The _EPROCESS structure represents a process in Windows. To manipulate privileges, you need to locate the Token field, which controls access rights.

  1. Dump the _EPROCESS Structure: Use the dt command to display the layout of _EPROCESS:

    Replace <address> with the address of the SYSTEM process (ffff820931a8d040 in this case).

    Example output:

    • The Token field is located at offset 0x4b8.

    • The UniqueProcessId confirms this is the SYSTEM process (PID = 4).

  2. Understanding the Token Field: The Token is an EX_FAST_REF structure that references the process's security token. This token defines the permissions of the process.

4. Validating the Target Process

To ensure that the process at address ffff820931a8d040 is indeed the SYSTEM process, you can use the following checks:

  1. Confirm the Image Name: Use:

    This command outputs details about the process, including the image name (System).

  2. Check the Token Field: Validate that the Token field exists at offset 0x4b8:

    Example output:

    This value represents the pointer to the security token.

5. Mapping This Information to the Vulnerable Driver

Now that the Token offset is identified (0x4b8), you can use it in your driver to perform privilege escalation. The driver can manipulate the Token field of the current process to match the Token of the SYSTEM process, effectively granting SYSTEM privileges.

  • Code snippet for updating the Token:

  • Debugging with WinDbg:

    • Use !process to locate the SYSTEM process (PID 4).

    • Use dt to analyze the _EPROCESS structure and locate the Token field.

  • Key Information:

    • Address of SYSTEM process: ffff820931a8d040

    • Offset of Token field: 0x4b8


Developing the Vulneravel Driver

We will delve into the development of a kernel-mode driver designed to showcase privilege escalation. Each function in the driver is carefully crafted to handle specific tasks, and understanding their purpose and implementation is crucial when working with Windows drivers. Below is a detailed explanation of each function in the driver.

1. DriverEntry

Purpose:

The DriverEntry function is the entry point for a kernel-mode driver. It is invoked when the driver is loaded into memory by the Windows operating system.

Responsibilities:

  • Initialize the driver and its resources.

  • Register the driver’s major functions (e.g., for handling IOCTLs, creating handles).

  • Create a device object to represent the driver in the system.

  • Create a symbolic link for user-mode applications to communicate with the driver.

Code Explanation:

2. DriverUnload

Purpose:

This function is called when the driver is being unloaded. It ensures that all resources allocated by the driver are cleaned up to avoid memory leaks or other issues.

Responsibilities:

  • Delete the symbolic link created during DriverEntry.

  • Delete the device object associated with the driver.

Code Explanation:

3. MajorFunctions

Purpose:

This function handles IRPs (I/O Request Packets) for operations such as creating or closing handles to the device.

Responsibilities:

  • Respond to IRP_MJ_CREATE and IRP_MJ_CLOSE.

  • Log and complete the IRP without performing any specific operation (for simplicity in this example).

Code Explanation:

4. IoControlHandler

Purpose:

This function processes IOCTL (Input/Output Control) requests sent from user-mode applications. It is the key to interacting with the vulnerable functionality of the driver.

Responsibilities:

  • Validate the received IOCTL code.

  • Perform operations based on the IOCTL code (e.g., manipulate the Token field for privilege escalation).

Code Explanation:

5. GetSystemProcess

Purpose:

This helper function retrieves the PEPROCESS structure for the SYSTEM process (PID 4). It is crucial for privilege escalation as it provides access to the Token field of the SYSTEM process.

Responsibilities:

  • Open a handle to the SYSTEM process.

  • Reference the process object to obtain a valid pointer to its PEPROCESS structure.

Code Explanation:

Purpose:

  • IoCreateDevice: Creates the device object that represents the driver in the Windows kernel.

  • IoCreateSymbolicLink: Creates a symbolic link that allows user-mode applications to access the driver.

Code Highlights:

  • IoCreateDevice:

  • IoCreateSymbolicLink:

Key Takeaways

  • DriverEntry: Initializes the driver, creates the device, and registers routines.

  • DriverUnload: Cleans up resources when the driver is unloaded.

  • MajorFunctions: Handles basic operations like opening/closing handles.

  • IoControlHandler: Processes IOCTL requests and performs privilege escalation.

  • GetSystemProcess: Retrieves the PEPROCESS structure for the SYSTEM process.

Source code: https://github.com/CyberSecurityUP/Offensive-Windows-Drivers-Development/blob/main/PrivilegeEscalation/GetSystem/VulnerableDriver/Driver.c


User-Mode Application for Exploiting a Vulnerable Driver

This user-mode application is designed to exploit a kernel-mode driver (VulnerableDriver) by sending a specially crafted IOCTL request to escalate privileges to NT AUTHORITY\SYSTEM. Below is an explanation of the application, how it interacts with the vulnerable driver, and how each part works.

Overview

This program uses the Windows API to:

  1. Open a handle to the vulnerable driver via its symbolic link.

  2. Send a custom IOCTL request (IOCTL_VULNERABLE) to the driver using DeviceIoControl.

  3. Trigger privilege escalation by manipulating the driver's code path.

  4. Open a SYSTEM shell upon successful privilege escalation.

Code Breakdown

1. Define IOCTL Code

The IOCTL_VULNERABLE is a custom-defined code that corresponds to the driver's IOCTL handler:

  • FILE_DEVICE_UNKNOWN: Specifies that the device type is not predefined.

  • 0x800: Function IOCTL code, chosen arbitrarily but must match the driver's code.

  • METHOD_BUFFERED: Indicates the buffering method for input/output data.

  • FILE_ANY_ACCESS: Allows access regardless of the security descriptor.

This code must match the one defined in the vulnerable driver's source.

2. Open a Handle to the Driver

The CreateFileW function opens a handle to the driver's symbolic link (\\.\VulnerableDriverLink), allowing the application to communicate with it:

  • Error Handling:

    • If INVALID_HANDLE_VALUE is returned, GetLastError is used to diagnose the problem:

      • ERROR_ACCESS_DENIED: User lacks the necessary permissions. The program must run as an administrator.

      • ERROR_FILE_NOT_FOUND: The driver is not loaded, or the symbolic link is incorrect.

3. Send the IOCTL Request

Once the handle is obtained, the application sends the IOCTL_VULNERABLE code to the driver using DeviceIoControl:

  • Purpose:

    • The IOCTL_VULNERABLE code instructs the driver to execute its vulnerable functionality (e.g., modifying the Token field for privilege escalation).

  • Error Handling:

    • If DeviceIoControl fails, the error is diagnosed with GetLastError.

Common errors include:

  • ERROR_ACCESS_DENIED: Insufficient permissions.

  • ERROR_INVALID_PARAMETER: Mismatch in input/output buffer sizes or parameters.

  • ERROR_FILE_NOT_FOUND: Driver or device not found.

4. Execute Privilege Escalation

If the IOCTL call succeeds, the driver modifies the Token field of the current process to match the SYSTEM process's Token. This grants the user SYSTEM privileges.

5. Open a SYSTEM Shell

Finally, the application spawns a command shell (cmd.exe) with SYSTEM privileges:

At this point, the user has elevated privileges and full control of the system.

How It Works with the Driver

  1. Driver's Role:

    • The vulnerable driver exposes an IOCTL handler (IoControlHandler) that processes IOCTL_VULNERABLE.

    • When the user-mode application sends the IOCTL, the driver:

      • Accesses the EPROCESS structure of the SYSTEM process (PID 4).

      • Copies the Token field from the SYSTEM process to the current process.

    • This operation effectively grants SYSTEM privileges to the calling process.

  2. Exploitation Process:

    • The user-mode application:

      • Opens a handle to the driver.

      • Sends the custom IOCTL.

    • The driver performs the privilege escalation.

    • The application gains SYSTEM privileges and opens a privileged shell.

Execution Flow

  1. Start the Vulnerable Driver: Load and start the vulnerable driver on the system:

  2. Run the Exploit Application: Execute the compiled user-mode application as an administrator:

  3. Outcome:

    • If successful, the application outputs:

    • A SYSTEM shell (cmd.exe) is opened.

Alternative using OSR Loader

Register Service and Start Service from your driver

Download: https://www.osronline.com/article.cfm%5Earticle=157.htm

Sucessful

Run the UserMode.exe program with the driver initialized and if everything goes well you will obtain the SYSTEM TOKEN

End result is NT/SYSTEM privilege

Key Takeaways

  • The user-mode application exploits the driver's improper validation of IOCTL requests.

  • By sending a crafted IOCTL, it triggers the driver to escalate privileges by modifying the Token field in the current process's EPROCESS structure.

  • This highlights the critical importance of secure IOCTL validation in kernel-mode drivers.

This user-mode application serves as a demonstration of how improperly designed drivers can be exploited, emphasizing the need for secure kernel development practices.

References:

https://www.loldrivers.io/drivers/

https://medium.com/@VL1729_JustAT3ch/just-want-to-talk-to-this-windows-kernel-driver-6642f9d27dc9

https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes

https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/sending-commands-from-userland-to-your-kernel-driver-using-ioctl#defining-custom-ioctl

Last updated