今顺便再来搞搞这个 IRP_MJ_READ 和 IRP_MJ_WRITE 等事件。

应用层读写设备文件

写文件

同样在函数的 SWITCH 分发中添加 case,然后在 DriverEntry 中注册回调,我们先了解三个指针,这里后面有大用,这三个指针是传参的三种方式。

1
2
3
4
5
6
7
case IRP_MJ_WRITE: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
break;
}

WriteFile 是 ring3 向 ring0 写入数据的一个过程,因此我们在 ring0 层要拷贝 UserBuffer 里面的内容。

在应用层,我们调用 WriteFile 函数向驱动层写数据。

1
2
3
4
5
6
void WriteF() {
DWORD written;
char buffer[] = "xia0ji233 write file now!";
WriteFile(DeviceHandle, buffer, sizeof(buffer), &written, 0);
printf("written=%d\n", written);
}

然后我们补充完整一下驱动层的事件。

1
2
3
4
5
6
7
8
9
10
case IRP_MJ_WRITE: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
int len = strlen(ptr1);
kprintf(("Line %d:xia0ji233: ring3 write string %s,len=%d\n"), __LINE__, ptr1,len);
pirp->IoStatus.Information = len;//返回
break;
}

具体就是打印指针,打印指针指向的内容,以及返回传入的数据长度。

来看看测试结果:

读设备

其实差不多,只不过我们这次用 ReadFile,其实和读一个文件差不多,只不过相应的我们要在 ring0 响应这个读取的事件。

应用层代码:

1
2
3
4
5
6
void ReadF() {
DWORD readden;
char buffer[512] = { 0 };
ReadFile(DeviceHandle, buffer, 0x20, &readden, 0);
printf("Read String:%s readden=%d\n", buffer, readden);
}

内核层代码:

1
2
3
4
5
6
7
8
9
10
11
12
case IRP_MJ_READ: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
char msg[] = "xia0ji233 Read file";
if (ptr1&&irpStackL->Parameters.Read.Length > sizeof(msg)) {
strcpy(ptr1, msg);
pirp->IoStatus.Information = sizeof(msg);
}
break;
}

建立一个 IRP_MJ_READ 的 case 就好了。

测试结果:

最终代码

驱动代码:

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
141
142
143
144
145
146
147
148
149
150
151
152
153
#include<ntifs.h>
#define SYMBOL L"\\??\\xia0ji2333"
#define kprintf(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, ##__VA_ARGS__)
#define WriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadWriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x805,METHOD_BUFFERED, FILE_ANY_ACCESS)

void DeleteDevice(PDRIVER_OBJECT);

NTSTATUS CreateDevice(PDEVICE_OBJECT driver) {
NTSTATUS status;
UNICODE_STRING MyDriver;
PDEVICE_OBJECT device = NULL;
RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\xia0ji233");
status = IoCreateDevice(
driver,
sizeof(driver->DeviceExtension),
&MyDriver,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&device
);
if (status == STATUS_SUCCESS) {
UNICODE_STRING Sym;
RtlInitUnicodeString(&Sym, SYMBOL);
status = IoCreateSymbolicLink(&Sym, &MyDriver);
if (status == STATUS_SUCCESS) {
kprintf(("Line %d:xia0ji233: symbol linked success\n"), __LINE__);
}
else {
kprintf(("Line %d:xia0ji233: symbol linked failed status=%x\n"), __LINE__, status);
}
}
else {
kprintf(("Line %d:xia0ji233: create device fail status=%x\n"), __LINE__, status);
}
}
NTSTATUS DeviceIrpCtl(PDEVICE_OBJECT driver, PIRP pirp) {
kprintf(("Line %d:xia0ji233: enter IRP Function\n"), __LINE__);
PIO_STACK_LOCATION irpStackL;
ULONG CtlCode;
ULONG InputBuffLength;
irpStackL = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的参数
switch (irpStackL->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL: {
UINT32 code = irpStackL->Parameters.DeviceIoControl.IoControlCode;
kprintf(("Line %d:xia0ji233: ring3 calls DEVICE CONTROL,control code=%x\n"), __LINE__, code);
switch (code) {
case WriteCode: {
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: Get Message:%s\n"), __LINE__, buffer);
break;
}
case ReadCode: {
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
char msg[] = "xia0ji233 in ring0";
kprintf(("Line %d:xia0ji233: return Message:%s\n"), __LINE__, msg);
memcpy(buffer, msg, sizeof(msg));
pirp->IoStatus.Information = sizeof(msg);
break;
}
case ReadWriteCode: {
typedef struct AB {
int a, b;
}AB;
char * buffer = (char *)pirp->AssociatedIrp.SystemBuffer;
AB *s = (AB *)buffer;
kprintf(("Line %d:xia0ji233:get two number %d and %d\n"), __LINE__, s->a, s->b);
int result = s->a + s->b;
memcpy(buffer, &result, sizeof(result));
pirp->IoStatus.Information = sizeof(result);
break;
}
}

break;
}
case IRP_MJ_CREATE: {
kprintf(("Line %d:xia0ji233: ring3 calls CREATE\n"), __LINE__);
break;
}
case IRP_MJ_CLOSE: {
kprintf(("Line %d:xia0ji233: ring3 calls CLOSE\n"), __LINE__);
break;
}
case IRP_MJ_READ: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
char msg[] = "xia0ji233 Read file";
if (ptr1&&irpStackL->Parameters.Read.Length > sizeof(msg)) {
strcpy(ptr1, msg);
pirp->IoStatus.Information = sizeof(msg);
}
break;
}
case IRP_MJ_WRITE: {
char *ptr1 = pirp->UserBuffer;
char *ptr2 = pirp->MdlAddress;
char *ptr3 = pirp->AssociatedIrp.SystemBuffer;
kprintf(("Line %d:xia0ji233: ring3 calls ReadFile ptr1=%p ptr2=%p ptr3=%p\n"), __LINE__, ptr1, ptr2, ptr3);
int len = strlen(ptr1);
kprintf(("Line %d:xia0ji233: ring3 write string %s,len=%d\n"), __LINE__, ptr1,len);
pirp->IoStatus.Information = len;
break;
}
default:
break;
}
pirp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
kprintf(("Line %d:xia0ji233: leave IRP Function\n"), __LINE__);
return STATUS_SUCCESS;

}

