首页
论坛
课程
招聘
[原创] 驱动开发:应用DeviceIoContro开发模板
2022-11-1 13:35 5348

[原创] 驱动开发:应用DeviceIoContro开发模板

2022-11-1 13:35
5348

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

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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;
}

输出效果如下:


[招生]科锐逆向工程师培训46期预科班将于 2023年02月09日 正式开班

收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回