windows 驱动与内核调试 学习4

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了windows 驱动与内核调试 学习4相关的知识,希望对你有一定的参考价值。

前言

本文编写驱动DeviceIoControl逻辑。

首先我们需要CTL_CODE这个宏定义控制码
控制码相关文档

#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)

其中比较难理解的是Method参数,这个参数决定输出输入缓存流如何定于,
这个参数同时也要受限与DEVICE_OBJECTflags字段.比如DEVICE_OBJECT.flagsDO_DIRECT_IO时不能使用METHOD_BUFFERED

Buffer Descriptions for I/O Control Codes

我们举例如下控制码生命

//Function 0x800以下为保留字段
#define MY_CTL(NUM) CTL_CODE(FILE_DEVICE_UNKNOWN,0x800+NUM, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define CTL_ENUM_1 MY_CTL(2)
#define CTL_ENUM_2 MY_CTL(3)

一个常规的创建驱动设备代码

//驱动被加载的时候会调用此函数
NTSTATUS
DriverEntry(
	_In_ struct _DRIVER_OBJECT* DriverObject,
	_In_ PUNICODE_STRING    RegistryPath
)

	//如果你没有用到参数需要告诉系统。
	UNREFERENCED_PARAMETER(RegistryPath);
	//打印信息
	DbgPrint("hello  drive loaded");
	//触发一个断点
	//DbgBreakPoint();
	//驱动卸载回调注册
	DriverObject->DriverUnload = myUnload;


	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;


	UNICODE_STRING ustrDevName;
	RtlInitUnicodeString(&ustrDevName, L"\\\\Device\\\\MytestDriver");
	PDEVICE_OBJECT  pDevObj = NULL;

	auto ret = IoCreateDevice(DriverObject, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevObj);




	if (NT_SUCCESS(ret))
	
		//指定IO模式
		pDevObj->Flags |= DO_BUFFERED_IO;
		DbgPrint("IoCreateDevice 成功 \\r\\n");
	
	else 
		DbgPrint("IoCreateDevice 失败 %d\\r\\n", ret);
		return STATUS_FAIL_CHECK;
	


	UNICODE_STRING symbolDevName;
	RtlInitUnicodeString(&symbolDevName, L"\\\\DosDevices\\\\MytestDriver");
	ret = IoCreateSymbolicLink(&symbolDevName, &ustrDevName);
	if (NT_SUCCESS(ret))
	
		DbgPrint("IoCreateSymbolicLink 成功 \\r\\n");
	
	else 
		DbgPrint("IoCreateSymbolicLink 失败%d\\r\\n", ret);

		IoDeleteDevice(pDevObj);

		return STATUS_FAIL_CHECK;
	

	return STATUS_SUCCESS;

驱动核心的代码实现


NTSTATUS
DispatchControl(
	_In_ struct _DEVICE_OBJECT* DeviceObject,
	_Inout_ struct _IRP* Irp
) 
	DbgPrint("DispatchControl");
	UNREFERENCED_PARAMETER(Irp);
	UNREFERENCED_PARAMETER(DeviceObject);

	PIO_STACK_LOCATION	pIrpStack = IoGetCurrentIrpStackLocation(Irp);
	ULONG nIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	ULONG nInputBufferLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	ULONG nOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	//这个SystemBuffer又作输入和输出
	PVOID lpBuffer = Irp->AssociatedIrp.SystemBuffer;
	switch (nIoControlCode)
	
	case CTL_ENUM_1: 
		DbgPrint("DispatchControl CTL_ENUM_1 buf %p content %s inputLen %d outlen %d controlcode %d ",lpBuffer,lpBuffer, nInputBufferLength, nOutputBufferLength, nIoControlCode);
		memcpy(lpBuffer, "CTL_ENUM_1", 10);
		break;

	
	case CTL_ENUM_2: 
		DbgPrint("DispatchControl CTL_ENUM_2 buf %p content %s inputLen %d outlen %d controlcode %d ", lpBuffer, lpBuffer, nInputBufferLength, nOutputBufferLength, nIoControlCode);
		memcpy(lpBuffer, "CTL_ENUM_2", 10);
		break;
	

	default:
		break;
	

	Irp->iostatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 10;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return STATUS_SUCCESS;

上层代码

#include <iostream>
#include<Windows.h>
#include<stdlib.h>
#define MY_CTL(NUM) CTL_CODE(FILE_DEVICE_UNKNOWN,0x800+NUM, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define CTL_ENUM_1 MY_CTL(2)
#define CTL_ENUM_2 MY_CTL(3)


int main()

	std::cout << "Hello World!\\n";

	HANDLE hFile;
	hFile = CreateFile("\\\\\\\\\\?\\\\MytestDriver",
		GENERIC_WRITE | GENERIC_READ,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);
	if (hFile == INVALID_HANDLE_VALUE)
	
		std::cout << "INVALID_HANDLE_VALUE  "<< GetLastError()<<"\\n";

		return EXIT_FAILURE;
	

	/*std::cout << "open ok\\n";
	DWORD dwBytes = 0;
	if (WriteFile(hFile, "hello", 6, &dwBytes, NULL))
	
		std::cout << "write ok " << dwBytes << std::endl;
	
	else 
		std::cout << "write failure " << dwBytes << std::endl;
	

	DWORD drBytes = 0;
	char szBuffer[120];
	if (ReadFile(hFile, szBuffer, sizeof szBuffer, &drBytes, NULL))
	
		std::cout << "read ok  " << drBytes << " "<< szBuffer << std::endl;
	
	else 
		std::cout << "read failure " << std::endl;
	*/

	char szControlIn[120]="hello";
	char szControlOut[120]="hello myboy";
	DWORD out=0;

	
	if (DeviceIoControl(hFile, CTL_ENUM_1, szControlIn, sizeof szControlIn, szControlOut, sizeof szControlOut, &out, nullptr))
	
		std::cout << "DeviceIoControl success out" << out <<" szControlOut:"<< szControlIn  << std::endl;

		printf("\\r\\n szControlIn %s\\r\\n", szControlIn);
		printf("\\r\\n szControlOut %s\\r\\n", szControlOut);
	
	else
	
		std::cout << "DeviceIoControl failure " <<GetLastError() << std::endl;

		
	CloseHandle(hFile);
	system("pause");
	return EXIT_SUCCESS;


以上是关于windows 驱动与内核调试 学习4的主要内容,如果未能解决你的问题,请参考以下文章

windows 驱动与内核调试 学习4

windows 驱动与内核调试 学习5

windows 驱动与内核调试 学习5

windows 驱动与内核调试 学习5

windows 驱动与内核调试 学习

windows 驱动与内核调试 学习