驅動通信:驅動與應用的通信


驅動程序與應用程序的通信離不開派遣函數,派遣函數是Windows驅動編程中的重要概念,一般情況下驅動程序負責處理I/O特權請求,而大部分IO的處理請求是在派遣函數中處理的,當用戶請求數據時,操作系統會提前處理好請求,並將其派遣到指定的內核函數中執行,接下來將詳細說明派遣函數的使用並通過派遣函數讀取Shadow SSDT中的內容。

先來簡單介紹一下 IRP(I/O Request Package) 輸入輸出請求包,該請求包在Windows內核中是一個非常重要的數據結構,當我們的上層應用與底層的驅動程序通信時,應用程序就會發出I/O請求,操作系統將該請求轉化為相應的IRP數據,然后會根據不同的請求數據將請求派遣到相應的驅動函數中執行,這一點有點類似於Windows的消息機制。

創建設備對象: 在使用派遣函數的之前需要創建設備對象,因為后期的讀寫都要通過設備對象來連接。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
	PDEVICE_OBJECT pDev;         // 用來取得要刪除設備對象
	UNICODE_STRING SymLinkName;  // 局部變量symLinkName

	//刪掉所有設備
	pDev = pDriver->DeviceObject;
	IoDeleteDevice(pDev);                                       // 調用IoDeleteDevice用於刪除設備
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");  	// 初始化字符串將symLinkName定義成需要刪除的符號鏈接名稱
	IoDeleteSymbolicLink(&SymLinkName);	                        // 調用IoDeleteSymbolicLink刪除符號鏈接
	DbgPrint("刪除設備與符號鏈接成功...");
}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
	NTSTATUS Status;               // 接收驅動程序的返回狀態
	PDEVICE_OBJECT pDevObj;        // 用於返回創建設備
	UNICODE_STRING DriverName;     // 用於存放設備的名稱
	UNICODE_STRING SymLinkName;    // 用於存放符號鏈接名稱

	RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");  // 將DrvierName填充為\\Device\\My_Device

	// 使用命令IoCreateDevice用來創建設備,並將創建后的狀態保存在status
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
	DbgPrint("當前命令IoCreateDevice狀態: %d", Status);
	if (!NT_SUCCESS(Status))
	{
		// 調用IoCreateDevice成功與失敗都會返回參數,將返回參數給Status用於判斷
		// STATUS_INSUFFICIENT_RESOURCES   資源不足
		// STATUS_OBJECT_NAME_EXISTS       指定對象名存在
		// STATUS_OBJECT_NAME_COLLISION    對象名有沖突
		if (Status == STATUS_OBJECT_NAME_COLLISION)
		{
			DbgPrint("對象名沖突..");
		}
		DbgPrint("創建失敗.");
	}

	pDevObj->Flags |= DO_BUFFERED_IO;                            // flags 標識有沒有do_buffered_io位標識
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");      // 對symLinkName初始化字串為 "\\??\\My_Device"
	// 創建設備鏈接,驅動程序雖然有設備名稱,但是這種設備名只能在內核態可見
	// 而對於應用程序是不可見的,因此驅動需要要暴露一個符號鏈接,該鏈接指向真正的設備名稱
	Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);    // 調用命令IoCreateSymbolicLink用於創建符號鏈接
	DbgPrint("當前命令IoCreateSymbolicLink狀態: %d", Status);
	if (!NT_SUCCESS(Status)) // 如果status不等於0 就執行
	{
		IoDeleteDevice(pDevObj);  // 調用命令IoDeleteDevice刪除當前pDevObj設備
		DbgPrint("刪除設備成功...");
		return Status;
	}
	else
	{
		DbgPrint("創建符號鏈接成功...");
	}
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	CreateDriverObject(pDriver);
	pDriver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

