Secondary Categories: 02-Windows Kernel

There are many ways to interact with a Windows Kernel Driver. The most common way that user application can communicate with kernel drivers is via IRP. There are several very common IRP requests that we can see such as:

  • IRP_MJ_CREATE
  • IRP_MJ_CLOSE
  • IRP_MJ_READ
  • IRP_MJ_WRITE
  • IRP_MJ_DEVICE_CONTROL

At minimum a driver needs to be able to support the create and close IRP. These allow the calling user client to open and close a handle to the driver.

The prototype for the dispatch routine is like so:

NTSTATUS SomeMethod(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp);

An example would look something like so:

NTSTATUS CreateClose(
	_In_ PDEVICE_OBJECT DeviceObject,
	_In_ PIRP Irp
)
{
	UNREFERENCED_PARAMETER(DeviceObject);
	KdPrint(("[+] Hello from CreateClose\n"));
 
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
 
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
	return STATUS_SUCCESS;
}

In our main.cpp we need to create a symbolic link and new device object for user clients to interact with the driver and send IRP’s like so:

#include "driver.h"
 
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDriver");
UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\MyDriver");
 
extern "C"
NTSTATUS
DriverEntry(
	_In_ PDRIVER_OBJECT DriverObject,
	_In_ PUNICODE_STRING RegistryPath
)
{
	NTSTATUS		status;
	PDEVICE_OBJECT	deviceObject;
 
	UNREFERENCED_PARAMETER(RegistryPath);
	KdPrint(("[+] Hello from DriverEntry\n"));
 
	DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE]  = CreateClose;
	DriverObject->DriverUnload = Cleanup;
 
	// create device object
	status = IoCreateDevice(
		DriverObject,
		0,
		&deviceName,
		FILE_DEVICE_UNKNOWN,
		0,
		FALSE,
		&deviceObject
	);
 
	if (!NT_SUCCESS(status)) {
		KdPrint(("[!] IoCreateDevice failed: 0x%08X\n", status));
		return status;
	}
 
	// create symlink
	status = IoCreateSymbolicLink(
		&symLink,
		&deviceName);
 
	if (!NT_SUCCESS(status)) {
		KdPrint(("[!] IoCreateSymbolicLink failed: 0x%08X\n", status));
 
		// delete device object before returning
		IoDeleteDevice(deviceObject);
 
		return status;
	}
 
	return STATUS_SUCCESS;
}

Notice that in the CreateClose function matches the prototype and we also return a STATUS_SUCCESS this is to ensure that we notify the driver that we are done and its memory can be cleaned up.

Resources:

TitleURL
PLACEHOLDER

Also Check Out:

  • PLACE HOLDER