概述:驱动开发通用模板

参考文章:驱动开发:应用DeviceIoContro开发模板 | LyShark®

模板说明

内核中执行代码后需要将结果动态显示给应用层的用户,DeviceIoControl 是直接发送控制代码到指定的设备驱动程序,使相应的移动设备以执行相应的操作的函数,如下代码是一个经典的驱动开发模板框架,在开发经典驱动时会用到的一个通用案例。

如下这段案例中,我们只介绍DispatchIoctl,该函数主要用于接收或发送IOCTL控制信号,以此来实现接收和发送数据。

首先,通过调用IoGetCurrentIrpStackLocation函数获取IRP(I/O Request Packet)的堆栈位置,并获取控制码、输入和输出缓冲区的相关信息。

然后,根据不同的控制信号码,进行相应的处理流程。这里的示例代码只列出了一个控制信号码(IOCTL_IO_LyShark)的处理流程,即接收传入数据,进行处理后返回传出数据。

最后,根据处理结果,设置IRP的状态和返回信息,并通过调用IoCompleteRequest函数完成IRP的处理。

需要注意的是,这段代码中没有对错误情况进行处理,如果出现错误,返回的状态码为STATUS_INVALID_DEVICE_REQUEST。因此,实际使用中需要根据具体情况进行修改和完善。

如下所示,为驱动开发通用模板:

#include <ntifs.h>
#include <windef.h>
 
// 控制器
#define IOCTL_IO_LyShark CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
 
// 卸载驱动执行
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_Driver");
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
 
	// 指定通信方式为缓冲区
	pDevObj->Flags |= DO_BUFFERED_IO;
 
	// 创建符号链接
	RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");
	Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
	return STATUS_SUCCESS;
}
 
// 创建回调函数
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;                           // 返回成功
}
 
// 主控制器,用于判断R3发送的控制信号
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack;
	ULONG uIoControlCode;
	PVOID pIoBuffer;
	ULONG uInSize;
	ULONG uOutSize;
 
	// 获得IRP里的关键数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
 
	// 获取控制码
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
 
	// 输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
 
	// EXE发送传入数据的BUFFER长度(DeviceIoControl的nInBufferSize)
	uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
 
	// EXE接收传出数据的BUFFER长度(DeviceIoControl的nOutBufferSize)
	uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
 
	// 对不同控制信号的处理流程
	switch (uIoControlCode)
	{
		// 接收或发送
	case IOCTL_IO_LyShark:
	{
		DWORD dw = 0;
 
		// 得到输入参数
		memcpy(&dw, pIoBuffer, sizeof(DWORD));
 
		DbgPrint("[+] hello lyshark \n");
 
		// 对输入参数进行处理
		dw++;
 
		// 设置输出参数
		memcpy(pIoBuffer, &dw, sizeof(DWORD));
 
		// 返回通信状态
		status = STATUS_SUCCESS;
		break;
	}
 
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = uOutSize;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
	}
 
	// 设定DeviceIoControl的*lpBytesReturned的值(如果通信失败则返回0长度)
	if (status == STATUS_SUCCESS)
		pIrp->IoStatus.Information = uOutSize;
	else
		pIrp->IoStatus.Information = 0;
 
	// 设定DeviceIoControl的返回值是成功还是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}
 
// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
	// 调用创建设备
	CreateDriverObject(pDriver);
 
	pDriver->DriverUnload = UnDriver;                               // 卸载函数
	pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;         // 创建派遣函数
	pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;           // 关闭派遣函数
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;  // 分发函数
 
	DbgPrint("By:LyShark ...");
 
	return STATUS_SUCCESS;
}