免费A级毛片无码专区网站-成人国产精品视频一区二区-啊 日出水了 用力乖乖在线-国产黑色丝袜在线观看下-天天操美女夜夜操美女-日韩网站在线观看中文字幕-AV高清hd片XXX国产-亚洲av中文字字幕乱码综合-搬开女人下面使劲插视频

驅動通信:通過PIPE管道與內核層通信

在本人前一篇博文《驅動開發(fā):通過ReadFile與內核層通信》詳細介紹了如何使用應用層ReadFile系列函數(shù)實現(xiàn)內核通信 , 本篇將繼續(xù)延申這個知識點 , 介紹利用PIPE命名管道實現(xiàn)應用層與內核層之間的多次通信方法 。

  • 什么是PIPE管道?
在Windows編程中 , 數(shù)據(jù)重定向需要用到管道PIPE , 管道是一種用于在進程間共享數(shù)據(jù)的機制 , 通常由兩端組成 , 數(shù)據(jù)從一端流入則必須從令一端流出 , 也就是一讀一寫 , 利用這種機制即可實現(xiàn)進程間直接通信 。管道的本質其實是一段共享內存區(qū)域 , 多數(shù)情況下管道是用于應用層之間的數(shù)據(jù)交換的 , 其實驅動中依然可以使用命名管道實現(xiàn)應用層與內核層的直接通信 。
那么如何在內核中創(chuàng)建一個管道?請看以下代碼片段 , 以及MSDN針對函數(shù)的解析 。
  • InitializeObjectAttributes
    • 初始化一個OBJECT_ATTRIBUTES結構 , 它設置將被打開的對象句柄的屬性 。然后調用方可以將一個指向該結構的指針傳遞給實際打開句柄的例程 。
  • ZwCreateFile
    • 該函數(shù)的作用時創(chuàng)建或打開一個已經存在的文件 , 在這里其實是打開objAttr這個文件 。
  • KeInitializeEvent
    • 將事件對象初始化為同步 (單個服務) 或通知類型事件 , 并將其設置為已發(fā)出信號或未發(fā)出信號的狀態(tài) 。
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文件 , 然后將事件對象初始化為同步狀態(tài) 。
接下來就是如何將數(shù)據(jù)發(fā)送給應用層的問題 , 發(fā)送問題可以調用ZwWriteFile這個內核函數(shù) , 如下我們實現(xiàn)的效果是將一個char類型的字符串傳輸給應用層 。
// 將數(shù)據(jù)傳到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);}// 將數(shù)據(jù)傳到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);// 發(fā)送到應用層ReportToR3(report, 4096);ExFreePool(report);} } DbgPrint("驅動加載成功 \n"); Driver->DriverUnload = UnDriver; return STATUS_SUCCESS;}

經驗總結擴展閱讀