国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

驅動開發(fā):通過PIPE管道與內核層通信

這篇具有很好參考價值的文章主要介紹了驅動開發(fā):通過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)建或打開一個已經(jīng)存在的文件,在這里其實是打開 objAttr 這個文件。
  • KeInitializeEvent

    • 將事件對象初始化為同步 (單個服務) 或通知類型事件,并將其設置為已發(fā)出信號或未發(fā)出信號的狀態(tài)。
HANDLE g_hClient;
IO_STATUS_BLOCK g_ioStatusBlock;
KEVENT g_event;

VOID NdisMSleep(IN ULONG  MicrosecondsToSleep);

// 初始化管道
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應用層
// LyShark
VOID 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 ULONG  MicrosecondsToSleep);

// 初始化管道
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應用層
// LyShark
VOID 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;
}

內核中創(chuàng)建了命名管道,客戶端就需要創(chuàng)建一個相同名稱的管道,并通過 ReadFile 函數(shù)讀取管道中的數(shù)據(jù),應用層核心代碼如下所示:

#include <iostream>
#include <windows.h>

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 == hPipe)
	{
		return false;
	}

	const int size = 1024 * 10;
	char buf[size];
	DWORD rlen = 0;
	while (true)
	{
		//if (ConnectNamedPipe(hPipe, NULL) != NULL)
		// PowerBy: LyShark.com
		if (1)
		{
			if (ReadFile(hPipe, buf, size, &rlen, NULL) == FALSE)
			{
				continue;
			}
			else
			{
				//接收信息
				char* buffer_tmp = (char*)&buf;

				// 拷貝前半部分,不包括 buffer_data
				char* buffer = (char*)malloc(size);
				memcpy(buffer, buffer_tmp, size);

				printf("內核層數(shù)據(jù): %s \n", buffer);

				free(buffer_tmp);
				free(buffer);
			}
		}
	}

	system("pause");
	return 0;
}

至此將驅動簽名后運行,并迅速打開應用層程序等待同步發(fā)送事件,即可得到如下返回結果。

此處有必要解釋一下為什么會寫出錯誤,很簡單這段代碼并沒有控制何時觸發(fā)事件,導致兩邊不同步,因為只是一個案例用于演示管道的應用方法,所以大家不要太較真,如果不想出錯誤這段代碼還有很多需要改進的地方。

管道不僅可以傳輸字符串完全可以傳輸結構體數(shù)據(jù),如下我們定義一個 Networkreport 結構體,并通過管道的方式多次傳輸給應用層,這部分傳輸模式適合用于驅動中一次性突出多個結構體,例如進程列表的輸出,ARK工具中的驅動列表輸出等功能的實現(xiàn)。

驅動層完整代碼

#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 ULONG  MicrosecondsToSleep);

// 初始化管道
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應用層
// PowerBy: LyShark.com
VOID 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);

      // 發(fā)送到應用層
      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 == 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_data
				Networkreport* buffer = (Networkreport*)malloc(buffer_len);
				memcpy(buffer, buffer_tmp, buffer_len);

				// 對后半部 分配空間
				// By: LyShark
				char* data = (char*)malloc(buffer->buffer_data_len);
				unsigned char* tmp = (unsigned char *)buffer + sizeof(Networkreport) - 4;
				memcpy(data, tmp, buffer->buffer_data_len);

				printf("輸出數(shù)據(jù): %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;
}

結構體一次性輸出多個,效果如下所示: 文章來源地址http://www.zghlxwxcb.cn/news/detail-828422.html

