最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言驅(qū)動(dòng)開發(fā)之通過ReadFile與內(nèi)核層通信

 更新時(shí)間:2022年09月30日 16:32:37   作者:lyshark  
驅(qū)動(dòng)與應(yīng)用程序的通信是非常有必要的,內(nèi)核中執(zhí)行代碼后需要將其動(dòng)態(tài)顯示給應(yīng)用層。為了實(shí)現(xiàn)內(nèi)核與應(yīng)用層數(shù)據(jù)交互則必須有通信的方法,微軟為我們提供了三種通信方式,本文先來介紹通過ReadFile系列函數(shù)實(shí)現(xiàn)的通信模式

驅(qū)動(dòng)與應(yīng)用程序的通信是非常有必要的,內(nèi)核中執(zhí)行代碼后需要將其動(dòng)態(tài)顯示給應(yīng)用層,但驅(qū)動(dòng)程序與應(yīng)用層畢竟不在一個(gè)地址空間內(nèi),為了實(shí)現(xiàn)內(nèi)核與應(yīng)用層數(shù)據(jù)交互則必須有通信的方法,微軟為我們提供了三種通信方式,如下先來介紹通過ReadFile系列函數(shù)實(shí)現(xiàn)的通信模式。

長(zhǎng)話短說,不說沒用的概念,首先系統(tǒng)中支持的通信模式可以總結(jié)為三種。

  • 緩沖區(qū)方式讀寫(DO_BUFFERED_IO)
  • 直接方式讀寫(DO_DIRECT_IO)
  • 其他方式讀寫

而通過ReadFile,WriteFile系列函數(shù)實(shí)現(xiàn)的通信機(jī)制則屬于緩沖區(qū)通信模式,在該模式下操作系統(tǒng)會(huì)將應(yīng)用層中的數(shù)據(jù)復(fù)制到內(nèi)核中,此時(shí)應(yīng)用層調(diào)用ReadFile,WriteFile函數(shù)進(jìn)行讀寫時(shí),在驅(qū)動(dòng)內(nèi)會(huì)自動(dòng)觸發(fā) IRP_MJ_READ 與 IRP_MJ_WRITE這兩個(gè)派遣函數(shù),在派遣函數(shù)內(nèi)則可以對(duì)收到的數(shù)據(jù)進(jìn)行各類處理。

首先需要實(shí)現(xiàn)初始化各類派遣函數(shù)這么一個(gè)案例,如下代碼則是通用的一種初始化派遣函數(shù)的基本框架,分別處理了IRP_MJ_CREATE創(chuàng)建派遣,以及IRP_MJ_CLOSE關(guān)閉的派遣,此外函數(shù)DriverDefaultHandle的作用時(shí)初始化其他派遣用的,也就是將除去CREATE/CLOSE這兩個(gè)派遣之外,其他的全部賦值成初始值的意思,當(dāng)然不增加此段代碼也是無妨,并不影響代碼的實(shí)際執(zhí)行。

#include <ntifs.h>

// 卸載驅(qū)動(dòng)執(zhí)行
VOID UnDriver(PDRIVER_OBJECT pDriver)
{
	PDEVICE_OBJECT pDev;                                        // 用來取得要?jiǎng)h除設(shè)備對(duì)象
	UNICODE_STRING SymLinkName;                                 // 局部變量symLinkName
	pDev = pDriver->DeviceObject;
	IoDeleteDevice(pDev);                                           // 調(diào)用IoDeleteDevice用于刪除設(shè)備
	RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver");     // 初始化字符串將symLinkName定義成需要?jiǎng)h除的符號(hào)鏈接名稱
	IoDeleteSymbolicLink(&SymLinkName);                             // 調(diào)用IoDeleteSymbolicLink刪除符號(hào)鏈接
	DbgPrint("驅(qū)動(dòng)卸載完畢...");
}

// 創(chuàng)建設(shè)備連接
// LyShark.com
NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
	NTSTATUS Status;
	PDEVICE_OBJECT pDevObj;
	UNICODE_STRING DriverName;
	UNICODE_STRING SymLinkName;

	// 創(chuàng)建設(shè)備名稱字符串
	RtlInitUnicodeString(&DriverName, L"\\Device\\LySharkDriver");
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);

	// 指定通信方式為緩沖區(qū)
	pDevObj->Flags |= DO_BUFFERED_IO;

	// 創(chuàng)建符號(hào)鏈接
	RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver");
	Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
	return STATUS_SUCCESS;
}

// 創(chuàng)建回調(diào)函數(shù)
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數(shù) IRP_MJ_CREATE 執(zhí)行 \n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功
}

// 關(guān)閉回調(diào)函數(shù)
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數(shù) IRP_MJ_CLOSE 執(zhí)行 \n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功
}

// 默認(rèn)派遣函數(shù)
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}

