我是靠谱客的博主 高高短靴,这篇文章主要介绍内核模块字符相关处理,现在分享给大家,希望可以做个参考。

学习自:

B站:写驱动的女装大佬 《–从零开始造核弹—windows驱动程序开发(中级篇-4课)》
感谢大佬制作高水准视频!!

学习笔记

一、初始化字符串 :
RtlInitUnicodeString(&deviceanme, DEVICE_NAME)

复制代码
1
2
3
4
5
6
7
8
9
10
11
#define DEVICE_NAME L"\Device\MyfirstDevice" //定义一个驱动的名字 UNICODE_STRING deviceanme = { 0 };//初始一个存储设备名字的内存空间 RtlInitUnicodeString(&deviceanme, DEVICE_NAME);//初始化一个字符串 DbgPrint("--:%wZ--n",&deviceanme);

二、初始化字符串2:
RTL_CONSTANT_STRING(DEVICE_NAME);
此方法有局限性,如果确定字符100%不能进行修改就可以用这个

复制代码
1
2
3
4
5
#define DEVICE_NAME L"\Device\MyfirstDevice" //定义一个驱动的名字 UNICODE_STRING deviceanme = RTL_CONSTANT_STRING(DEVICE_NAME);//初始一个字符串 DbgPrint("--:%wZ--n",&deviceanme);

三、初始化字符串3:

复制代码
1
2
3
4
5
6
PWCHAR testbuffer = ExAllocatePool(NonPagedPool, 0x1000);//创建一个空指针 RtlZeroMemory(testbuffer, 0x1000);// 缓冲区清零 RtlCopyMemory(testbuffer, L'FFFFFFFFFF', sizeof(L'FFFFFFFFFF'));//拷贝一个字符串到缓冲区 RtlInitUnicodeString(&deviceanme, testbuffer);//初始字符串 DbgPrint("--:%wZ--n",&deviceanme);

四、窄字符转宽字符:
RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//窄字符转宽字符

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
UNICODE_STRING deviceanme = { 0 };//初始一个存储宽字符的内存空间 PCHAR tempbuffer = "C:\123\321\567\123.txt"; //赋值一个字符串 STRING str = { 0 };//定义一个窄字符存储空间 RtlInitString(&str,tempbuffer);//把字符串初始到窄字符空间 //参数1:宽字符存储位置 //参数2:需要转换的字符 //参数3:是否给参数1申请一个内存空间 RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//把窄字符转换到宽字符 DbgPrint("--:%wZ--n",&deviceanme); RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间

五、字符串之间的复制,及小写字母转大写字母
RtlCopyUnicodeString(&targeunicode,&deviceanme); 字符串拷贝
RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE); 小写字符转大写

复制代码
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
UNICODE_STRING targeunicode = { 0 };//定义一个缓冲区 targeunicode.Buffer = ExAllocatePool(NonPagedPool, 0x1000);//给缓存区分配一个指针 targeunicode.MaximumLength = 0x1000;//设置缓冲区的长度 PCHAR tempbuffer = "C:\123\321\567\123.txt"; STRING str = { 0 }; RtlInitString(&str,tempbuffer); RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE); //参数1:目标 //参数2:源字符串 RtlCopyUnicodeString(&targeunicode,&deviceanme); //参数1可以与参数2相同,也可以是另外一个地址空间 //参数1是被转换后的大写字母存放位置 //参数2是需要进行转换的小写字母 //参数3:是否需要为参数一的地址分配一个空间 FALSE 是不要分配空间,TRUE是要分配空间 RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE);//小写字符串转换为大写 RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间 ExFreePool(targeunicode.Buffer);//释放空间,一般要先清零后再释放,这里没有写清零

六、字符串安全的复制,追加, 查找前缀,比较两个字符是否相等,查找字符串
需要引用这个头文件 #include <ntstrsafe.h>
RtlStringCbCopyW(tempbuffer2, 0x1000, L"??");拷贝函数
RtlStringCbCatW(tempbuffer2, 0x1000, L"C:123AAAbbbaaa.txt"); 追加字符
RtlPrefixUnicodeString(&temp2, &temp1, FALSE)// 前缀,判断参数1是否是参数2的前缀

FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL))//搜索字符串
//这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写
RtlInitUnicodeString(&temp5, L"AAA");//设置查找条件
在参数2中查找是否包含参数1
使用FsRtlIsNameInExpression需要引入#include <ntifs.h> 而且要放在 #include <ntddk.h>前面,否则会报错

复制代码
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
PWCHAR tempbuffer2 = ExAllocatePool(NonPagedPool, 0x1000); RtlZeroMemory(tempbuffer2, 0x1000);//得到一片被清空的内存 //拷贝字符串 //参数1:一个内存空间 //参数2:一个缓冲区的长度,就是参数1空间的长度 //参数3:要复制的内容 RtlStringCbCopyW(tempbuffer2, 0x1000, L"\??\");//安全的字符拷贝 //参数3:要追加的字符串 RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\123\AAA\bbb\aaa.txt");//追加字符串 UNICODE_STRING temp1 = { 0 }, temp2 = { 0 }; RtlInitUnicodeString(&temp1, tempbuffer2); RtlInitUnicodeString(&temp2, L"\??\"); //字符串前缀判断 //判断一个字符串是否是另外一个字符串的头部,或者说是前缀 //判断参数1是否是参数2的前缀 //参数3是大小写是否敏感 if (RtlPrefixUnicodeString(&temp2, &temp1, FALSE)) { //如果是前缀就打印这个 DbgPrint("Be Finden"); } UNICODE_STRING temp3 = { 0 }, temp4 = { 0 }; RtlInitUnicodeString(&temp3, L"D:\ABc\AAA\ddd\aaa.txt"); RtlInitUnicodeString(&temp4, L"D:\ABc\AAA\DDD\aaa.txt"); //字符串比较 //参数1与参数2进行比较 //参数3是大小写是否敏感 if (RtlEqualUnicodeString(&temp3, &temp4, TRUE)) { //字符串比较 DbgPrint("temp3=temp4n"); } //搜索字符串 UNICODE_STRING temp5 = { 0 }; //这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写 RtlInitUnicodeString(&temp5, L"*AAA*"); //查找字符串 //参数1就是搜索条件 //在参数2中查找是否包含参数1 //如果第三个参数是TRUE ,搜索条件字母必须全部大写,这样就能做到精准搜索 if (FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL)) { //查找到了就打印下面 DbgPrint("Searchedn"); } DbgPrint("--%ws--n", tempbuffer2);//大于出追加的字符串

完整测试代码

复制代码
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <ntifs.h>//必须放在前面 #include <ntddk.h> #include <windef.h> #include <ntstrsafe.h>//提供以下比较安全的函数 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) { NTSTATUS status = STATUS_SUCCESS; //定义一个返回值 UNICODE_STRING deviceanme = { 0 };//初始一个存储设备名字的内存空间 //UNICODE_STRING deviceanme = RTL_CONSTANT_STRING(DEVICE_NAME);//初始一个存储设备名字的内存空间 (方式二) PDEVICE_OBJECT pdevice = NULL; //设备创建后的输出参数,如果不为NULL就表示设备创建成功了 driver->DriverUnload = DrvUnload; //------字符串的操作测试开始-------- UNICODE_STRING targeunicode = { 0 };//定义一个缓冲区 targeunicode.Buffer = ExAllocatePool(NonPagedPool, 0x1000);//给缓存区分配一个指针 targeunicode.MaximumLength = 0x1000;//设置缓冲区的长度 PCHAR tempbuffer = "C:\123\AAA\bbb\aaa.txt"; STRING str = { 0 }; //定义一个窄字符串 RtlInitString(&str, tempbuffer);//初始化一个字符串 RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//窄字符转换为宽字符 RtlCopyUnicodeString(&targeunicode, &deviceanme);//复制字串 RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE);//小写字符串转换为大写 DbgPrint("--%wZ--n", &deviceanme); ExFreePool(targeunicode.Buffer);//释放空间,一般要先清零后再释放,这里没有写清零 RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间 //------字符串的操作测试结尾-------------- //------字符串安全操作测试开始----------- PWCHAR tempbuffer2 = ExAllocatePool(NonPagedPool, 0x1000); RtlZeroMemory(tempbuffer2, 0x1000);//得到一片被清空的内存 //拷贝字符串 //参数1:一个内存空间 //参数2:一个缓冲区的长度,就是参数1空间的长度 //参数3:要复制的内容 RtlStringCbCopyW(tempbuffer2, 0x1000, L"\??\");//安全的字符拷贝 //参数3:要追加的字符串 RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\123\AAA\bbb\aaa.txt");//追加字符串 UNICODE_STRING temp1 = { 0 }, temp2 = { 0 }; RtlInitUnicodeString(&temp1, tempbuffer2); RtlInitUnicodeString(&temp2, L"\??\"); //字符串前缀判断 //判断一个字符串是否是另外一个字符串的头部,或者说是前缀 //判断参数1是否是参数2的前缀 //参数3是大小写是否敏感 if (RtlPrefixUnicodeString(&temp2, &temp1, FALSE)) { //如果是前缀就打印这个 DbgPrint("Be Finden"); } UNICODE_STRING temp3 = { 0 }, temp4 = { 0 }; RtlInitUnicodeString(&temp3, L"D:\ABc\AAA\ddd\aaa.txt"); RtlInitUnicodeString(&temp4, L"D:\ABc\AAA\DDD\aaa.txt"); //字符串比较 //参数1与参数2进行比较 //参数3是大小写是否敏感 if (RtlEqualUnicodeString(&temp3, &temp4, TRUE)) { //字符串比较 DbgPrint("temp3=temp4n"); } //搜索字符串 UNICODE_STRING temp5 = { 0 }; //这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写 RtlInitUnicodeString(&temp5, L"*AAA*"); //查找字符串 //参数1就是搜索条件 //在参数2中查找是否包含参数1 //如果第三个参数是TRUE ,搜索条件字母必须全部大写,这样就能做到精准搜索 if (FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL)) { //查找到了就打印下面 DbgPrint("Searchedn"); } DbgPrint("--%ws--n", tempbuffer2);//大于出追加的字符串 //------字符串安全操作结尾----------- RtlInitUnicodeString(&deviceanme, DEVICE_NAME);//初始化一个字符串,这个是符合连接用的 /* * IoCreateDevice创建设备 参数1:driver 设备对象; 参数2:0 设备扩展的大小; 参数3:&deviceanme 设备名字; 参数4:FILE_DEVICE_UNKNOWN(未知设备) 设备类型 参数5:0 默认参数 参数6:TRUE 默认参数 参数7:&pdevice 输出参数,设备创建成功后,会把设备对象传出来 */ status = IoCreateDevice(driver,200, &deviceanme, FILE_DEVICE_UNKNOWN,0,TRUE,&pdevice); if (!NT_SUCCESS(status)) { //如果设备创建设备就打印下面的信息 DbgPrint("Create Device Failed:%xn",status); //返回错误信息 return status; } //设备的读写方式(必须设置,否则蓝屏) pdevice->Flags |= DO_BUFFERED_IO; //到这里 设备就创建成功了 UNICODE_STRING symname = { 0 };//定义一个符号连接名称 RtlInitUnicodeString(&symname, SYM_NAME);//初始化一个字符串 /*IoCreateSymbolicLink创建符号连接 参数1:&symname 符号连接名字 参数2:&deviceanme 设备名字 */ status = IoCreateSymbolicLink(&symname, &deviceanme); if (!NT_SUCCESS(status)) { //如果创建符号连接失败就打印下面的信息 DbgPrint("Create SymbolicLink Failed:%xn", status); //既然创建符号连接失败,就要删除这个设备 IoDeleteDevice(pdevice); //返回错误信息 return status; } //到这里 符号连接就创建成功了 //驱动的功能都写在下面,派遣函数 //打开设备 driver->MajorFunction[IRP_MJ_CREATE] = MyCreate; //关闭设备 driver->MajorFunction[IRP_MJ_CLOSE] = MyClose; //清理设备 driver->MajorFunction[IRP_MJ_CLEANUP] = MyCleanUp; //读取,应用层把内核数据读取出去 driver->MajorFunction[IRP_MJ_READ] = MyRead; //写入取,应用层把数据写入内核 driver->MajorFunction[IRP_MJ_WRITE] = MyWrite; //自定义控制 driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyControl; return 0; }

最后

以上就是高高短靴最近收集整理的关于内核模块字符相关处理的全部内容,更多相关内核模块字符相关处理内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(104)

评论列表共有 0 条评论

立即
投稿
返回
顶部