簡單的驅動通信: 注冊兩個派遣函數,當設備創建的時候觸發,以及關閉時觸發。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
	PDEVICE_OBJECT pDev;         // 用來取得要刪除設備對象
	UNICODE_STRING SymLinkName;  // 局部變量symLinkName

	pDev = pDriver->DeviceObject;
	IoDeleteDevice(pDev);                                       // 調用IoDeleteDevice用於刪除設備
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");  	// 初始化字符串將symLinkName定義成需要刪除的符號鏈接名稱
	IoDeleteSymbolicLink(&SymLinkName);	                        // 調用IoDeleteSymbolicLink刪除符號鏈接
	DbgPrint("刪除設備與符號鏈接成功...");
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數 IRP_MJ_CREATE 成功執行 !\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數 IRP_MJ_CLOSE 成功執行 !\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功

}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
	NTSTATUS Status;
	PDEVICE_OBJECT pDevObj;
	UNICODE_STRING DriverName;
	UNICODE_STRING SymLinkName;

	RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
	DbgPrint("命令 IoCreateDevice 狀態: %d", Status);

	// DO_BUFFERED_IO 設置讀寫方式 Flags的三個不同的值分別為:DO_BUFFERED_IO、DO_DIRECT_IO和0
	pDevObj->Flags |= DO_BUFFERED_IO;
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");
	Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
	DbgPrint("當前命令IoCreateSymbolicLink狀態: %d", Status);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	CreateDriverObject(pDriver);           // 調用創建設備子過程
	// 注冊兩個派遣函數,分別對應創建與關閉,派遣函數名可自定義
	pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 創建成功派遣函數
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 關閉派遣函數

	DbgPrint("驅動加載完成...");
	pDriver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

客戶端代碼

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

int main()
{
	HANDLE hDevice = CreateFile(L"\\\\.\\My_Device", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hDevice == INVALID_HANDLE_VALUE) //判斷hDevice返回值是否為空
	{
		printf("獲取驅動句柄失敗!錯誤: %d\n", GetLastError());
		getchar();
	}

	getchar();
	CloseHandle(hDevice);
	return 0;
}

讀取驅動中的數據: 實現讀取內核緩沖區中的數據,並打印出來。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
	PDEVICE_OBJECT pDev;         // 用來取得要刪除設備對象
	UNICODE_STRING SymLinkName;  // 局部變量symLinkName
	pDev = pDriver->DeviceObject;
	IoDeleteDevice(pDev);                                       // 調用IoDeleteDevice用於刪除設備
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");     // 初始化字符串將symLinkName定義成需要刪除的符號鏈接名稱
	IoDeleteSymbolicLink(&SymLinkName);                         // 調用IoDeleteSymbolicLink刪除符號鏈接
	DbgPrint("刪除設備與符號鏈接成功...");
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數 IRP_MJ_CREATE 成功執行 !\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
	DbgPrint("派遣函數 IRP_MJ_CLOSE 成功執行 !\n");
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
	return STATUS_SUCCESS;                           // 返回成功
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(pIrp);
	ULONG ulReadLength = Stack->Parameters.Read.Length;
	pIrp->IoStatus.Status = Status;
	pIrp->IoStatus.Information = ulReadLength;
	DbgPrint("應用要讀取的長度:%d\n", ulReadLength);

	// 將內核中的緩沖區全部填充為0x68 方便演示讀取的效果
	memset(pIrp->AssociatedIrp.SystemBuffer, 0x68, ulReadLength);
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return Status;
}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
	NTSTATUS Status;
	PDEVICE_OBJECT pDevObj;
	UNICODE_STRING DriverName;
	UNICODE_STRING SymLinkName;

	RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
	DbgPrint("命令 IoCreateDevice 狀態: %d", Status);
	pDevObj->Flags |= DO_BUFFERED_IO;
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");
	Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
	DbgPrint("當前命令IoCreateSymbolicLink狀態: %d", Status);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	CreateDriverObject(pDriver);                               // 調用創建設備
	pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 創建成功派遣函數
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 關閉派遣函數
	pDriver->MajorFunction[IRP_MJ_READ] = DispatchRead;

	DbgPrint("驅動加載完成...");
	pDriver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

客戶端代碼

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

int main()
{
	HANDLE hDevice = CreateFile(L"\\\\.\\My_Device", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("獲取驅動句柄失敗: %d\n", GetLastError());
		getchar();
	}

	UCHAR buffer[10];
	ULONG ulRead;

	ReadFile(hDevice, buffer, 10, &ulRead, 0);
	for (int i = 0; i < (int)ulRead; i++)
	{
		printf("%02X", buffer[i]);
	}
	getchar();
	CloseHandle(hDevice);
	return 0;
}