// 入口函數(shù)
// By: LyShark
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark \n");

	// 調(diào)用創(chuàng)建設(shè)備
	CreateDriverObject(pDriver);

	pDriver->DriverUnload = UnDriver;                          // 卸載函數(shù)
	pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 創(chuàng)建派遣函數(shù)
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 關(guān)閉派遣函數(shù)

	// 初始化其他派遣
	for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		DbgPrint("初始化派遣: %d \n", i);
		pDriver->MajorFunction[i] = DriverDefaultHandle;
	}

	DbgPrint("驅(qū)動(dòng)加載完成...");

	return STATUS_SUCCESS;
}

代碼運(yùn)行效果如下:

通用框架有了,接下來就是讓該驅(qū)動(dòng)支持使用ReadWrite的方式實(shí)現(xiàn)通信,首先我們需要在DriverEntry處增加兩個(gè)派遣處理函數(shù)的初始化。

// 入口函數(shù)
// By: LyShark
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark \n");

	// 調(diào)用創(chuàng)建設(shè)備
	CreateDriverObject(pDriver);

	// 初始化其他派遣
	for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		DbgPrint("初始化派遣: %d \n", i);
		pDriver->MajorFunction[i] = DriverDefaultHandle;
	}

	pDriver->DriverUnload = UnDriver;                          // 卸載函數(shù)
	pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 創(chuàng)建派遣函數(shù)
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 關(guān)閉派遣函數(shù)

	// 增加派遣處理
	pDriver->MajorFunction[IRP_MJ_READ] = DispatchRead;        // 讀取派遣函數(shù)
	pDriver->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;      // 寫入派遣函數(shù)

	DbgPrint("驅(qū)動(dòng)加載完成...");

	return STATUS_SUCCESS;
}

接著,我們需要分別實(shí)現(xiàn)這兩個(gè)派遣處理函數(shù),如下DispatchRead負(fù)責(zé)讀取時(shí)觸發(fā),與之對(duì)應(yīng)DispatchWrite負(fù)責(zé)寫入觸發(fā)。

  • 引言:
  • 對(duì)于讀取請(qǐng)求I/O管理器分配一個(gè)與用戶模式的緩沖區(qū)大小相同的系統(tǒng)緩沖區(qū)SystemBuffer,當(dāng)完成請(qǐng)求時(shí)I/O管理器將驅(qū)動(dòng)程序已經(jīng)提供的數(shù)據(jù)從系統(tǒng)緩沖區(qū)復(fù)制到用戶緩沖區(qū)。
  • 對(duì)于寫入請(qǐng)求,會(huì)分配一個(gè)系統(tǒng)緩沖區(qū)并將SystemBuffer設(shè)置為地址,用戶緩沖區(qū)的內(nèi)容會(huì)被復(fù)制到系統(tǒng)緩沖區(qū),但是不設(shè)置UserBuffer緩沖。

通過IoGetCurrentIrpStackLocation(pIrp)接收讀寫請(qǐng)求長(zhǎng)度,偏移等基本參數(shù),AssociatedIrp.SystemBuffer則是讀寫緩沖區(qū),IoStatus.Information是輸出緩沖字節(jié)數(shù),Parameters.Read.Length是讀取寫入的字節(jié)數(shù)。

// 讀取回調(diào)函數(shù)
NTSTATUS DispatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(pIrp);
	ULONG ulReadLength = Stack->Parameters.Read.Length;

	char szBuf[128] = "hello lyshark";

	pIrp->IoStatus.Status = Status;
	pIrp->IoStatus.Information = ulReadLength;
	DbgPrint("讀取長(zhǎng)度:%d \n", ulReadLength);

	// 取出字符串前5個(gè)字節(jié)返回給R3層
	memcpy(pIrp->AssociatedIrp.SystemBuffer, szBuf, ulReadLength);

	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return Status;
}

// 接收傳入回調(diào)函數(shù)
// By: LyShark
NTSTATUS DispatchWrite(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
	ULONG ulWriteLength = Stack->Parameters.Write.Length;
	PVOID ulWriteData = Irp->AssociatedIrp.SystemBuffer;

	// 輸出傳入字符串
	DbgPrint("傳入長(zhǎng)度: %d 傳入數(shù)據(jù): %s \n", ulWriteLength, ulWriteData);

	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return Status;
}

如上部分都是在講解驅(qū)動(dòng)層面的讀寫派遣,應(yīng)用層還沒有介紹,在應(yīng)用層我們只需要調(diào)用ReadFile函數(shù)當(dāng)調(diào)用該函數(shù)時(shí)驅(qū)動(dòng)中會(huì)使用DispatchRead派遣例程來處理這個(gè)請(qǐng)求,同理調(diào)用WriteFile函數(shù)則觸發(fā)的是DispatchWrite派遣例程。

我們首先從內(nèi)核中讀出前五個(gè)字節(jié)并放入緩沖區(qū)內(nèi),輸出該緩沖區(qū)內(nèi)的數(shù)據(jù),然后在調(diào)用寫入,將hello lyshark寫回到內(nèi)核里里面,這段代碼可以這樣來寫。

