驱动通信:通过PIPE管道与内核层通信( 二 )

至此将驱动签名后运行,并迅速打开应用层程序等待同步发送事件,即可得到如下返回结果 。
此处有必要解释一下为什么会写出错误,很简单这段代码并没有控制何时触发事件,导致两边不同步 , 因为只是一个案例用于演示管道的应用方法,所以大家不要太较真,如果不想出错误这段代码还有很多需要改进的地方 。

驱动通信:通过PIPE管道与内核层通信

文章插图
管道不仅可以传输字符串完全可以传输结构体数据,如下我们定义一个Networkreport结构体,并通过管道的方式多次传输给应用层,这部分传输模式适合用于驱动中一次性突出多个结构体,例如进程列表的输出,ARK工具中的驱动列表输出等功能的实现 。
驱动层完整代码
#include <ntifs.h>#include <ndis.h>#include <stdio.h>HANDLE g_hClient;IO_STATUS_BLOCK g_ioStatusBlock;KEVENT g_event;typedef struct{int type;unsigned long address;unsigned long buffer_data_len;char buffer_data[0];}Networkreport;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应用层// PowerBy: LyShark.comVOID ReportToR3(Networkreport* 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++){// 分配空间Networkreport *report = (Networkreport*)ExAllocatePoolWithTag(NonPagedPool, 4096, 'lysh');if (report){RtlZeroMemory(report, 4096);report->type = x;report->address = 401000 + x;report->buffer_data_len = 13;// 定位到结构体最后一个元素上unsigned char * tmp = (unsigned char *)report + sizeof(Networkreport);memcpy(tmp, "hello lyshark", 13);// 发送到应用层ReportToR3(report, 4096);ExFreePool(report);}}DbgPrint("驱动加载成功 \n");Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}应用层完整代码
#include <iostream>#include <windows.h>typedef struct{ int type; unsigned long address; unsigned long buffer_data_len; char *buffer_data;}Networkreport;int main(int argc, char *argv[]){ HANDLE hPipe = CreateNamedPipe(TEXT("\\\\.\\Pipe\\LySharkPipeConn"), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, NULL); if (INVALID_HANDLE_VALUE =https://www.huyubaike.com/biancheng/= hPipe) {return false; } const int size = 1024 * 10; char buf[size]; DWORD rlen = 0; while (true) {//if (ConnectNamedPipe(hPipe, NULL) != NULL)if (1 == 1){if (ReadFile(hPipe, buf, size, &rlen, NULL) == FALSE){continue;}else{//接收信息Networkreport* buffer_tmp = (Networkreport*)&buf;SIZE_T buffer_len = sizeof(Networkreport) + buffer_tmp->buffer_data_len;// 拷贝前半部分,不包括 buffer_dataNetworkreport* buffer = (Networkreport*)malloc(buffer_len);memcpy(buffer, buffer_tmp, buffer_len);// 对后半部 分配空间// By: LySharkchar* data = (char*)malloc(buffer->buffer_data_len);unsigned char* tmp = (unsigned char *)buffer + sizeof(Networkreport) - 4;memcpy(data, tmp, buffer->buffer_data_len);printf("输出数据: %s \n", data);printf("地址: %d \n", buffer_tmp->address);printf("长度: %d \n", buffer_tmp->type);printf("输出长度: %d \n", buffer_tmp->buffer_data_len);free(data);free(buffer);}} } system("pause"); return 0;}结构体一次性输出多个,效果如下所示:
驱动通信:通过PIPE管道与内核层通信

文章插图
【驱动通信:通过PIPE管道与内核层通信】

推荐阅读