Driver Basics

A Windows driver is a software component that enables communication between hardware devices and the operating system, providing access to device-specific functionality and resources.

Microsoft states that "In the most fundamental sense, a driver is a software component that lets the operating system and a device communicate with each other".

Given this basic definition: As an example, let's consider a scenario where an application requires data from a device. In this case, the application invokes a function provided by the operating system, which in turn invokes a function implemented by the corresponding driver responsible for that device.

Drivers are not as simple as this sense; not all drivers communicate directly with the hardware, and some drivers don't interact with software at all!

Types of Driver

This is over-simplified but there are different types of driver:

  1. A filter driver acts as an intermediary between a device and its associated functional driver, allowing for additional processing or manipulation of data.

  2. A function driver directly interacts with a specific hardware device, providing the necessary functionality and control for the device's operation.

  3. A software driver, also known as a virtual driver, emulates hardware functionality or provides an interface for software components to communicate with the operating system, enabling the use of virtual devices or software-based features.

  4. A bus driver, is a type of driver that manages communication between the computer's central processing unit (CPU) and the various peripheral devices connected to the system bus.

Let's Simplify This

For our purposes, a driver is a software component that operates at the kernel level of the operating system. It acts as an intermediary between user mode applications and the underlying hardware or system functionality.

Drivers have elevated privileges, allowing them to access and control critical resources and perform privileged operations. In fact drivers are loaded as modules within the system process, meaning they run in the context of NT Authority\SYSTEM.

We can target drivers as potential attack vectors due to their privileged position, as compromising a vulnerable driver can lead to gaining kernel level access and possibly executing arbitrary code with high privileges.

High Level Overview

Essentially, a driver is a module that is loaded in to kernel space. Any user mode applications that need to interact with a driver must first obtain a valid handle, this is done via the CreateFile Win32 API:

DriverEntry

The DEVICE_OBJECT is created in the DriverEntry function, this can be thought of as the main function for device drivers. Within the DriverEntry function the developer will create the DEVICE_OBJECT using one of the IoCreateDevice or IoCreateDeviceSecure routines.

These routines create a DEVICE_OBJECT (allocated from nonpaged pool) which serves as a communications channel and handles I/O requests from user mode. I/O requests are made using I/O Request Packets (IRPs).

Note: If the DEVICE_OBJECT is created using IoCreateDeviceSecure a Security Descriptor Definition Language (SDDL) string is provided via the DefaultSDDLString parameter. This is used to control privileged access to the driver.

The Windows I/O Manager is responsible for managing the DEVICE_OBJECT.

Major Functions

In the context of driver development, a Major Function refers to a set of predefined functions or callbacks that a driver must implement to handle different types of I/O operations requested by the operating system.

These functions are associated with specific major I/O control codes (IRP_MJ_* codes) and are responsible for performing various tasks related to device communication and operation.

Each major function corresponds to a specific type of I/O operation, such as reading, writing, device control, or handling PnP (Plug and Play) events. By implementing the major functions, the driver can properly handle the corresponding I/O requests from the operating system.

Dispatch Routines

A dispatch routine refers to a function implemented by a driver to handle specific types of I/O requests or control operations.

Each major function represents a specific type of I/O request or control operation that the driver can handle. The dispatch routine is responsible for implementing the functionality related to a particular major function.

Dispatch routines are the actual functions that handle specific types of I/O requests, and they are associated with major functions that represent those types of requests.

Dispatch routines are written by the driver developer; for example MyDriverWrite in the preceeding diagram.

CreateFile and IRP_MJ_CREATE

In order for a user mode application to communicate with a driver it first needs to call the Win32 API function CreateFile:

HANDLE hDevice = CreateFile(L"\\\\.\\MyDriver", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);

The first parameter is lpFileName, in driver terms this is the symbolic link. If the function call is successful a handle to the driver will be returned.

Depending on how the driver is implemented the user mode application can start sending IRPs to the driver.

Last updated