πŸ› οΈWindows Kernel Drivers 101 - Creating a Simple Driver

Short Introduction to Windows Software Kernel Driver with Code snippet and example for a basic driver and a User-Mode client.

If you're only interested in the Driver template and Client template you can skip to

#driver-code-template-breakdown

Windows Architecture Refresher

Before you are charts that were taken from "Windows Kernel Development" by Pavel Yosifovich, presented here for a quick representation of the general architecture of Windows OS and the general flow of a System Service Request (Syscall).

Windows Architecture - Taken from "Windows Kernel Programming" by Pavel Yosifovich
System Service Request - Taken from "Windows Kernel Programming" by Pavel Yosifovich

Getting Started with Driver Development

When developing a Driver, you should have remote machine in which you can test the driver, or at the very least have a VM with a snapshot since there is a good chance to crash the system if you're not careful.

Requirements

Frameworks

Common Frameworks for driver development are WDM and KMDF, I will use WDM in this project.

Type of Drivers

Drivers are divided into two types, User-Mode drivers and Kernel-Mode drivers. Within kernel-mode drivers are additional types of drivers in which you can read more about here

The driver template in this page is a simple software driver.

Enable Test Mode

To allow unsigned or self-signed driver to load and execute, use bcdedit.exe

After a successful prompt you will need to reboot the machine.

General Flow of Driver Execution

Driver Initialization

DriverEntry is the Entry point of a Driver, it's the equivalent of a main() of user-mode programs. Most software drivers will be required to do the following actions before the driver can receive requests from clients.

  1. Set unload routine

  2. Set dispatch routines the driver support (e.g. IRP_MJ_CREATE for example)

  3. Create device object -> IoCreateDevice()

  4. Create a symbolic link to the device object -> IoCreateSymbolicLink()

Communication between User-Mode & Kernel-Mode

On a basic level, for a user-mode client to communicate with a driver it needs to:

  1. Open a handle to the device's object -> CreateFile()

  2. Send IO Control Requests -> DeviceIoControl()

The handle we open to the Device object is a handle to it's symbolic link which the Driver created, only using the symbolic link can we get a handle and communicate with the driver.

Driver & Client Template Breakdown

Template

Breakdown

PLACEHOLDER

Testing the Driver

  1. Installing the Driver as a service with sc.exe

2. Starting the service and using Winobj.exe (sysinternals) to verify the symbolic link to the Device was created successfully.

3. Executing the client process that initiates a DeviceIoControl() to the driver and using DebugView.exe (sysinternals) to observe the TRACE messages and verify the data from user-mode passed to the driver.

Generic Notes about Drivers

PLACEHOLDER

References and Additional Read

For actual driver / kernel development I recommend these sources for start:

Last updated

Was this helpful?