到了這里,關于驅動開發(fā):通過PIPE管道與內核層通信的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 在windows通過VS Code開發(fā)Linux內核驅動程序

    在windows通過VS Code開發(fā)Linux內核驅動程序

    最近在看Linux設備驅動程序第三版,為了在windows系統(tǒng)上練手操作,先是下載VMware Workstation安裝了Linux系統(tǒng)虛擬機。然后在vscode上編寫簡單的示例程序,通過ftp把源文件發(fā)送到Linux虛擬機后,再在虛擬機上make編譯測試內核驅動程序。這樣即使是在內核日志中打印個簡單的hello w

    2024年02月06日
    瀏覽(35)
  • 驅動開發(fā):通過應用堆實現(xiàn)多次通信

    驅動開發(fā):通過應用堆實現(xiàn)多次通信

    在前面的文章 《驅動開發(fā):運用MDL映射實現(xiàn)多次通信》 LyShark教大家使用 MDL 的方式靈活的實現(xiàn)了內核態(tài)多次輸出結構體的效果,但是此種方法并不推薦大家使用原因很簡單首先內核空間比較寶貴,其次內核里面不能分配太大且每次傳出的結構體最大不能超過 1024 個,而最終

    2024年02月05日
    瀏覽(33)
  • 驅動開發(fā):通過MDL映射實現(xiàn)多次通信

    驅動開發(fā):通過MDL映射實現(xiàn)多次通信

    在前幾篇文章中 LyShark 通過多種方式實現(xiàn)了驅動程序與應用層之間的通信,這其中就包括了通過運用 SystemBuf 緩沖區(qū)通信,運用 ReadFile 讀寫通信,運用 PIPE 管道通信,以及運用 ASYNC 反向通信,這些通信方式在應對 一收一發(fā) 模式的時候效率極高,但往往我們需要實現(xiàn)一次性吐

    2024年02月01日
    瀏覽(16)
  • NestJs 管道(Pipe)

    NestJs 管道(Pipe)

    ??Hi~ 大家好,我是小鑫同學,資深 IT 從業(yè)者,InfoQ 的簽約作者,擅長前端開發(fā)并在這一領域有多年的經(jīng)驗,致力于分享我在技術方面的見解和心得 我在 94Code 總結技術學習; 我在 1024Code 在線編寫代碼; 我在 Github 參與開源學習; var-conv 適用于VSCode IDE的代碼變量名稱快速轉

    2024年02月09日
    瀏覽(21)
  • 【IMX6ULL驅動開發(fā)學習】10.設置uboot,通過tftp服務器加載內核與設備樹,通過nfs掛載根文件系統(tǒng)

    【IMX6ULL驅動開發(fā)學習】10.設置uboot,通過tftp服務器加載內核與設備樹,通過nfs掛載根文件系統(tǒng)

    首先根據(jù)這篇博客,保證自己的開發(fā)板與Ubuntu主機處于同一個網(wǎng)段,并且可以ping通 【IMX6ULL驅動開發(fā)學習】03.設置IMX6ULL開發(fā)板與虛擬機在同一網(wǎng)段 1. 在uboot中設置網(wǎng)絡 首先啟動自己的板子進入Linux系統(tǒng),使用 ifconfig 命令或者 ifconfig -a 命令查看自己網(wǎng)卡的地址 我的網(wǎng)卡地址是

    2024年02月05日
    瀏覽(29)
  • Angular中的管道(pipe)如何使用?

    在Angular中,管道(Pipes)是用于在模板中轉換數(shù)據(jù)顯示的工具。它們用于格式化、過濾、排序等操作,以便將數(shù)據(jù)以更易讀或更有意義的方式呈現(xiàn)給用戶。 1、使用Angular內置管道: 假設我們有一個顯示日期的組件,并且我們想要在模板中格式化這個日期。我們可以使用Angul

    2024年02月02日
    瀏覽(24)
  • java.io.IOException: Broken pipe管道斷開

    一、Broken pipe產(chǎn)生原因分析 1.當訪問某個服務突然服務器掛了,就會產(chǎn)生Broken pipe; 2.客戶端讀取超時關閉了連接,這時服務器往客戶端再寫數(shù)據(jù)就發(fā)生了broken pipe異常! 3.端口沖突,地址已被使用,也會導致Broken pipe 二、方案 1.問題一分析服務器為什么掛了。 2.問題二使用jp

    2024年02月10日
    瀏覽(17)
  • Windows驅動(用戶層R3與內核層R0通信)

    Windows驅動(用戶層R3與內核層R0通信)

    內存空間分為用戶層和系統(tǒng)層,普通的應用程序只能運行在用戶層,為了可以操作系統(tǒng)層的內存 所以引入了驅動程序,有了驅動就可以通過用戶層來操作系統(tǒng)層的內存及函數(shù),所以驅動就是應用層和系統(tǒng)層之間的一個橋梁 在應用層通過創(chuàng)建符號鏈接,自動產(chǎn)生驅動層的IRP事

    2024年02月14日
    瀏覽(18)
  • linux驅動開發(fā)--day1(驅動、內核模塊及相關命令、內核模塊傳參)
  • Linux驅動開發(fā)——內核模塊

    Linux驅動開發(fā)——內核模塊

    目錄 內核模塊的由來 第一個內核模塊程序? 內核模塊工具? 將多個源文件編譯生成一個內核模塊? 內核模塊參數(shù) 內核模塊依賴 關于內核模塊的進一步討論? 習題 最近一直在玩那些其它的技術,眼看快暑假了,我決定夯實一下我的驅動方面的技能,迎接我的實習,找了一本

    2024年02月04日
    瀏覽(100)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包