复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18kd> dt PDRIVER_OBJECT Wdf01000!PDRIVER_OBJECT Ptr32 +0x000 Type : Int2B +0x002 Size : Int2B +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT +0x008 Flags : Uint4B +0x00c DriverStart : Ptr32 Void +0x010 DriverSize : Uint4B +0x014 DriverSection : Ptr32 Void +0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING +0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH +0x02c DriverInit : Ptr32 long +0x030 DriverStartIo : Ptr32 void +0x034 DriverUnload : Ptr32 void +0x038 MajorFunction : [28] Ptr32 long //由驱动程序的DispatchXxx例程的入口点数组组成的调度表。数组的索引值是IRP_MJ_ XXX代表每个值IRP主功能码。每个驱动必须在此数组中设置的入口点IRP_MJ_ XXX请求驱动程序句柄
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13kd> dt PIO_STACK_LOCATION Wdf01000!PIO_STACK_LOCATION Ptr32 +0x000 MajorFunction : UChar//指示要执行的 I/O 操作类型的IRP 主要功能代码。 +0x001 MinorFunction : UChar//MajorFunction的子函数代码 +0x002 Flags : UChar +0x003 Control : UChar +0x004 Parameters : _IO_STACK_LOCATION::<unnamed-type-Parameters>//取决于MajorFunction和MinorFunction 中包含的主要和次要 IRP 函数代码值的联合 +0x014 DeviceObject : Ptr32 _DEVICE_OBJECT +0x018 FileObject : Ptr32 _FILE_OBJECT +0x01c CompletionRoutine : Ptr32 long +0x020 Context : Ptr32 Void
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17驱动程序处理使用以下部分或全部主要功能代码设置的 IRP: IRP_MJ_CLEANUP IRP_MJ_CLOSE IRP_MJ_CREATE//创造 IRP_MJ_DEVICE_CONTROL//设备控制 IRP_MJ_FILE_SYSTEM_CONTROL IRP_MJ_FLUSH_BUFFERS IRP_MJ_INTERNAL_DEVICE_CONTROL//设备控制 IRP_MJ_PNP IRP_MJ_POWER IRP_MJ_QUERY_INFORMATION//查询文件 IRP_MJ_READ//读 IRP_MJ_SET_INFORMATION//设置文件 IRP_MJ_SHUTDOWN IRP_MJ_SYSTEM_CONTROL IRP_MJ_WRITE//写
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25kd> dt _IRP win32k!_IRP +0x000 Type : Int2B +0x002 Size : Uint2B +0x004 MdlAddress : Ptr32 _MDL//指向一个内存描述符表(MDL) +0x008 Flags : Uint4B//包含一些对驱动程序只读的标志 +0x00c AssociatedIrp : <unnamed-tag> +0x010 ThreadListEntry : _LIST_ENTRY +0x018 IoStatus : _IO_STATUS_BLOCK//包含两个域的结构,驱动程序在最终完成请求时设置这个结构,IoStatus.Status域将收到一个NTSTATUS代码,而IoStatus.Information的类型为ULONG_PTR +0x020 RequestorMode : Char//UserMode或KernelMode,指定原始I/O请求的来源 +0x021 PendingReturned : UChar +0x022 StackCount : Char +0x023 CurrentLocation : Char +0x024 Cancel : UChar +0x025 CancelIrql : UChar +0x026 ApcEnvironment : Char +0x027 AllocationFlags : UChar +0x028 UserIosb : Ptr32 _IO_STATUS_BLOCK +0x02c UserEvent : Ptr32 _KEVENT +0x030 Overlay : <unnamed-tag> +0x038 CancelRoutine : Ptr32 void +0x03c UserBuffer : Ptr32 Void +0x040 Tail : <unnamed-tag>
IRP_MJ_READ 通信
驱动
复制代码
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#include <ntifs.h> #define DEVICE_NAME L"\Device\wangliang"//设备名 #define SYM_NAME L"\??\wangliang" NTSTATUS DefDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp) { Irp->IoStatus.Status = STATUS_SUCCESS;//完成请求时设置这个结构 IoCompleteRequest(Irp, 0);//调用方已完成所有I/O请求处理操作,并将给定的 IRP 返回给 I/O 管理器 /* void IofCompleteRequest( PIRP Irp,//指向要完成的 IRP 的指针 CCHAR PriorityBoost ); */ return STATUS_SUCCESS; } NTSTATUS ReadDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp) { DbgBreakPoint(); PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);//返回一个指向IO_STACK_LOCATION结构的指针 LARGE_INTEGER ByteOffset = ioStack->Parameters.Read.ByteOffset;//指定读多少个字节 int Length = ioStack->Parameters.Read.Length;//要读取的数据的长度(以字节为单位)。如果读取操作成功,则在Irp->IoStatus指向的IO_STATUS_BLOCK结构体的Information成员中返回读取的字节数。 int* xxx = Irp->AssociatedIrp.SystemBuffer;//SystemBuffer指针指向一个数据缓冲区,该缓冲区位于内核模式的非分页内存中。对于IRP_MJ_READ和IRP_MJ_WRITE操作,如果顶级设备指定DO_BUFFERED_IO标志,则I/O管理器就创建这个数据缓冲区。对于IRP_MJ_DEVICE_CONTROL操作,如果 I/O控制功能代码指出需要缓冲区,则I/O管理器就创建这个数据缓冲区。I/O管理器把用户模式程序发送给驱动程序的数据复制到这个缓冲区,这也是创建IRP过程的一部分。对于读请求,设备驱动程序把读出的数据填到这个缓冲区,然后I/O管理器再把缓冲区的内容复制到用户模式缓冲区。 *xxx = 100; Irp->IoStatus.Information = Length; Irp->IoStatus.Status = STATUS_SUCCESS;//驱动程序在最终完成请求时设置这个结构,IoStatus.Status域将收到一个NTSTATUS代码,而IoStatus.Information的类型为ULONG_PTR IoCompleteRequest(Irp, 0); return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT pDriver) { UNICODE_STRING symName = { 0 }; RtlInitUnicodeString(&symName, SYM_NAME); IoDeleteSymbolicLink(&symName);//删除符号链接 IoDeleteDevice(pDriver->DeviceObject); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) { UNICODE_STRING unName = { 0 }; RtlInitUnicodeString(&unName, DEVICE_NAME);//初始化一个Unicode的字符串,设备名 UNICODE_STRING symName = { 0 }; RtlInitUnicodeString(&symName, SYM_NAME);//函数名 PDEVICE_OBJECT pDevice = NULL; NTSTATUS status = IoCreateDevice(pDriver, 0, &unName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);//创建一个驱动设备使用的设备对象 /* NTSTATUS IoCreateDevice( PDRIVER_OBJECT DriverObject,//指向调用者的驱动程序对象的指针 ULONG DeviceExtensionSize,//指定要为设备对象的设备扩展分配的驱动程序确定的字节数 PUNICODE_STRING DeviceName,//命名设备对象 DEVICE_TYPE DeviceType,//指定设备类型的值 ULONG DeviceCharacteristics,//提供有关驱动程序设备的附加信息 多数驱动程序为此参数指定 FILE_DEVICE_SECURE_OPEN BOOLEAN Exclusive,//指定设备对象是否代表独占设备。多数驱动程序将此值设置为FALSE PDEVICE_OBJECT *DeviceObject//指向变量的指针,该变量接收指向新创建的DEVICE_OBJECT结构的指针 );*/ if (!NT_SUCCESS(status)) { DbgPrint("[db]:%xrn", status); //DbgPrintEx(77, 0, ""); return status; } status = IoCreateSymbolicLink(&symName, &unName);//设备名和用户的可见名之间创建符号链接 /* NTSTATUS IoCreateSymbolicLink( PUNICODE_STRING SymbolicLinkName,//用户的可见名 PUNICODE_STRING DeviceName//指向设备对象名称 );*/ if (!NT_SUCCESS(status)) { IoDeleteDevice(pDevice); DbgPrint("[db]:%xrn", status); return status; } pDevice->Flags &= ~DO_DEVICE_INITIALIZING;//干掉这个位 符号链接->设备对象->驱动对象->功能函数 pDevice->Flags |= DO_BUFFERED_IO; pDriver->MajorFunction[IRP_MJ_CREATE] = DefDispatch;//设置回调函数 pDriver->MajorFunction[IRP_MJ_CLOSE] = DefDispatch; pDriver->MajorFunction[IRP_MJ_READ] = ReadDispatch; pDriver->DriverUnload = DriverUnload; return status; }
R3端的程序
复制代码
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#include <stdio.h> #include <Windows.h> #include <winioctl.h> #define SYM_NAME "\\.\wangliang" int main() { HANDLE hDevice = CreateFileA(SYM_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* HANDLE CreateFileA( LPCSTR lpFileName,//要创建或打开的文件或设备的名称 DWORD dwDesiredAccess,//权限 DWORD dwShareMode,//请求的文件或设备的共享模式 LPSECURITY_ATTRIBUTES lpSecurityAttributes,//指向SECURITY_ATTRIBUTES 结构的指针,该结构包含两个独立但相关的数据成员:一个可选的安全描述符,以及一个确定返回的句柄是否可以被子进程继承的布尔值。此参数可以为NULL。如果此参数为NULL,则CreateFile返回的句柄 不能由应用程序可能创建的任何子进程继承,并且与返回的句柄关联的文件或设备获得默认安全描述符。 DWORD dwCreationDisposition,//对存在或不存在的文件或设备采取的操作。 DWORD dwFlagsAndAttributes,//文件或设备属性和标志,FILE_ATTRIBUTE_NORMAL是文件最常见的默认值。 HANDLE hTemplateFile//具有GENERIC_READ访问权限的模板文件的有效句柄。模板文件为正在创建的文件提供文件属性和扩展属性。此参数可以为NULL。 );*/ int x = 500; DWORD p = 0; ReadFile(hDevice, &x, 4, &p, NULL);//从指定的文件或输入/输出 (I/O) 设备读取数据 /* BOOL ReadFile( HANDLE hFile,//设备句柄 LPVOID lpBuffer,//指向接收从文件或设备读取的数据的缓冲区的指针。 DWORD nNumberOfBytesToRead,//要读取的最大字节数。 LPDWORD lpNumberOfBytesRead,/一个指向接收使用同步hFile参数时读取的字节数的变量的指针 LPOVERLAPPED lpOverlapped );*/ CloseHandle(hDevice); printf("%drn", x); system("pause"); return 0; }
这是不开驱动的情况
开了驱动
成功通信
IRP_MJ_DEVICE_CONTROL 通信
驱动
复制代码
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#include <ntifs.h> #define DEVICE_NAME L"\Device\wangliang"//设备名 #define SYM_NAME L"\??\wangliang" #define CODE_CTR_INDEX 0x800//为以上设备类型定义一个设备的唯一标识功能号。CODE的唯一标识功能号用十六进制表示,转换为十进制后的有效范围是:0 - 2047是保留给微软; 代码2048 - 4095是为OEM和IHV保留。其它功能代码定义大于4095。 #define TEST CTL_CODE(FILE_DEVICE_UNKNOWN,CODE_CTR_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)//用于创建一个唯一的32位系统I/O控制代码 /* void CTL_CODE( DeviceType,//设备类型,高16位(16-31位) Function,//包含功能函数值 Method,//包含有关如何为 I/O 和 FS 控件传递缓冲区的方法代码 Access//访问限制,14-15位 ); ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) */ NTSTATUS DefDispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp) { Irp->IoStatus.Status = STATUS_SUCCESS;//完成请求时设置这个结构 IoCompleteRequest(Irp, 0);//调用方已完成所有I/O请求处理操作,并将给定的 IRP 返回给 I/O 管理器 /* void IofCompleteRequest( PIRP Irp,//指向要完成的 IRP 的指针 CCHAR PriorityBoost ); */ return STATUS_SUCCESS; } NTSTATUS Dispatch(DEVICE_OBJECT* DeviceObject, IRP* Irp) { PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);//返回一个指向IO_STACK_LOCATION结构的指针 DbgBreakPoint(); if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)//判断类型是不是这个 { int size = ioStack->Parameters.DeviceIoControl.InputBufferLength; int OutputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength; ULONG IoControlCode = ioStack->Parameters.DeviceIoControl.IoControlCode; switch (IoControlCode)//判断控制代码 { case TEST: { int* x = (int*)Irp->AssociatedIrp.SystemBuffer; DbgPrint("[db]:-------%x----------rn", *x); } break; } } Irp->IoStatus.Status = STATUS_SUCCESS;//设置成功 IoCompleteRequest(Irp, 0); return STATUS_SUCCESS; } VOID DriverUnload(PDRIVER_OBJECT pDriver) { UNICODE_STRING symName = { 0 }; RtlInitUnicodeString(&symName, SYM_NAME); IoDeleteSymbolicLink(&symName);//删除符号链接 IoDeleteDevice(pDriver->DeviceObject); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) { UNICODE_STRING unName = { 0 }; RtlInitUnicodeString(&unName, DEVICE_NAME);//初始化一个Unicode的字符串,设备名 UNICODE_STRING symName = { 0 }; RtlInitUnicodeString(&symName, SYM_NAME);//函数名 PDEVICE_OBJECT pDevice = NULL; NTSTATUS status = IoCreateDevice(pDriver, 0, &unName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);//创建一个驱动设备使用的设备对象 /* NTSTATUS IoCreateDevice( PDRIVER_OBJECT DriverObject,//指向调用者的驱动程序对象的指针 ULONG DeviceExtensionSize,//指定要为设备对象的设备扩展分配的驱动程序确定的字节数 PUNICODE_STRING DeviceName,//命名设备对象 DEVICE_TYPE DeviceType,//指定设备类型的值 ULONG DeviceCharacteristics,//提供有关驱动程序设备的附加信息 多数驱动程序为此参数指定 FILE_DEVICE_SECURE_OPEN BOOLEAN Exclusive,//指定设备对象是否代表独占设备。多数驱动程序将此值设置为FALSE PDEVICE_OBJECT *DeviceObject//指向变量的指针,该变量接收指向新创建的DEVICE_OBJECT结构的指针 );*/ if (!NT_SUCCESS(status)) { DbgPrint("[db]:%xrn", status); //DbgPrintEx(77, 0, ""); return status; } status = IoCreateSymbolicLink(&symName, &unName);//设备名和用户的可见名之间创建符号链接 /* NTSTATUS IoCreateSymbolicLink( PUNICODE_STRING SymbolicLinkName,//用户的可见名 PUNICODE_STRING DeviceName//指向设备对象名称 );*/ if (!NT_SUCCESS(status)) { IoDeleteDevice(pDevice); DbgPrint("[db]:%xrn", status); return status; } pDevice->Flags &= ~DO_DEVICE_INITIALIZING;//干掉这个位 符号链接->设备对象->驱动对象->功能函数 pDevice->Flags |= DO_BUFFERED_IO; pDriver->MajorFunction[IRP_MJ_CREATE] = DefDispatch;//设置回调函数 pDriver->MajorFunction[IRP_MJ_CLOSE] = DefDispatch; pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch; //"\device\null" //有些游戏 加跳板可以,有些游戏追跳板 BE//jmp 我的函数 E8 E9 mov rax,0x11345678 push 0x123465678 //遍历驱动 找到驱动路径,打开驱动文件,对比代码段 //我之前lock文件, WIN7 走是HOOK WIN10走是WIN10 pDriver->DriverUnload = DriverUnload; return status; }
接收
复制代码
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#include <stdio.h> #include <Windows.h> #include <winioctl.h> #define SYM_NAME "\\.\wangliang" #define CODE_CTR_INDEX 0x800//为以上设备类型定义一个设备的唯一标识功能号。CODE的唯一标识功能号用十六进制表示,转换为十进制后的有效范围是:0 - 2047是保留给微软; 代码2048 - 4095是为OEM和IHV保留。其它功能代码定义大于4095。 #define TEST CTL_CODE(FILE_DEVICE_UNKNOWN,CODE_CTR_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)//用于创建一个唯一的32位系统I/O控制代码 int main() { HANDLE hDevice = CreateFileA(SYM_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* HANDLE CreateFileA( LPCSTR lpFileName,//要创建或打开的文件或设备的名称 DWORD dwDesiredAccess,//权限 DWORD dwShareMode,//请求的文件或设备的共享模式 LPSECURITY_ATTRIBUTES lpSecurityAttributes,//指向SECURITY_ATTRIBUTES 结构的指针,该结构包含两个独立但相关的数据成员:一个可选的安全描述符,以及一个确定返回的句柄是否可以被子进程继承的布尔值。此参数可以为NULL。如果此参数为NULL,则CreateFile返回的句柄 不能由应用程序可能创建的任何子进程继承,并且与返回的句柄关联的文件或设备获得默认安全描述符。 DWORD dwCreationDisposition,//对存在或不存在的文件或设备采取的操作。 DWORD dwFlagsAndAttributes,//文件或设备属性和标志,FILE_ATTRIBUTE_NORMAL是文件最常见的默认值。 HANDLE hTemplateFile//具有GENERIC_READ访问权限的模板文件的有效句柄。模板文件为正在创建的文件提供文件属性和扩展属性。此参数可以为NULL。 );*/ int x = 100; DWORD p = 0; BOOL b = DeviceIoControl(hDevice, TEST, x, 4, NULL, NULL , &p, NULL);//直接向指定的设备驱动程序发送控制代码,使相应的设备执行相应的操作。 /* BOOL DeviceIoControl( HANDLE hDevice,//要在其上执行操作的设备的句柄 DWORD dwIoControlCode,//操作的控制代码。此值标识要执行的特定操作以及执行该操作的设备类型。 LPVOID lpInBuffer,//指向包含执行操作所需数据的输入缓冲区的指针 DWORD nInBufferSize,//输入缓冲区的大小 LPVOID lpOutBuffer,//指向输出缓冲区的指针 DWORD nOutBufferSize,//输出缓冲区的大小 LPDWORD lpBytesReturned,//一个指向变量的指针 LPOVERLAPPED lpOverlapped );*/ CloseHandle(hDevice); printf("%drn", b); system("pause"); return 0; }
第一个是ReadFile实现的通信,这个是DeviceIoControl实现的通信
方式
METHOD_BUFFERED:直接把值传入内核中去
METHOD_IN_DIRECT/METHOD_OUT_DIRECT:把物理页映射到内核地址中,修改哪一边都一起修改
METHOD_NEITHER:直接操作地址
最后
以上就是文静航空最近收集整理的关于驱动与R3的通信IRP_MJ_READ 通信IRP_MJ_DEVICE_CONTROL 通信方式的全部内容,更多相关驱动与R3的通信IRP_MJ_READ内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复