今天来了解一下IRP模块。
IRP
IRP是输入输出请求包(I/O Request Package)的简称
常见的事件有以下几种:
- IRP_MJ_CREATE:请求一个句柄 CreateFile
- IRP_MJ_CLOSE:关闭句柄 CloseHandle
- IRP_MJ_READ:从设备得到数据ReadFile
- IRP_MJ_WRITE:传送数据到设备 WriteFile
- IRP_MJ_DEVICE_CONTROL:控制操作利用IOCTL宏 DeviceIOControl
代码
基本框架
这里注册这个 IRP 事件跟注册卸载驱动函数差不多,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<ntifs.h> #define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)
NTSTATUS DeviceIrpCtl(PDEVICE_OBJECT driver, PIRP pirp) { kprintf(("Line %d:xia0ji233: enter IRP Function\n"), __LINE__); PIO_STACK_LOCATION irpStackL; ULONG CtlCode; ULONG InputBuffLength; irpStackL = IoGetCurrentIrpStackLocation(pirp);
switch (irpStackL->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: { kprintf(("Line %d:xia0ji233: ring3 calls DEVICE CONTROL\n"), __LINE__); break; } case IRP_MJ_CREATE: { kprintf(("Line %d:xia0ji233: ring3 calls CREATE\n"), __LINE__); break; } case IRP_MJ_CLOSE: { kprintf(("Line %d:xia0ji233: ring3 calls CLOSE\n"), __LINE__); break; } default: break; } pirp->IoStatus.Status = STATUS_SUCCESS; pirp->IoStatus.Information = 4; IoCompleteRequest(pirp, IO_NO_INCREMENT); kprintf(("Line %d:xia0ji233: leave IRP Function\n"), __LINE__); return STATUS_SUCCESS; } void DriverUnload(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: unload success\n"),__LINE__); } NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ){ DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceIrpCtl; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceIrpCtl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIrpCtl;
kprintf(("RegistryPath = %S\n"), RegistryPath->Buffer); kprintf(("Line %d:xia0ji233: work success\n"), __LINE__); return 0; }
|
但是这样生成的 sys 被加载之后并不会调用到 IRP 的这个函数,需要 ring3 层去调用对应的函数来触发。
这里可以用一个空宏来忽略局部变量未使用的错误:UNREFERENCED_PARAMETER(p)。
这里需要理解一下两个概念:
- 驱动设备(DEVICE_OBJECT):可以是硬件,也可以是软件。
- 驱动对象(DRIVER_OBJECT):用于创建驱动设备对象的,用于创建多个驱动设备。
反正主要记一下,这俩东西是不一样的。
创建设备代码和符号链接
设备是有名字的,名字遵循变量命名规则。因为在 UNICODE 字符集的环境下,我们先定义一个 UNICODE 字符串,并赋值:
1 2
| UNICODE_STRING MyDriver; RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\xia0ji233");
|
然后创建设备:
1 2 3 4 5 6 7 8 9 10 11 12
| NTSTATUS status; PDEVICE_OBJECT device=NULL; RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\xia0ji233"); status = IoCreateDevice( driver, sizeof(driver->DeviceExtension), &MyDriver, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &device );
|
此时,创建的对象指针返回到了 device 当中,下一步应该创建符号链接,这里可以简单判断一下是否创建成功。
成功之后,可以创建符号链接去,这里的符号链接是给 ring3 的用户层去使用的,而这里创建出来的 Device 只能在内核层使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if (status == STATUS_SUCCESS) { UNICODE_STRING Sym; RtlInitUnicodeString(&Sym, L"\\??\\xia0ji2333"); status = IoCreateSymbolicLink(&Sym, &MyDriver); if (status == STATUS_SUCCESS) { kprintf(("Line %d:xia0ji233: symbol linked success\n"), __LINE__); } else { kprintf(("Line %d:xia0ji233: symbol linked failed status=%x\n"), __LINE__, status); } } else { kprintf(("Line %d:xia0ji233: create device fail status=%x\n"), __LINE__, status); }
|
这里需要注意,创建的符号链接和设备名称不能一样,虽然看别人好像能一样,但是自己一样的话报错了就。
删除设备代码和符号链接
然后再把删除设备和删除符号的一些代码写好,在 unload 例程当中去调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void DriverUnload(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: start unload\n"), __LINE__); DeleteDevice(pDriver); } void DeleteDevice(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: start delete device\n"), __LINE__); if (pDriver->DeviceObject) { UNICODE_STRING Sym; RtlInitUnicodeString(&Sym, L"\\??\\xia0ji2333"); kprintf(("Line %d:xia0ji233: Delete Symbol\n"), __LINE__); IoDeleteSymbolicLink(&Sym); kprintf(("Line %d:xia0ji233: Delete Device\n"), __LINE__); IoDeleteDevice(pDriver->DeviceObject); } kprintf(("Line %d:xia0ji233: end delete device\n"), __LINE__); }
|
三环应用程序
直接像这样,使用 CreateFile 去创建,但是似乎有点问题。
1 2 3 4 5 6 7 8 9
| #include <iostream> #include <Windows.h> #define SYMBOL L"\\\\??\\\\xia0ji2333" int main() { HANDLE DriverHandle = CreateFile(SYMBOL, 0, 0, 0, 0, 0, 0); printf("handle=%x\n", DriverHandle); getchar(); }
|
驱动总代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #include<ntifs.h> #include "main.h" #define SYMBOL L"\\??\\xia0ji2333" #define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)
NTSTATUS CreateDevice(PDEVICE_OBJECT driver) { NTSTATUS status; UNICODE_STRING MyDriver; PDEVICE_OBJECT device = NULL; RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\xia0ji233"); status = IoCreateDevice( driver, sizeof(driver->DeviceExtension), &MyDriver, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &device ); if (status == STATUS_SUCCESS) { UNICODE_STRING Sym; RtlInitUnicodeString(&Sym, SYMBOL); status = IoCreateSymbolicLink(&Sym, &MyDriver); if (status == STATUS_SUCCESS) { kprintf(("Line %d:xia0ji233: symbol linked success\n"), __LINE__); } else { kprintf(("Line %d:xia0ji233: symbol linked failed status=%x\n"), __LINE__, status); } } else { kprintf(("Line %d:xia0ji233: create device fail status=%x\n"), __LINE__, status); } } NTSTATUS DeviceIrpCtl(PDEVICE_OBJECT driver, PIRP pirp) { kprintf(("Line %d:xia0ji233: enter IRP Function\n"), __LINE__); PIO_STACK_LOCATION irpStackL; ULONG CtlCode; ULONG InputBuffLength; irpStackL = IoGetCurrentIrpStackLocation(pirp); switch (irpStackL->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: { kprintf(("Line %d:xia0ji233: ring3 calls DEVICE CONTROL\n"), __LINE__); break; } case IRP_MJ_CREATE: { kprintf(("Line %d:xia0ji233: ring3 calls CREATE\n"), __LINE__); break; } case IRP_MJ_CLOSE: { kprintf(("Line %d:xia0ji233: ring3 calls CLOSE\n"), __LINE__); break; } default: break; } pirp->IoStatus.Status = STATUS_SUCCESS; pirp->IoStatus.Information = 4; IoCompleteRequest(pirp, IO_NO_INCREMENT); kprintf(("Line %d:xia0ji233: leave IRP Function\n"), __LINE__); return STATUS_SUCCESS; }
void DriverUnload(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: start unload\n"), __LINE__); DeleteDevice(pDriver); }
NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ){ DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceIrpCtl; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceIrpCtl; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIrpCtl; CreateDevice(DriverObject); kprintf(("Line %d:xia0ji233: RegistryPath = %S\n"),__LINE__,RegistryPath->Buffer); kprintf(("Line %d:xia0ji233: work success\n"), __LINE__); return 0; }
void DeleteDevice(PDRIVER_OBJECT pDriver) { kprintf(("Line %d:xia0ji233: start delete device\n"), __LINE__); if (pDriver->DeviceObject) { UNICODE_STRING Sym; RtlInitUnicodeString(&Sym, SYMBOL); kprintf(("Line %d:xia0ji233: Delete Symbol\n"), __LINE__); IoDeleteSymbolicLink(&Sym); kprintf(("Line %d:xia0ji233: Delete Device\n"), __LINE__); IoDeleteDevice(pDriver->DeviceObject); } kprintf(("Line %d:xia0ji233: end delete device\n"), __LINE__); }
|
细节明天再看看吧,来看看基本的运行情况: