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

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

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

输出效果如下:

image.png

目录
相关文章
|
27天前
|
C# Android开发 开发者
Uno Platform 高级定制秘籍:深度解析与实践样式和模板应用,助你打造统一且高效的跨平台UI设计
【9月更文挑战第7天】Uno Platform 是一个强大的框架,支持使用 C# 和 XAML 创建跨平台 UI 应用,覆盖 Windows、iOS、Android、macOS 和 WebAssembly。本文介绍 Uno Platform 中样式和模板的应用,助力开发者提升界面一致性与开发效率。样式定义控件外观,如颜色和字体;模板则详细定制控件布局。通过 XAML 定义样式和模板,并可在资源字典中全局应用或嵌套扩展。合理利用样式和模板能简化代码、保持设计一致性和提高维护性,帮助开发者构建美观高效的跨平台应用。
32 1
|
2月前
|
前端开发 Go API
goctl 技术系列 - 通过模板简化应用开发
goctl 技术系列 - 通过模板简化应用开发
|
3月前
|
安全 测试技术 数据库
LabVIEW软件需求分析文档内容和编写指南
LabVIEW软件需求分析文档内容和编写指南
36 0
|
5月前
|
XML 存储 数据格式
使用自定义模板和示例项目开发LabVIEW项目
使用自定义模板和示例项目开发LabVIEW项目
38 1
|
5月前
|
存储 前端开发 JavaScript
软件设计文档编写指南
软件设计文档编写指南
|
5月前
|
XML 存储 文件存储
LabVIEW使用自定义模板和示例项目来开发LabVIEW项目
LabVIEW使用自定义模板和示例项目来开发LabVIEW项目
36 0
|
5月前
|
数据可视化 前端开发 JavaScript
iVX,重新定义编程:人人都可掌握的可视化编程
iVX,重新定义编程:人人都可掌握的可视化编程
130 0
|
数据库
【平台开发】技术整合思考(五)代码生成代码
【平台开发】技术整合思考(五)代码生成代码
82 2
|
存储
驱动开发:应用DeviceIoContro模板精讲
在笔者上一篇文章`《驱动开发:应用DeviceIoContro开发模板》`简单为大家介绍了如何使用`DeviceIoContro`模板快速创建一个驱动开发通信案例,但是该案例过于简单也无法独立加载运行,本章将继续延申这个知识点,通过封装一套标准通用模板来实现驱动通信中的常用传递方式,这其中包括了如何传递字符串,传递整数,传递数组,传递结构体等方法。可以说如果你能掌握本章模板精讲的内容基本上市面上的功能都可以使用本方法进行通信。
57 0
|
小程序 API 数据安全/隐私保护
小程序模板及插件开发应用
本节对小程序模板和插件开发以及会涉及到的场景做了介绍。
小程序模板及插件开发应用
下一篇
无影云桌面