#include <iostream>
#include <Windows.h>
#include <winioctl.h>

int main(int argc, char *argv[])
{
  HANDLE hDevice = CreateFileA("\\\\.\\LySharkDriver", GENERIC_READ | GENERIC_WRITE, 0,
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hDevice == INVALID_HANDLE_VALUE)
  {
    CloseHandle(hDevice);
    return 0;
  }

  // 從內(nèi)核讀取數(shù)據(jù)到本地
  char buffer[128] = { 0 };
  ULONG length;

  // 讀入到buffer長(zhǎng)度為5
  // By:lyshark.com
  ReadFile(hDevice, buffer, 5, &length, 0);
  for (int i = 0; i < (int)length; i++)
  {
    printf("讀取字節(jié): %c", buffer[i]);
  }

  // 寫入數(shù)據(jù)到內(nèi)核
  char write_buffer[128] = "hello lyshark";
  ULONG write_length;
  WriteFile(hDevice, write_buffer, strlen(write_buffer), &write_length, 0);

  system("pause");
  CloseHandle(hDevice);
  return 0;
}

使用驅(qū)動(dòng)工具安裝我們的驅(qū)動(dòng),然后運(yùn)行該應(yīng)用層程序,實(shí)現(xiàn)通信,效果如下所示:

到此這篇關(guān)于C語言驅(qū)動(dòng)開發(fā)之通過ReadFile與內(nèi)核層通信的文章就介紹到這了,更多相關(guān)C語言 ReadFile內(nèi)核層通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言中計(jì)算字符串長(zhǎng)度與分割字符串的方法

    C語言中計(jì)算字符串長(zhǎng)度與分割字符串的方法

    這篇文章主要介紹了C語言中計(jì)算字符串長(zhǎng)度與分割字符串的方法,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-08-08
  • C++數(shù)據(jù)結(jié)構(gòu)鏈表基本操作示例過程

    C++數(shù)據(jù)結(jié)構(gòu)鏈表基本操作示例過程

    這篇文章主要為大家介紹了C++數(shù)據(jù)結(jié)構(gòu)鏈表基本操作的示例過程有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • 圖文詳解C語言位運(yùn)算基礎(chǔ)知識(shí)

    圖文詳解C語言位運(yùn)算基礎(chǔ)知識(shí)

    這篇文章主要以圖文結(jié)合的方式為大家詳細(xì)介紹了C語言位運(yùn)算基礎(chǔ)知識(shí),感興趣的小伙伴們可以參考一下
    2016-07-07
  • C++ Boost Archive超詳細(xì)講解

    C++ Boost Archive超詳細(xì)講解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱
    2022-12-12
  • C++中的static和const的關(guān)鍵字用法詳解

    C++中的static和const的關(guān)鍵字用法詳解

    這篇文章主要介紹了C++中的static和const的關(guān)鍵字用法詳解,這是一道經(jīng)常在面試中被問到的知識(shí),本文給大家詳細(xì)介紹下,需要的朋友可以參考下
    2023-06-06
  • C語言指針和數(shù)組深入探究使用方法

    C語言指針和數(shù)組深入探究使用方法

    在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-08-08
  • C++?boost?thread庫用法詳細(xì)講解

    C++?boost?thread庫用法詳細(xì)講解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個(gè)可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱
    2022-11-11
  • C++關(guān)于字符的接收與輸出操作示例

    C++關(guān)于字符的接收與輸出操作示例

    這篇文章主要介紹了C++關(guān)于字符的接收與輸出操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01
  • C語言指針入門學(xué)習(xí)面面觀

    C語言指針入門學(xué)習(xí)面面觀

    這篇文章主要介紹了C語言指針的一些基礎(chǔ)知識(shí),指針可以說是C語言入門學(xué)習(xí)中的頭等大事,文中從數(shù)組和函數(shù)等多方面剖析C中指針的作用,需要的朋友可以參考下
    2016-02-02
  • C++序列操作函數(shù)學(xué)習(xí)最全指南

    C++序列操作函數(shù)學(xué)習(xí)最全指南

    這篇文章主要給大家介紹了關(guān)于C++序列操作函數(shù)學(xué)習(xí)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02

最新評(píng)論

永泰县| 梧州市| 长阳| 花垣县| 垫江县| 松溪县| 绥阳县| 天镇县| 东辽县| 延吉市| 桂平市| 沙坪坝区| 普兰店市| 昌图县| 荣成市| 阿克苏市| 阿巴嘎旗| 密云县| 英吉沙县| 建湖县| 信阳市| 武山县| 新宾| 固原市| 乌什县| 阳谷县| 桃江县| 龙海市| 舞钢市| 营口市| 瑞丽市| 永安市| 东台市| 吉隆县| 武隆县| 铁岭县| 汉寿县| 永昌县| 东至县| 哈巴河县| 获嘉县|