驱动通信:通过PIPE管道与内核层通信
在本人前一篇博文《驱动开发:通过ReadFile与内核层通信》
详细介绍了如何使用应用层ReadFile
系列函数实现内核通信 , 本篇将继续延申这个知识点 , 介绍利用PIPE
命名管道实现应用层与内核层之间的多次通信方法 。
- 什么是PIPE管道?
那么如何在内核中创建一个管道?请看以下代码片段 , 以及MSDN针对函数的解析 。
- InitializeObjectAttributes
- 初始化一个
OBJECT_ATTRIBUTES
结构 , 它设置将被打开的对象句柄的属性 。然后调用方可以将一个指向该结构的指针传递给实际打开句柄的例程 。
- 初始化一个
- ZwCreateFile
- 该函数的作用时创建或打开一个已经存在的文件 , 在这里其实是打开
objAttr
这个文件 。
- 该函数的作用时创建或打开一个已经存在的文件 , 在这里其实是打开
- KeInitializeEvent
- 将事件对象初始化为同步 (单个服务) 或通知类型事件 , 并将其设置为已发出信号或未发出信号的状态 。
HANDLE g_hClient;IO_STATUS_BLOCK g_ioStatusBlock;KEVENT g_event;VOID NdisMSleep(IN ULONGMicrosecondsToSleep);// 初始化管道void init(){ UNICODE_STRING uniName; OBJECT_ATTRIBUTES objAttr; RtlInitUnicodeString(&uniName, L"\\DosDevices\\Pipe\\LySharkPipeConn"); InitializeObjectAttributes(&objAttr, &uniName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ZwCreateFile(&g_hClient, GENERIC_READ | GENERIC_WRITE, &objAttr, &g_ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!g_hClient) {return; } KeInitializeEvent(&g_event, SynchronizationEvent, TRUE);}
原理就是打开\\DosDevices\\Pipe\\LySharkPipeConn
文件 , 然后将事件对象初始化为同步状态 。接下来就是如何将数据发送给应用层的问题 , 发送问题可以调用
ZwWriteFile
这个内核函数 , 如下我们实现的效果是将一个char
类型的字符串传输给应用层 。// 将数据传到R3应用层// LySharkVOID ReportToR3(char* m_parameter, int lent){ if (!NT_SUCCESS(ZwWriteFile(g_hClient, NULL, NULL, NULL, &g_ioStatusBlock, (void*)m_parameter, lent, NULL, NULL))) {DbgPrint("写出错误"); }}
内核层的核心代码就是如上这些 , 将这些整合在一起完整代码如下所示:#include <ntifs.h>#include <ndis.h>#include <stdio.h>HANDLE g_hClient;IO_STATUS_BLOCK g_ioStatusBlock;KEVENT g_event;VOID NdisMSleep(IN ULONGMicrosecondsToSleep);// 初始化管道void init(){ UNICODE_STRING uniName; OBJECT_ATTRIBUTES objAttr; RtlInitUnicodeString(&uniName, L"\\DosDevices\\Pipe\\LySharkPipeConn"); InitializeObjectAttributes(&objAttr, &uniName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ZwCreateFile(&g_hClient, GENERIC_READ | GENERIC_WRITE, &objAttr, &g_ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!g_hClient) {return; } KeInitializeEvent(&g_event, SynchronizationEvent, TRUE);}// 将数据传到R3应用层// LySharkVOID ReportToR3(char* m_parameter, int lent){ if (!NT_SUCCESS(ZwWriteFile(g_hClient, NULL, NULL, NULL, &g_ioStatusBlock, (void*)m_parameter, lent, NULL, NULL))) {DbgPrint("写出错误"); }}VOID UnDriver(PDRIVER_OBJECT driver){ DbgPrint("驱动卸载成功 \n");}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){ init(); // 延时3秒 NdisMSleep(3000000); DbgPrint("hello lyshark \n"); for (int x = 0; x < 10; x++) {// 分配空间char *report = (char*)ExAllocatePoolWithTag(NonPagedPool, 4096, 'lysh');if (report){RtlZeroMemory(report, 4096);RtlCopyMemory(report, "hello lyshark", 13);// 发送到应用层ReportToR3(report, 4096);ExFreePool(report);} } DbgPrint("驱动加载成功 \n"); Driver->DriverUnload = UnDriver; return STATUS_SUCCESS;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- mac通过docker一键部署Jenkins
- 如何通过执行SQL为低代码项目提速?
- 驱动开发:通过ReadFile与内核层通信
- 抖音团购套餐佣金抽成是多少
- 全国计算机等级考试通过率
- 狗狗靠什么辨认主人?
- 驱动精灵重装了驱动后无法开机
- 微粒贷在哪
- 口袋妖怪火红版中如何走精灵塔
- 手相怎么看