Core concepts
IRCAP is a standalone driver which hooks DispatchDeviceControl
of the target driver.
Implementation
1// ircap/ircap.c
2NTSTATUS
3DriverEntry(
4 _In_ PDRIVER_OBJECT DriverObject,
5 _In_ PUNICODE_STRING RegistryPath
6 )
7{
8 ...
9 ntStatus = PsCreateSystemThread(&threadHandle,
10 THREAD_ALL_ACCESS,
11 NULL,
12 (HANDLE)0,
13 NULL,
14 ThreadIRPHooker,
15 NULL);
16
17 ...
18 KeWaitForSingleObject(threadObject, Executive, KernelMode, FALSE, NULL);
19 ...
20}
It is loaded at boot time and creates a system thread with ThreadIRPHooker
routine.
1// ircap/hook.h
2VOID
3ThreadIRPHooker(
4 _In_ PVOID Context
5)
6{
7 ...
8
9 for (i = 0; i < 10000; i++) {
10 KDPRINTF("[ircap.sys] try hooking (%d) \n", i);
11
12 g_targetDriverObject = GetDriverObjectbyDeviceName(TARGET_DEVICE_NAME);
13 if (g_targetDriverObject)
14 break;
15
16 KeDelayExecutionThread(KernelMode, FALSE, &Time);
17 }
18 ...
19}
This routine first obtains the driver object using GetDriverObjectbyDeviceName
function. To get the driver object, it callsObReferenceObjectByName
function with a device name.
1 // Hook a DispatchDeviceControl function.
2 g_oriDispatchDeviceControl = g_targetDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
3 g_targetDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = hookDispatchDeviceControl;
4
5 InitializeObjectAttributes(&ObjectAttributes, &PROGRAM_FILE_PATH, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
6 ntStatus = ZwCreateFile(&g_handle, GENERIC_WRITE, &ObjectAttributes,
7 &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
8 FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
Then, it overwrites DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
with hookDispatchDeviceControl
function and creates a file to save IRP requests.
1NTSTATUS
2hookDispatchDeviceControl(
3 PDEVICE_OBJECT DeviceObject,
4 PIRP Irp
5)
6
7{
8 ...
9
10 programInfo[0] = irpSp->Parameters.DeviceIoControl.IoControlCode;
11 programInfo[1] = inBufLength;
12 programInfo[2] = outBufLength;
13
14 ZwWriteFile(g_handle, NULL, NULL, NULL, &IoStatusBlock, (PVOID)programInfo, sizeof(programInfo), NULL, NULL);
15 ZwWriteFile(g_handle, NULL, NULL, NULL, &IoStatusBlock, (PVOID)inBuf, inBufLength, NULL, NULL);
16
17 return g_oriDispatchDeviceControl(DeviceObject, Irp);
18}
The hookDispatchDeviceControl
function saves a serialized IRP request to the file and forwards it to the original DispatchDeviceControl
function.