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


    内核中执行代码后需要将结果动态显示给应用层的用户,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;
    }
    

    输出效果如下:

  • 相关阅读:
    从七牛云迁移图片到github
    Ajax 结构及使用
    JQuery 简单的文字超出部分隐藏下拉显示
    JQuery 动画及一些小知识点
    Jqurey DOM 操作详解
    Jquery DOM 操作列表
    文件上传以及JS链式结构
    JQuery选择器
    JQuery 基本知识
    LinQ to sql 各种数据库查询方法
  • 原文地址:https://www.cnblogs.com/LyShark/p/16751136.html
Copyright © 2020-2023  润新知