void DriverUnload(PDRIVER_OBJECT pDriver) {
kprintf(("Line %d:xia0ji233: start unload\n"), __LINE__);
DeleteDevice(pDriver);
}

NTSTATUS DriverEntry(
_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath
) {
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_READ] = DeviceIrpCtl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DeviceIrpCtl;
CreateDevice(DriverObject);
kprintf(("Line %d:xia0ji233: RegistryPath = %S\n"), __LINE__, RegistryPath->Buffer);
kprintf(("Line %d:xia0ji233: work success\n"), __LINE__);

return 0;
}

void DeleteDevice(PDRIVER_OBJECT pDriver) {
kprintf(("Line %d:xia0ji233: start delete device\n"), __LINE__);
if (pDriver->DeviceObject) {
//删除符号链接
UNICODE_STRING Sym;//符号链接名字
RtlInitUnicodeString(&Sym, SYMBOL);//CreateFile
kprintf(("Line %d:xia0ji233: Delete Symbol\n"), __LINE__);
IoDeleteSymbolicLink(&Sym);
kprintf(("Line %d:xia0ji233: Delete Device\n"), __LINE__);
IoDeleteDevice(pDriver->DeviceObject);//删除设备对象
}
kprintf(("Line %d:xia0ji233: end delete device\n"), __LINE__);
}

应用程序代码:

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
#include <iostream>
#include <Windows.h>
#define SYMBOL L"\\??\\xia0ji2333"
#define WriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ReadWriteCode CTL_CODE (FILE_DEVICE_UNKNOWN,0x805,METHOD_BUFFERED, FILE_ANY_ACCESS)

HANDLE DeviceHandle;
void menu() {
printf("------------------------\n");
printf("1.create\n");
printf("2.close\n");
printf("3.wtest\n");
printf("4.rtest\n");
printf("5.Read Write test\n");
printf("6.ReadFile test\n");
printf("7.WriteFile test\n");
printf("8.exit\n");
printf("------------------------\n");
printf("Your choice:");
}
void create() {
DeviceHandle = CreateFile(SYMBOL, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
void close() {
CloseHandle(DeviceHandle);
}
void Wtest() {
DWORD dwRetSize = 0;//返回字节数
char *inBuf = (char *)malloc(0x20);
char *OutBuf = (char *)malloc(0x20);
printf("Your message>");
scanf("%30s", inBuf);

DeviceIoControl(
DeviceHandle,//CreateFile打开驱动设备 返回的句柄
WriteCode,//控制码 CTL_CODE
inBuf,//输入缓冲区指针
strlen(inBuf) + 1,//输入缓冲区大小
OutBuf,//返回缓冲区
20,//返回缓冲区大小
&dwRetSize,//返回字节数
NULL
);
printf("control code=%x\n", WriteCode);
}
void Rtest() {
DWORD dwRetSize = 0;//返回字节数
char *OutBuf = (char *)malloc(0x20);

DeviceIoControl(
DeviceHandle,//CreateFile打开驱动设备 返回的句柄
ReadCode,//控制码 CTL_CODE
NULL,//输入缓冲区指针
0,//输入缓冲区大小
OutBuf,//返回缓冲区
30,//返回缓冲区大小
&dwRetSize,//返回字节数
NULL
);
printf("control code=%x return value=%d\n", WriteCode, dwRetSize);
printf("get message from ring0:%s\n", OutBuf);
}
void WRtest() {
DWORD dwRetSize = 0;//返回字节数
typedef struct AB {
int a, b;
}AB;
AB InBuf;
int result;
printf("two number>");
scanf("%d%d", &InBuf.a, &InBuf.b);
DeviceIoControl(
DeviceHandle,//CreateFile打开驱动设备 返回的句柄
ReadWriteCode,//控制码 CTL_CODE
&InBuf,//输入缓冲区指针
sizeof(AB),//输入缓冲区大小
&result,//返回缓冲区
4,//返回缓冲区大小
&dwRetSize,//返回字节数
NULL
);
printf("control code=%x return value=%d\n", ReadWriteCode, dwRetSize);
printf("get result from ring0:%d\n", result);
}
void ReadF() {
DWORD readden;
char buffer[512] = { 0 };
ReadFile(DeviceHandle, buffer, 0x20, &readden, 0);
printf("Read String:%s readden=%d\n", buffer, readden);
}
void WriteF() {
DWORD written;
char buffer[] = "xia0ji233 write file now!";
WriteFile(DeviceHandle, buffer, sizeof(buffer), &written, 0);
printf("written=%d\n", written);
}
int main()
{
while (1) {
int ch;
menu();
scanf("%d", &ch);
switch (ch)
{
case 1:
create();
break;
case 2:
close();
break;
case 3:
Wtest();
break;
case 4:
Rtest();
break;
case 5:
WRtest();
break;
case 6:
ReadF();
break;
case 7:
WriteF();
break;
default:
exit(0);
break;
}
}
}