向驅動派發命令: 向驅動程序中發送一個結構,驅動程序內部通過DbgPrint打印出來。

#include <ntddk.h>
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

typedef struct Hread {
	ULONG Flage;
	ULONG Addr;
	ULONG WriteBufferAddr;
	ULONG Size;
	ULONG Pid;
}_Hread, *PtrHread;

typedef struct _DEVICE_EXTENSION {
	UNICODE_STRING SymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT pDevObj;
	pDevObj = pDriverObject->DeviceObject;
	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	UNICODE_STRING pLinkName = pDevExt->SymLinkName;
	IoDeleteSymbolicLink(&pLinkName);
	IoDeleteDevice(pDevObj);
}
NTSTATUS DefDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}

NTSTATUS IoctlDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	ULONG_PTR Informaiton = 0;
	PVOID InputData = NULL;
	ULONG InputDataLength = 0;
	PVOID OutputData = NULL;
	ULONG OutputDataLength = 0;
	PIO_STACK_LOCATION  IoStackLocation = IoGetCurrentIrpStackLocation(pIrp);              // Irp堆棧  
	InputData = pIrp->AssociatedIrp.SystemBuffer;
	OutputData = pIrp->AssociatedIrp.SystemBuffer;
	InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;      // 輸入數據大小
	OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;    // 輸出數據大小
	ULONG Code = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;

	switch (Code)
	{
	case My_Code:
		PtrHread PtrBuff = (PtrHread)InputData;
		ULONG RetFlage = PtrBuff->Flage;
		ULONG RetAddr = PtrBuff->Addr;
		ULONG RetBufferAddr = PtrBuff->WriteBufferAddr;
		ULONG Size = PtrBuff->Size;
		ULONG Pid = PtrBuff->Pid;

		DbgPrint("讀取文件標志:%d", RetFlage);
		DbgPrint("讀取寫入地址:%x", RetAddr);
		DbgPrint("讀取緩沖區大小:%d", RetBufferAddr);
		DbgPrint("讀取當前大小:%d", Size);
		DbgPrint("要操作進程PID: %d", Pid);

		// 通過內存返回數據.
		char *retBuffer = "hello lyshark";
		memcpy(OutputData, retBuffer , strlen(retBuffer));
		Informaiton = strlen(retBuffer) + 1;
		Status = STATUS_SUCCESS;

		// 通過內存返回數據,另一種通信方式.
		PVOID addr = (PVOID)"ok";
		RtlCopyMemory(OutputData, addr, 4);
		Informaiton = 4;
		Status = STATUS_SUCCESS;
		break;
	}

	pIrp->IoStatus.Status = Status;                   // 設置IRP完成狀態,會設置用戶模式下的GetLastError
	pIrp->IoStatus.Information = Informaiton;    // 設置操作的字節
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);         // 完成IRP,不增加優先級
	return Status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
	pDriverObject->DriverUnload = DriverUnload;//注冊驅動卸載函數
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = DefDispatchRoutine;   // 注冊派遣函數
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = DefDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoctlDispatchRoutine;

	NTSTATUS status;
	PDEVICE_OBJECT pDevObj;
	PDEVICE_EXTENSION pDevExt;

	//創建設備名稱的字符串
	UNICODE_STRING devName;
	RtlInitUnicodeString(&devName, L"\\Device\\MyDevice");
	//創建設備
	status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
	pDevObj->Flags |= DO_BUFFERED_IO;//將設備設置為緩沖I/O設備
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;//得到設備擴展

	//創建符號鏈接
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName, L"\\??\\MyDevice");
	pDevExt->SymLinkName = symLinkName;
	status = IoCreateSymbolicLink(&symLinkName, &devName);
	return STATUS_SUCCESS;
}

客戶端

#include "stdafx.h"
#include<Windows.h>
// 自定義的控制信號
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

