...功能实现对驱动目录的监控,包括创建,重命名,删除并实现hips_百度文 ...
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小时内删除。