前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >驱动开发:应用DeviceIoContro开发模板

驱动开发:应用DeviceIoContro开发模板

原创
作者头像
微软技术分享
发布2022-11-18 15:38:44
7490
发布2022-11-18 15:38:44
举报

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

驱动程序开发通用模板代码如下:

代码语言:C
复制
#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"\\??\\LySharkDriver");     // 初始化字符串将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\\LySharkDriver");
	Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);

	// 指定通信方式为缓冲区
	pDevObj->Flags |= DO_BUFFERED_IO;

	// 创建符号链接
	RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver");
	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发送的控制信号
// lyshark.com
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;
}

应用层通用测试模板代码如下:

代码语言:C
复制
#include <iostream>
#include <Windows.h>
#include <winioctl.h>

#define IOCTL_IO_LyShark CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

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;
	}

	// 发送控制信号

	// input = 发送数据 output = 接受数据 ref_len = 数据长度
	DWORD input = 100, output = 0, ref_len = 0;
	DeviceIoControl(hDevice, IOCTL_IO_LyShark, &input, sizeof(input), &output, sizeof(output), &ref_len, 0);

	printf("输出: %d \n", output);

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

输出效果如下:

image.png
image.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档