typedef struct Hread {
	ULONG Flage;
	ULONG Addr;
	ULONG WriteBufferAddr;
	ULONG Size;
	ULONG Pid;
}_Hread, *PtrHread;

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE handle = CreateFileA("\\\\.\\MyDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	unsigned char RetBufferData[20] = { 0 };
	DWORD ReturnLength = 4;
	_Hread buf;

	buf.Flage = 2;
	buf.Addr = 0x401234;
	buf.WriteBufferAddr = 1024;
	buf.Size = 100;
	buf.Pid = 2566;

	DeviceIoControl(handle, My_Code, &buf, 20, (LPVOID)RetBufferData, 4, &ReturnLength, 0);
	printf("返回的數據: %s", RetBufferData);

	getchar();
	CloseHandle(handle);
	return 0;
}

驅動讀寫操作: 網上找到一個驅動讀寫相關的案例,看着不錯這里就轉過來啦,我就不自己寫了。

這個驅動讀寫轉載於:https://blog.csdn.net/weixin_44286745

服務端:

#pragma once
#include<ntifs.h>
#include<windef.h>

#define READCODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ALL_ACCESS)
#define WRITECODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ALL_ACCESS)

#define DEVICENAME L"\\Device\\ReadWriteDevice"
#define SYMBOLNAME L"\\??\\ReadWriteSymbolName"

typedef struct DATA
{
	DWORD pid;//要讀寫的進程ID
	unsigned __int64 address;//要讀寫的地址
	DWORD size;//讀寫長度
	BYTE* data;//要讀寫的數據,
}Data;

void DriverUnload(PDRIVER_OBJECT driver)
{

	if (driver->DeviceObject)
	{
		UNICODE_STRING SymbolName;
		RtlInitUnicodeString(&SymbolName, SYMBOLNAME);

		IoDeleteSymbolicLink(&SymbolName);
		IoDeleteDevice(driver->DeviceObject);
	}

	DbgPrint("驅動已卸載");
}

NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_OBJECT device = NULL;
	UNICODE_STRING DeviceName;

	RtlInitUnicodeString(&DeviceName, DEVICENAME);

	status = IoCreateDevice(
		driver,
		sizeof(driver->DriverExtension),
		&DeviceName,
		FILE_DEVICE_UNKNOWN,
		FILE_DEVICE_SECURE_OPEN,
		FALSE,
		&device
		);

	if (status == STATUS_SUCCESS)
	{
		UNICODE_STRING SymbolName;
		RtlInitUnicodeString(&SymbolName, SYMBOLNAME);

		status = IoCreateSymbolicLink(&SymbolName, &DeviceName);

		if (status != STATUS_SUCCESS)
		{
			DbgPrint("創建符號鏈接失敗");
			IoDeleteDevice(device);
		}
	}
	DbgPrint("驅動設備已創建");
	return status;
}


BOOL ReadMemory(Data* data)
{
	BOOL bRet = TRUE;
	PEPROCESS process = NULL;

	PsLookupProcessByProcessId(data->pid, &process);

	if (process == NULL)
	{
		DbgPrint("獲取進程對象失敗");
		return FALSE;
	}

	BYTE* GetData;
	__try
	{
		GetData = ExAllocatePool(PagedPool, data->size);
	}
	__except (1)
	{
		DbgPrint("內存分配失敗");
		return FALSE;
	}

	KAPC_STATE stack = { 0 };
	KeStackAttachProcess(process, &stack);

	__try
	{
		ProbeForRead(data->address, data->size, 1);
		RtlCopyMemory(GetData, data->address, data->size);
	}
	__except (1)
	{
		DbgPrint("讀取內存出錯");
		bRet = FALSE;
	}

	ObDereferenceObject(process);
	KeUnstackDetachProcess(&stack);
	RtlCopyMemory(data->data, GetData, data->size);
	ExFreePool(GetData);
	return bRet;
}

