C++ 第一个驱动程序
驱动入口
// NTSTATUS : (LONG) 0~0X7FFFFFFF 正确状态,0X80000000~0XFFFFFFFF 错误状态。参考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55/* PDRIVER_OBJECT : 驱动对象结构体指针 **********************************
typedef struct _DRIVER_OBJECT {CSHORT Type; // ?CSHORT Size; // ?PDEVICE_OBJECT DeviceObject; // 指向设备对象的指针ULONG Flags; // ?PVOID DriverStart; // ?ULONG DriverSize; // ?PVOID DriverSection; // ?PDRIVER_EXTENSION DriverExtension; // 指向驱动程序扩展的指针UNICODE_STRING DriverName; // ?PUNICODE_STRING HardwareDatabase; // 指向注册表 \Registry\Machine\Hardware 路径的指针PFAST_IO_DISPATCH FastIoDispatch; // 指向驱动快速 I/O 入口点结构体指针PDRIVER_INITIALIZE DriverInit; // DriverEntry 入口点指针PDRIVER_STARTIO DriverStartIo; // StartIo 入口点指针PDRIVER_UNLOAD DriverUnload; // Unload 入口点指针PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // IRP(派遣函数) 入口点指针-----------------------------------------------------IRP_MJ_CLEANUP :关闭设备IRP_MJ_CLOSE :关闭文件句柄IRP_MJ_CREATE :打开设备IRP_MJ_DEVICE_CONTROL :对用户模式或内核模式客户程序可用的控制操作IRP_MJ_FILE_SYSTEM_CONTROL :文件系统控制IRP_MJ_FLUSH_BUFFERS :写输入缓冲区或丢弃输入缓冲区IRP_MJ_INTERNAL_DEVICE_CONTROL :内核模式客户程序可用的控制操作IRP_MJ_PNP :即插即用管理IRP_MJ_POWER :电源管理IRP_MJ_QUERY_INFORMATION :得到信息IRP_MJ_READ :读取数据IRP_MJ_SET_INFORMATION :设置信息IRP_MJ_SHUTDOWN :系统关闭IRP_MJ_SYSTEM_CONTROL :系统管理与测试IRP_MJ_WRITE :写数据------------------------------------------------------
} DRIVER_OBJECT, *PDRIVER_OBJECT;
****************************************//* PUNICODE_STRING : Unicode 字符串结构体
typedef struct _UNICODE_STRING {USHORT Length; // 字符串长度USHORT MaximumLength; // 分配给缓冲区的大小PWSTR Buffer; // 指向宽字符串的指针
} UNICODE_STRING, *PUNICODE_STRING;
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath
){// 输出日志DbgPrint("DriverEntry start.");// 指定驱动卸载函数DriverObject->DriverUnload = (PDRIVER_UNLOAD)你的卸载函数;// 指定派遣函数DriverObject->MajorFunction[IRP_MJ_CREATE] = 你的 IRP_MJ_CREATE 派遣函数名DriverObject->MajorFunction[IRP_MJ_CLOSE] = 你的 IRP_MJ_CLOSE 派遣函数名DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 你的 IRP_MJ_DEVICE_CONTROL 派遣函数名// 等等...(如:创建设备)
}
创建设备
/* 设备对象 ********************************
typedef struct _DEVICE_OBJECT {CSHORT Type; // 固定值 3,表示这个对象是一个设备对象USHORT Size; // 设备对象字节大小LONG ReferenceCount; // 相关联的设备被打开的句柄数量struct _DRIVER_OBJECT *DriverObject; // 驱动对象指针struct _DEVICE_OBJECT *NextDevice; // 指向下一个设备对象的指针(属于同一个驱动)struct _DEVICE_OBJECT *AttachedDevice; // 挂载设备指针struct _IRP *CurrentIrp; // 当前IRPPIO_TIMER Timer; // 计时器指针ULONG Flags; // 设备操作类型ULONG Characteristics; // 设备附加信息__volatile PVPB Vpb; // PVOID DeviceExtension;DEVICE_TYPE DeviceType;CCHAR StackSize;union {LIST_ENTRY ListEntry;WAIT_CONTEXT_BLOCK Wcb;} Queue;ULONG AlignmentRequirement;KDEVICE_QUEUE DeviceQueue;KDPC Dpc;ULONG ActiveThreadCount;PSECURITY_DESCRIPTOR SecurityDescriptor;KEVENT DeviceLock;USHORT SectorSize;USHORT Spare1;struct _DEVOBJ_EXTENSION *DeviceObjectExtension;PVOID Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
*********/
NTSTATUS CreateDevice(IN PDRIVER_OBJECT DriverObject){// 定义返回值NTSTATUS status;// 初始化设备名RtlInitUnicodeString(&接收设备名的变量,L"\\Device\\设备名");// 创建设备status = IoCreateDevice(DriverObject, // 指向驱动对象的指针0, // 设备扩展分配的字节数&(UNICODE_STRING)设备名变量, // 设备名FILE_DEVICE_UNKNOWN, // 设备类型,参考:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/kernel/specifying-device-types0, // 驱动设备附加信息TRUE, // 设备对象是否独占设备&(PDEVICE_OBJECT)设备对象变量 // 设备对象指针 );if(!NT_SUCCESS(status)){KdPrint(("IoCreateDevice error."));return status;}// 初始化符号链接名RtlInitUnicodeString(&符号链接名变量,L"\\??\\符号链接名");// 创建符号链接status = IoCreateSymbolicLink(&符号链接名变量,&设备对象变量);if(!NT_SUCCESS(status)){DbgPrint("IoCreateSymbolicLink error.");return status;}return STATUS_SUCCESS;
}
卸载驱动
NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject){// 输出日志DbgPrint("DriverUnload start.");// 删除符号链接IoDeleteSymbolicLink(&符号链接名变量);// 删除设备IoDeleteDevice(设备对象变量);
}
派遣函数
/* _IRP:表示一个 I/O 请求包 ************************
参考:https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp?redirectedfrom=MSDNtypedef struct _IRP {CSHORT Type;USHORT Size;PMDL MdlAddress; // 指向描述用户缓冲区的MDL的指针ULONG Flags;union {struct _IRP *MasterIrp; // 指向IRP中主IRP的指针__volatile LONG IrpCount;PVOID SystemBuffer; // 指向系统空间缓冲区的指针。} AssociatedIrp;LIST_ENTRY ThreadListEntry;IO_STATUS_BLOCK IoStatus; // 驱动程序在调用IoCompleteRequest之前存储状态和信息KPROCESSOR_MODE RequestorMode; // UserMode 或 KernelModeBOOLEAN PendingReturned; // 驱动程序是否已经将IRP标记为pendingCHAR StackCount; CHAR CurrentLocation;BOOLEAN Cancel; // IRP 是否要被取消KIRQL CancelIrql;CCHAR ApcEnvironment;UCHAR AllocationFlags;PIO_STATUS_BLOCK UserIosb;PKEVENT UserEvent;union {struct {union {PIO_APC_ROUTINE UserApcRoutine;PVOID IssuingProcess;};PVOID UserApcContext;} AsynchronousParameters;LARGE_INTEGER AllocationSize;} Overlay;__volatile PDRIVER_CANCEL CancelRoutine; // IRP 取消函数的入口点,NULL 表示 IRP 不会被取消PVOID UserBuffer; // 输出缓冲区union {struct {union {KDEVICE_QUEUE_ENTRY DeviceQueueEntry; struct {PVOID DriverContext[4];};};PETHREAD Thread;PCHAR AuxiliaryBuffer;struct {LIST_ENTRY ListEntry;union {struct _IO_STACK_LOCATION *CurrentStackLocation;ULONG PacketType;};};PFILE_OBJECT OriginalFileObject;} Overlay;KAPC Apc;PVOID CompletionKey;} Tail;
} IRP;
********************************//* IO_STATUS_BLOCK:IRP 调用 IoCompleteRequest 之前 I/O 请求的最终状态 ***
typedef struct _IO_STATUS_BLOCK {union {NTSTATUS Status; // I/O 请求的完成状态,参考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55PVOID Pointer; // 保留} DUMMYUNIONNAME;ULONG_PTR Information; // I/O 请求传输的字节数
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
*****************/// 对应 IRP_MJ_CREATE 、 IRP_MJ_CLOSE
NTSTATUS dpc_CAC(IN PDEVICE_OBJECT pDevObj,IN PIRP pIRP){// 将 IRP 返回给 I/O 管理器IoCompleteRequest(pIRP, // IRP 指针IO_NO_INCREMENT // 线程优先级,IO_NO_INCREMENT :不增加优先级/*IO_NO_INCREMENT 不增加优先级IO_CD_ROM_INCREMENT 光驱设备增加的优先级IO_DISK_INCREMENT 磁盘设备增加的优先级IO_KEYBOARD_INCREMENT 键盘设备增加的优先级IO_MOUSE_INCREMENT 鼠标设备增加的优先级IO_NAMED_PIPE_INCREMENT 命名管道增加的优先级IO_NETWORK_INCREMENT 网络设备增加的优先级IO_PARALLEL_INCREMENT 并口设备增加的优先级IO_SERIAL_INCREMENT 串口设备增加的优先级IO_SOUND_INCREMENT 声卡设备增加的优先级IO_VIDEO_INCREMENT 视频设备增加的优先级SEMAPHORE_INCREMENT 信号灯增加的优先级*/);// 设置 I/O 请求状态pIRP->IoStatus.Status = STATUS_SUCCESS;// 设置 I/O 请求传输的字节数pIRP->IoStatus.Information = 0;return STATUS_SUCCESS;
}// 对应 IRP_MJ_DEVICE_CONTROL
#define IRP_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) // #define 最好放在最上方,我这里为了方便看就放在了这里。
NTSTATUS myIrpControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIRP){// 获取 IRP 对应的 I/O 堆栈指针PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIRP);// 得到输入缓冲区大小ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;// 得到输出缓冲区大小ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;// 得到 IOCTL 码(用于写在下面的 switch 中,避免代码臃肿)ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;// 捕获 I/O 操作类型(MajorFunction)switch (code){case IRP_TEST:// do somethingsdefault:break;}
}
.exe 请求派遣函数
int _tmain(int argc, _TCHAR* argv[])
{// 连接设备HANDLE hDevice = CreateFile(L"\\\\.\\设备符号链接名",GENERIC_READ | GENERIC_WRITE, // 访问设备的方式FILE_SHARE_READ | FILE_SHARE_WRITE, // 设备共享方式NULL, // 保留OPEN_EXISTING, // 如果设备不存在,函数返回失败FILE_ATTRIBUTE_NORMAL, // 设备没有设置其他属性NULL // 保留);if(hDevice == INVALID_HANDLE_VALUE){cout << "CreateFile error : " << GetLastError() << endl;}// 向设备发送 I/O 请求DWORD ReturnLength = 0;DWORD status = DeviceIoControl(hDevice, // 设备句柄CTL_CODE( // 操作控制代码FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS),NULL, // 指向输入缓冲区的指针NULL, // 输入缓冲区大小NULL, // 指向输出缓冲区的指针NULL, // 输出缓冲区大小&ReturnLength, // 必须要有,否则程序卡死NULL // 指向 OVERLAPPED 结构体的指针);getchar();return 0;
}
完整代码
#include UNICODE_STRING name_device; // 设备名
UNICODE_STRING name_symbol; // 符号链接
PDEVICE_OBJECT deviceObj; // 设备对象// 对应 IRP_MJ_DEVICE_CONTROL
NTSTATUS myIrpControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIRP) {// 获取 IRP 对应的 I/O 堆栈指针PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIRP);// 捕获 I/O 操作类型(MajorFunction)switch (stack->MajorFunction) {case IRP_MJ_DEVICE_CONTROL:{// 捕获 I/O 控制码switch (stack->Parameters.DeviceIoControl.IoControlCode) {case CTL_CODE(FILE_DEVICE_UNKNOWN, // 设备类型0x800, // 函数代码,不能大于 4095(推荐使用 0 - 2047)METHOD_BUFFERED, // 访问内存的方式FILE_ANY_ACCESS // 权限): {KdPrint(("应用程序调用了我"));}default:break;}}case IRP_MJ_CREATE:break;case IRP_MJ_CLOSE:break;default:break;}
}// 对应 IRP_MJ_CREATE 、 IRP_MJ_CLOSE
NTSTATUS dpc_CAC(IN PDEVICE_OBJECT pDevObj, IN PIRP pIRP) {// 将 IRP 返回给 I/O 管理器IoCompleteRequest(pIRP, // IRP 指针IO_NO_INCREMENT // 线程优先级,IO_NO_INCREMENT :不增加优先级);// 设置 I/O 请求状态pIRP->IoStatus.Status = STATUS_SUCCESS;// 设置 I/O 请求传输的字节数pIRP->IoStatus.Information = 0;return STATUS_SUCCESS;
}NTSTATUS CreateDevice(IN PDRIVER_OBJECT DriverObject) {// 定义返回值NTSTATUS status;// 初始化设备名RtlInitUnicodeString(&name_device, L"\\Device\\LYSM_device");// 创建设备status = IoCreateDevice(DriverObject, // 指向驱动对象的指针0, // 设备扩展分配的字节数&name_device, // 设备名FILE_DEVICE_UNKNOWN, // 设备类型0, // 驱动设备附加信息TRUE, // 设备对象是否独占设备&deviceObj // 设备对象指针 ); if (!NT_SUCCESS(status)) { KdPrint(("IoCreateDevice error:%X",status));return status;}// 初始化符号链接名RtlInitUnicodeString(&name_symbol, L"\\??\\LYSM_symbol");// 创建符号链接status = IoCreateSymbolicLink(&name_symbol, &name_device);if (!NT_SUCCESS(status)) { DbgPrint("IoCreateSymbolicLink error:%X",status); return status; }return STATUS_SUCCESS;
}NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject) {// 定义返回值NTSTATUS status;// 输出日志DbgPrint("DriverUnload start.");// 删除符号链接status = IoDeleteSymbolicLink(&name_symbol);if (!NT_SUCCESS(status)) {DbgPrint("IoDeleteSymbolicLink error:%X",status); return status; }// 删除设备IoDeleteDevice(deviceObj);return STATUS_SUCCESS;
}extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath
) {// 定义返回值NTSTATUS status;// 输出日志DbgPrint("DriverEntry start.");// 指定驱动卸载函数DriverObject->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;// 指定派遣函数DriverObject->MajorFunction[IRP_MJ_CREATE] = dpc_CAC;DriverObject->MajorFunction[IRP_MJ_CLOSE] = dpc_CAC;DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = myIrpControl;// 创建设备status = CreateDevice(DriverObject);if(!NT_SUCCESS(status)) { DbgPrint("CreateDevice error:%X",status); return status; }return STATUS_SUCCESS;
}

回家打游戏去咯 ε≡٩(๑>₃<)۶
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
