首页 > 其他分享 >驱动开发:应用DeviceIoContro开发模板

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

时间:2022-10-03 20:22:34浏览次数:55  
标签:STATUS DeviceIoControl DeviceIoContro OBJECT 开发 IO pDriver 模板 pIrp

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

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

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

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

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

输出效果如下:

标签:STATUS,DeviceIoControl,DeviceIoContro,OBJECT,开发,IO,pDriver,模板,pIrp
From: https://www.cnblogs.com/LyShark/p/16751136.html

相关文章

  • 抽象类及模板设计模式
    1基本介绍当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类当父类的一些方法不能确定时,可以用abstract关键字来修饰该方......
  • 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用
    刚完成一些前端项目的开发,腾出精力来总结一些前端开发的技术点,以及继续完善基于SqlSugar的开发框架循序渐进介绍的系列文章,本篇随笔主要介绍一下基于Vue3+TypeScript的全局......
  • IDEA 插件开发(一):菜单及气泡通知
    开发工具开发工具使用IntellijIDEA,官网下载地址:https://www.jetbrains.com/idea/download/other.html推荐使用2020.3.4社区版(Community),原因如下:免费开源,在开发插件......
  • 驱动开发:通过Async反向与内核通信
    在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在......
  • 驱动开发:通过Async反向与内核通信
    在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在......
  • springboot整合thymeleaf模板引擎和bootstrap实现增删改查和文件上传
     一、参照第八天任务中的栏目表,使用thymeleaf做为前端展现,完成CRUD及分页操作二、使用springboot+mybatis-plus+redis完成用户登录系统,数据库表users字段名称......
  • SpringBlade微服务开发平台(工作流+大屏+监控等)
    源码地址:https://gitee.com/smallc/SpringBlade(如有侵权请及时联系博主删贴)SpringBlade是一个由商业级项目升级优化而来的微服务架构,采用SpringBoot2.7、SpringClou......
  • 深度学习Vue源码-模板编译原理
    前言此篇主要手写Vue2.0源码-模板编译原理上一篇咱们主要介绍了Vue数据的响应式原理对于中高级前端来说响应式原理基本是面试Vue必考的源码基础类如果不是很清......
  • P3384 【模板】轻重链剖分/树链剖分
    【模板】轻重链剖分/树链剖分题目描述如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:1xyz,表示将树从\(x\)到\(y\)结点......
  • 【Golang开发面经】百度(三轮技术面)
    文章目录​​写在前面​​​​笔试​​​​一面​​​​算法:判断是否为镜面二叉树​​​​算法:二叉树的俯视图​​​​一个协程被网络io卡住了,对应的线程会不会卡住?​​​​......