BOOL WriteMemory(Data* data)
{
	BOOL bRet = TRUE;
	PEPROCESS process = NULL;

	PsLookupProcessByProcessId(data->pid, &process);
	if (process == NULL)
	{
		DbgPrint("獲取進程對象失敗");
		return FALSE;
	}

	//在進入進程地址空間之前先賦值
	BYTE* GetData;
	__try
	{
		GetData = ExAllocatePool(PagedPool, data->size);
	}
	__except (1)
	{
		DbgPrint("內存分配失敗");
		return FALSE;
	}

	for (int i = 0; i < data->size; i++)
	{
		GetData[i] = data->data[i];
	}

	KAPC_STATE stack = { 0 };
	KeStackAttachProcess(process, &stack);

	PMDL mdl = IoAllocateMdl(data->address, data->size, 0, 0, NULL);
	if (mdl == NULL)
	{
		DbgPrint("創建MDL失敗");
		return FALSE;
	}

	MmBuildMdlForNonPagedPool(mdl);

	BYTE* ChangeData = NULL;

	__try
	{
		ChangeData = MmMapLockedPages(mdl, KernelMode);
		RtlCopyMemory(ChangeData, GetData, data->size);
	}
	__except (1)
	{
		DbgPrint("內存映射失敗,%d", sizeof(ChangeData));
		bRet = FALSE;
		goto END;
	}

END:
	IoFreeMdl(mdl);
	ExFreePool(GetData);
	KeUnstackDetachProcess(&stack);
	ObDereferenceObject(process);

	return bRet;
}

NTSTATUS DriverIrpCtl(PDEVICE_OBJECT device, PIRP pirp)
{
	PIO_STACK_LOCATION stack;
	stack = IoGetCurrentIrpStackLocation(pirp);
	Data* data;

	switch (stack->MajorFunction)
	{

	case IRP_MJ_CREATE:
	{
						  DbgPrint("設備已打開");
						  break;
	}

	case IRP_MJ_CLOSE:
	{
						 DbgPrint("設備已關閉");
						 break;
	}

	case IRP_MJ_DEVICE_CONTROL:
	{
								  data = pirp->AssociatedIrp.SystemBuffer;
								  DbgPrint("PID:%d  地址:%x  大小:%d", data->pid, data->address, data->size);
								  switch (stack->Parameters.DeviceIoControl.IoControlCode)
								  {

								  case READCODE:
								  {
												   ReadMemory(data);
												   break;
								  }

								  case WRITECODE:
								  {
													WriteMemory(data);
													break;
								  }

								  }

								  pirp->IoStatus.Information = sizeof(data);

								  break;
	}

	}

	pirp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(pirp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING path)
{
	DbgPrint("驅動已加載,路徑:%wZ", path);

	driver->DriverUnload = DriverUnload;

	CreateDevice(driver);

	driver->MajorFunction[IRP_MJ_CREATE] = DriverIrpCtl;
	driver->MajorFunction[IRP_MJ_CLOSE] = DriverIrpCtl;
	driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIrpCtl;

	return STATUS_SUCCESS;
}

客戶端:

#include "stdafx.h"
#include<Windows.h>
#include <string.h>

#define READCODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ALL_ACCESS)
#define WRITECODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ALL_ACCESS)

typedef struct DATA
{
	DWORD pid;//要讀寫的進程ID
	unsigned __int64 address;//要讀寫的地址
	DWORD size;//讀寫長度
	BYTE* data;//要讀寫的數據,
}Data;

/*  驅動內存寫入,如下
Data data;
data.pid = GetDlgItemInt(IDC_EDIT_PID);
data.address = GetDlgItemInt(IDC_EDIT_address);
data.size = GetDlgItemInt(IDC_EDIT_Size);
data.data = new BYTE[data.size];

for (int i = 0; i < data.size; i++)
{
	data.data[i] = 90909090;   // 寫入Nop指令
}

DWORD dwSize = 0;
DeviceIoControl(DeviceHandle,WRITECODE,&data,sizeof(data),&data,sizeof(data),&dwSize,NULL);
delete[] data.data;
*/

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE handle = CreateFileA("\\??\\ReadWriteSymbolName", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	Data data;
	DWORD dwSize = 0;

	data.pid = 908;
	data.address = 4198400;
	data.size = 4;
	
	data.data = new BYTE[data.size];
	DeviceIoControl(handle, READCODE, &data, sizeof(data), &data, sizeof(data), &dwSize, NULL);
	for (int i = 0; i < data.size; i++)
	{
		printf("%x", data.data[i]);
	}

	getchar();
	CloseHandle(handle);
	return 0;
}

上方的代碼,經過修改后可以正常完成編譯鏈接,並讀出內存數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM