Minifilter过滤,功能实现对驱动目录的监控,包括创建,重命名,删除并实现hips

本文介绍了如何在NT6系统上使用Minifilter驱动进行文件监控,包括文件创建、重命名和删除的处理。在文件创建时,通过在Post操作中监控以避免多次请求,利用FltGetFileNameInformation获取全路径,并记录拒绝的文件以防止重复拦截。在删除操作中,区分直接删除和普通删除,通过文件的发现和更名过程进行判断。重命名文件时,通过Buffer或FltGetDestinationFileNameInformation获取新路径。在处理多次创建请求时,将处理过的文件全路径记录以避免弹窗。
摘要由CSDN通过智能技术生成

注意下:我的这套过滤只能用在nt6系统上

原因是使用一个nt6上才有的函数

见函数

PsGetProcessFullName

其实没必要自己来写获取全路径

因为minifilter已经给我们提供了获取全路径的函数

FltGetFileNameInformation

我就不改了,哈哈


说说遇到的问题吧

在监控创建的时候,我是在post中监控,我拒绝后,会弹窗,2-3次吧,也就是会请求2-3次,我的解决方法是记录上一次拒绝的文件全路径,然后下一次来的时候来比对

这里可以将处理过的文件加入链表或者hash,我偷懒了,就直接用这种方法来解决多重求情的问题,

这里注意下,出现多次请求的原因是你第一次放行了,那么我们第二次的时候就知道比对的时候就直接放行了


考虑过在pre中监控

但根据MF周老师的意见 说在这里拿到的信息是不准确的,

可以用下面一句话总结:

在pre中是对请求本身就行拦截,在post中是对请求完成结果的拦截.

遵循周老师的意见,我还是在post中监控


在拦截创建的时候,还有一个问题,就是如果创建的时候我拒绝了,那么返回给用户的会出现一个替换的框(文件已存在,但大小是0)

针对这个情况,我直接对这个data设置文件属性 有点像前面学习的IRP下发强删文件


//就算拒绝了 也会创建一个空文件 这里我们删除
			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就说明是新建操作

下面是对文件夹的判断

 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呢,知道的人可以回复下

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

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#include "scanuk.h"
#include "scanner.h"

#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")


NTSTATUS
PsReferenceProcessFilePointer (
IN PEPROCESS Process,
OUT PVOID *OutFileObject
);

SCANNER_DATA ScannerData;

UNICODE_STRING g_LastDelFileName = {0};

//
//  This is a static list of file name extensions files we are interested in scanning
//

const UNICODE_STRING ScannerExtensionsToScan[] =
    { RTL_CONSTANT_STRING( L"doc"),
      RTL_CONSTANT_STRING( L"txt"),
      RTL_CONSTANT_STRING( L"bat"),
      RTL_CONSTANT_STRING( L"cmd"),
      RTL_CONSTANT_STRING( L"inf"),
      /*RTL_CONSTANT_STRING( L"ini"),   Removed, to much usage*/
      {0, 0, NULL}
    };


//
//  Function prototypes
//

NTSTATUS
ScannerPortConnect (
    __in PFLT_PORT ClientPort,
    __in_opt PVOID ServerPortCookie,
    __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
    __in ULONG SizeOfContext,
    __deref_out_opt PVOID *ConnectionCookie
    );

VOID
ScannerPortDisconnect (
    __in_opt PVOID ConnectionCookie
    );

NTSTATUS
ScannerpScanFileInUserMode (
    __in PFLT_INSTANCE Instance,
    __in PFILE_OBJECT FileObject,
    __out PBOOLEAN SafeToOpen
    );

BOOLEAN
ScannerpCheckExtension (
    __in PUNICODE_STRING Extension
    );

NTSTATUS
MyScannerpScanFileInUserMode (
    __in PFLT_INSTANCE Instance,
    __in PFILE_OBJECT FileObject,
	__in PFLT_CALLBACK_DATA Data,
	__in ULONG		Operation,
    __out PBOOLEAN SafeToOpen
    );

//
//  Assign text sections for each routine.
//

#ifdef ALLOC_PRAGMA
    #pragma alloc_text(INIT, DriverEntry)
    #pragma alloc_text(PAGE, ScannerInstanceSetup)
    #pragma alloc_text(PAGE, ScannerPreCreate)
	#pragma alloc_text(PAGE, ScannerPostCreate)
    #pragma alloc_text(PAGE, ScannerPortConnect)
    #pragma alloc_text(PAGE, ScannerPortDisconnect)
	#pragma alloc_text(PAGE, ScannerPostSetInforMation)
	#pragma alloc_text(PAGE, ScannerPreSetInforMation )
//IsPatternMatch
//PsGetProcessFullName
#endif


//
//  Constant FLT_REGISTRATION structure for our filter.  This
//  initializes the callback routines our filter wants to register
//  for.  This is only used to register with the filter manager
//

const FLT_OPERATION_REGISTRATION Callbacks[] = {

    { IRP_MJ_CREATE,
      0,
      ScannerPreCreate,
      ScannerPostCreate},

    { IRP_MJ_CLEANUP,
      0,
      ScannerPreCleanup,
      NULL},

    { IRP_MJ_WRITE,
      0,
      ScannerPreWrite,
      NULL},

	{ IRP_MJ_SET_INFORMATION,
	  0,
	  ScannerPreSetInforMation,
	  ScannerPostSetInforMation},

    { IRP_MJ_OPERATION_END }
};


const FLT_CONTEXT_REGISTRATION ContextRegistration[] = {

    { FLT_STREAMHANDLE_CONTEXT,
      0,
      NULL,
      sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
      'chBS' },

    { FLT_CONTEXT_END }
};

const FLT_REGISTRATION FilterRegistration = {

    sizeof( FLT_REGISTRATION ),         //  Size
    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags
    ContextRegistration,                //  Context Registration.
    Callbacks,                          //  Operation callbacks
    ScannerUnload,                      //  FilterUnload
    ScannerInstanceSetup,               //  InstanceSetup
    ScannerQueryTeardown,               //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart
    NULL,                               //  InstanceTeardownComplete
    NULL,                               //  GenerateFile
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值