Minifilter过滤,功能实现对驱动⽬录的监控,包括创建,重命名,删除并实现hips 注意下:我的这套过滤只能⽤在nt6系统上
原因是使⽤⼀个nt6上才有的函数
见函数
PsGetProcessFullName
其实没必要⾃⼰来写获取全路径
因为minifilter已经给我们提供了获取全路径的函数
FltGetFileNameInformation
我就不改了,哈哈
说说遇到的问题吧
在监控创建的时候,我是在post中监控,我拒绝后,会弹窗,2-3次吧,也就是会请求2-3次,我的解决⽅法是记录上⼀次拒绝的⽂件全路径,然后下⼀次来的时候来⽐对
这⾥可以将处理过的⽂件加⼊链表或者hash,我偷懒了,就直接⽤这种⽅法来解决多重求情的问题,
这⾥注意下,出现多次请求的原因是你第⼀次放⾏了,那么我们第⼆次的时候就知道⽐对的时候就直接放⾏了
考虑过在pre中监控
但根据MF周⽼师的意见说在这⾥拿到的信息是不准确的,
可以⽤下⾯⼀句话总结:
在pre中是对请求本⾝就⾏拦截,在post中是对请求完成结果的拦截.
遵循周⽼师的意见,我还是在post中监控
在拦截创建的时候,还有⼀个问题,就是如果创建的时候我拒绝了,那么返回给⽤户的会出现⼀个替换的框(⽂件已存在,但⼤⼩是0)
针对这个情况,我直接对这个data设置⽂件属性有点像前⾯学习的IRP下发强删⽂件
[cpp]
1. //就算拒绝了也会创建⼀个空⽂件这⾥我们删除
2. fdi.DeleteFile = TRUE;
3. FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
//就算拒绝了也会创建⼀个空⽂件这⾥我们删除
fdi.DeleteFile = TRUE;
FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
在post中我们可以使⽤FltCancelFileOpen 或者FltCancelFileIrp(未)来取消前⾯的操作
还有⼀点是,刚开始写的时候我直接对Create的回调函数进⾏过滤,没有判断⽂件打开的属性,或是⽂件还是⽂件夹
然后⼀直弹窗,然后你懂得....
然后就修复了对⽂件夹的判断和打开的判断
这⾥其实是有BUG的为什么这么说呢,在CreateFile的函数中我们可以⽤FILE_OPEN_IF创建⽂件这⾥没有过滤
这⾥不应该在内核中过滤原因是如果这⾥填写了对FILE_OPEN_IF的过滤,会不断弹窗,⽽且这个时候在这⾥已经不能判断⽂件是否存在了已经完成了
已经⽣成了⼀个⽂件⼀个为空的⽂件
那么怎么办呢,思路是得到此时⽂件的⼤⼩,如果是0则是新建,否则就是打开操作
获取⼤⼩的⽅法我知道的是通过FltReadFile去读⽂件然后BytesRead就是⽂件的⼤⼩
还有⼀个思路就是在pre中过滤,此时⽂件还没有创建,我们得到⽂件的全路径,然后打开,如果返回NO_FOUND就说明是新建操作
下⾯是对⽂件夹的判断
[cpp]
1. if (!NT_SUCCESS( Data->IoStatus.Status ) ||
2. (STATUS_REPARSE == Data->IoStatus.Status)) {
3.
4. return FLT_POSTOP_FINISHED_PROCESSING;
5. }
6.
7. Options = Data->Iopb->Parameters.Create.Options;
8.
9. if (FlagOn(Options, FILE_DIRECTORY_FILE) ||
10. FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||
12. {
13. return FLT_POSTOP_FINISHED_PROCESSING;
14. }
15.
16. ulDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
17. if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
18. {
19. PopWindow = TRUE;
20. }
if (!NT_SUCCESS( Data->IoStatus.Status ) ||
(STATUS_REPARSE == Data->IoStatus.Status)) {
return FLT_POSTOP_FINISHED_PROCESSING;
}
Options = Data->Iopb->Parameters.Create.Options;
if (FlagOn(Options, FILE_DIRECTORY_FILE) ||
FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||
FlagOn(Data->Flags, SL_OPEN_PAGING_FILE))
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
ulDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
{
PopWindow = TRUE;
}
另外遇到的问题是删除
删除分两种
⼀种是直接删除也就是shift+Del的⽅式
这种没什么问题
另外⼀种普通的删除,右键⽂件-删除-或者直接按Del
这其实⼀个发现 + 更名的操作
这个发现具体我也不知道怎么说,因为你普通删除⽂件的时候,不是有⼀个正在发现⽂件吗,就是统计⽂件的⼤⼩操作
然后就是更名的操作
这是我第⼀次实验时出现的情况
我的操作是普通删除->放⾏->然后就出现了这个框
有了这个后就简单了,在PreSetInforMation中获得⽂件全路径,匹配如果中间有Recycle.Bin的字符串
但这不是准确的,我也偷懒啦
⾄于重命名⽆⾮就是拿到重命名后的路径
两种⽅法
1.直接在buffer中拿
2.FltGetDestinationFileNameInformation获得
不懂的是:重命名的路径能直接在buffer中拿到为什么还要使⽤FltGetDestinationFileNameInformation呢,知道的⼈可以回复下
[cpp]
1. pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
2.
3. /*
4. //这也是可⾏的
5. wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1);
6. if(wstrTest == NULL)
文件不能删除怎么办7. leave;
8.
9. memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1);
10.
11. wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength);
12. DbgPrint("%ws\n",wstrTest);*/
13.
14.
15. status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo-
>FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo);
16. if(!NT_SUCCESS(status))
17. {
18. DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
19. leave;
20. }
21. wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);
22.
23. DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);
24.
25. FltReleaseFileNameInformation(pOutReNameinfo);
pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
/*
//这也是可⾏的
wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1);
if(wstrTest == NULL)
leave;
memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1);
wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength);
DbgPrint("%ws\n",wstrTest);*/
status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo); if(!NT_SUCCESS(status))
{
DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
leave;
}
wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);
DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);
FltReleaseFileNameInformation(pOutReNameinfo);
其他没什么了就是R3的处理了,我对创建多次请求的判断是放在R3的
核⼼⽂件:R0
[cpp]
1. #include <fltKernel.h>
2. #include <dontuse.h>
3. #include <suppress.h>
4. #include "scanuk.h"
5. #include "scanner.h"
6.
7. #pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")
8.
9.
10. NTSTATUS
11. PsReferenceProcessFilePointer (
12. IN PEPROCESS Process,
13. OUT PVOID *OutFileObject
14. );
15.
16. SCANNER_DATA ScannerData;
17.
18. UNICODE_STRING g_LastDelFileName = {0};
19.
20. //
21. // This is a static list of file name extensions files we are interested in scanning
22. //
23.
24. const UNICODE_STRING ScannerExtensionsToScan[] =
25. { RTL_CONSTANT_STRING( L"doc"),
26. RTL_CONSTANT_STRING( L"txt"),
27. RTL_CONSTANT_STRING( L"bat"),
28. RTL_CONSTANT_STRING( L"cmd"),
29. RTL_CONSTANT_STRING( L"inf"),
30. /*RTL_CONSTANT_STRING( L"ini"), Removed, to much usage*/
31. {0, 0, NULL}
32. };
33.
34.
35. //
36. // Function prototypes
37. //
38.
39. NTSTATUS
40. ScannerPortConnect (
41. __in PFLT_PORT ClientPort,
42. __in_opt PVOID ServerPortCookie,
43. __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
44. __in ULONG SizeOfContext,
45. __deref_out_opt PVOID *ConnectionCookie
46. );
47.
48. VOID
49. ScannerPortDisconnect (
50. __in_opt PVOID ConnectionCookie
51. );
52.
53. NTSTATUS
54. ScannerpScanFileInUserMode (
55. __in PFLT_INSTANCE Instance,
56. __in PFILE_OBJECT FileObject,
57. __out PBOOLEAN SafeToOpen
58. );
59.
60. BOOLEAN
61. ScannerpCheckExtension (
62. __in PUNICODE_STRING Extension
63. );
64.
66. MyScannerpScanFileInUserMode (
67. __in PFLT_INSTANCE Instance,
68. __in PFILE_OBJECT FileObject,
69. __in PFLT_CALLBACK_DATA Data,
70. __in ULONG Operation,
71. __out PBOOLEAN SafeToOpen
72. );
73.
74. //
75. // Assign text sections for each routine.
76. //
77.
78. #ifdef ALLOC_PRAGMA
79. #pragma alloc_text(INIT, DriverEntry)
80. #pragma alloc_text(PAGE, ScannerInstanceSetup)
81. #pragma alloc_text(PAGE, ScannerPreCreate)
82. #pragma alloc_text(PAGE, ScannerPostCreate)
83. #pragma alloc_text(PAGE, ScannerPortConnect)
84. #pragma alloc_text(PAGE, ScannerPortDisconnect)
85. #pragma alloc_text(PAGE, ScannerPostSetInforMation)
86. #pragma alloc_text(PAGE, ScannerPreSetInforMation )
87. //IsPatternMatch
88. //PsGetProcessFullName
89. #endif
90.
91.
92. //
93. // Constant FLT_REGISTRATION structure for our filter. This
94. // initializes the callback routines our filter wants to register
95. // for. This is only used to register with the filter manager
96. //
97.
98. const FLT_OPERATION_REGISTRATION Callbacks[] = {
99.
100. { IRP_MJ_CREATE,
101. 0,
102. ScannerPreCreate,
103. ScannerPostCreate},
104.
105. { IRP_MJ_CLEANUP,
106. 0,
107. ScannerPreCleanup,
108. NULL},
109.
110. { IRP_MJ_WRITE,
111. 0,
112. ScannerPreWrite,
113. NULL},
114.
115. { IRP_MJ_SET_INFORMATION,
116. 0,
117. ScannerPreSetInforMation,
118. ScannerPostSetInforMation},
119.
120. { IRP_MJ_OPERATION_END }
121. };
122.
123.
124. const FLT_CONTEXT_REGISTRATION ContextRegistration[] = {
125.
126. { FLT_STREAMHANDLE_CONTEXT,
127. 0,
128. NULL,
129. sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
130. 'chBS' },
131.
132. { FLT_CONTEXT_END }
133. };
134.
135. const FLT_REGISTRATION FilterRegistration = {
136.
137. sizeof( FLT_REGISTRATION ), // Size
138. FLT_REGISTRATION_VERSION, // Version
139. 0, // Flags
140. ContextRegistration, // Context Registration.
141. Callbacks, // Operation callbacks
142. ScannerUnload, // FilterUnload
143. ScannerInstanceSetup, // InstanceSetup
144. ScannerQueryTeardown, // InstanceQueryTeardown
145. NULL, // InstanceTeardownStart
146. NULL, // InstanceTeardownComplete
147. NULL, // GenerateFileName
148. NULL, // GenerateDestinationFileName
149. NULL // NormalizeNameComponent
150. };
151.
152.
153.
154. BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase) 155. {
156. return FsRtlIsNameInExpression(
157. Expression,
159. IgnoreCase,//如果这⾥设置为TRUE,那么Expression必须是⼤写的
160. NULL
161. );
162.
163. }
164.
165. PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
166. {
167. PFILE_OBJECT pFileObject=NULL;
168. POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
169. if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
170. return NULL;
171. if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
172. return NULL;
173. ObDereferenceObject(pFileObject);
174. return &(pObjectNameInfo->Name);//尚未释放内存以及 ObDereferenceObject
175. }
176.
177. ULONG g_Count = 0;
178. NTSTATUS
179. DriverEntry (
180. __in PDRIVER_OBJECT DriverObject,
181. __in PUNICODE_STRING RegistryPath
182. )
183. {
184. OBJECT_ATTRIBUTES oa;
185. UNICODE_STRING uniString;
186. PSECURITY_DESCRIPTOR sd;
187. NTSTATUS status;
188.
189. UNREFERENCED_PARAMETER( RegistryPath );
190.
191. g_LastDelFileName.Buffer = ExAllocatePool(NonPagedPool,MAX_PATH*2);
192. g_LastDelFileName.Length = g_LastDelFileName.MaximumLength = MAX_PATH*2;
193. memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
194.
195. //注册回调
196. status = FltRegisterFilter( DriverObject,
197. &FilterRegistration,
198. &ScannerData.Filter );
199.
200.
201. if (!NT_SUCCESS( status )) {
202.
203. return status;
204. }
205.
206. //创建端⼝
207. RtlInitUnicodeString( &uniString, ScannerPortName );
208.
209. //设置通信端⼝权限 ,只有管理员和系统进程才能操作
210. status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
211.
212. if (NT_SUCCESS( status )) {
213.
214. InitializeObjectAttributes( &oa,
215. &uniString,
216. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
217. NULL,
218. sd );
219.
220. //创建通信端⼝,并设置对应的回调函数
221. status = FltCreateCommunicationPort( ScannerData.Filter,
222. &ScannerData.ServerPort,
223. &oa,//设置的名字
224. NULL,
225. ScannerPortConnect,//当R3连接时回调主要是记录R3的进程ID或EPROCESS以便放过本进程还有记录R3的通信端⼝,给后⾯主动通信的时候⽤
226. ScannerPortDisconnect,//当R3离线时回调主要是关闭R3端⼝和设置R3的进程信息为NULL
227. NULL,//处理R3主动函数⽐如R3下新的规则,
228. 1 );//最后⼀个常为1
229. //设置好后需要释放权限的设置
230. FltFreeSecurityDescriptor( sd );
231.
232. if (NT_SUCCESS( status )) {
233.
234. //
235. // Start filtering I/O.
236. //
237. //开始过滤
238. status = FltStartFiltering( ScannerData.Filter );
239.
240. if (NT_SUCCESS( status )) {
241.
242. return STATUS_SUCCESS;
243. }
244. //失败就滚吧
245. FltCloseCommunicationPort( ScannerData.ServerPort );
246. }
247. }
248. //失败就滚吧
249. FltUnregisterFilter( ScannerData.Filter );
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论