Minifilter过滤,功能实现对驱动目录的监控,包括创建,重命名,删除并实现hips
注意下:我的这套过滤只能用在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);
//就算拒绝了 也会创建一个空文件 这里我们删除 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;
- }
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);
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, // GenerateFileName
- NULL, // GenerateDestinationFileName
- NULL // NormalizeNameComponent
- };
- BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase)
- {
- return FsRtlIsNameInExpression(
- Expression,
- Name,
- IgnoreCase,//如果这里设置为TRUE,那么Expression必须是大写的
- NULL
- );
- }
- PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
- {
- PFILE_OBJECT pFileObject=NULL;
- POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
- if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
- return NULL;
- if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
- return NULL;
- ObDereferenceObject(pFileObject);
- return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
- }
- ULONG g_Count = 0;
- NTSTATUS
- DriverEntry (
- __in PDRIVER_OBJECT DriverObject,
- __in PUNICODE_STRING RegistryPath
- )
- {
- OBJECT_ATTRIBUTES oa;
- UNICODE_STRING uniString;
- PSECURITY_DESCRIPTOR sd;
- NTSTATUS status;
- UNREFERENCED_PARAMETER( RegistryPath );
- g_LastDelFileName.Buffer = ExAllocatePool(NonPagedPool,MAX_PATH*2);
- g_LastDelFileName.Length = g_LastDelFileName.MaximumLength = MAX_PATH*2;
- memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
- //注册回调
- status = FltRegisterFilter( DriverObject,
- &FilterRegistration,
- &ScannerData.Filter );
- if (!NT_SUCCESS( status )) {
- return status;
- }
- //创建端口
- RtlInitUnicodeString( &uniString, ScannerPortName );
- //设置通信端口权限 ,只有管理员和系统进程才能操作
- status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
- if (NT_SUCCESS( status )) {
- InitializeObjectAttributes( &oa,
- &uniString,
- OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
- NULL,
- sd );
- //创建通信端口,并设置对应的回调函数
- status = FltCreateCommunicationPort( ScannerData.Filter,
- &ScannerData.ServerPort,
- &oa,//设置的名字
- NULL,
- ScannerPortConnect,//当R3连接时回调 主要是记录R3的进程ID或EPROCESS以便放过本进程 还有记录R3的通信端口,给后面主动通信的时候用
- ScannerPortDisconnect,//当R3离线时回调 主要是关闭R3端口和设置R3的进程信息为NULL
- NULL,//处理R3主动函数 比如R3下新的规则,
- 1 );//最后一个常为1
- //设置好后需要释放权限的设置
- FltFreeSecurityDescriptor( sd );
- if (NT_SUCCESS( status )) {
- //
- // Start filtering I/O.
- //
- //开始过滤
- status = FltStartFiltering( ScannerData.Filter );
- if (NT_SUCCESS( status )) {
- return STATUS_SUCCESS;
- }
- //失败就滚吧
- FltCloseCommunicationPort( ScannerData.ServerPort );
- }
- }
- //失败就滚吧
- FltUnregisterFilter( ScannerData.Filter );
- return status;
- }
- NTSTATUS
- ScannerPortConnect (
- __in PFLT_PORT ClientPort,
- __in_opt PVOID ServerPortCookie,
- __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
- __in ULONG SizeOfContext,
- __deref_out_opt PVOID *ConnectionCookie
- )
- {
- PAGED_CODE();
- UNREFERENCED_PARAMETER( ServerPortCookie );
- UNREFERENCED_PARAMETER( ConnectionContext );
- UNREFERENCED_PARAMETER( SizeOfContext);
- UNREFERENCED_PARAMETER( ConnectionCookie );
- ASSERT( ScannerData.ClientPort == NULL );
- ASSERT( ScannerData.UserProcess == NULL );
- //设置本身进程 和 R3的的通信端口 给后面判断和通信时使用
- ScannerData.UserProcess = PsGetCurrentProcess();
- ScannerData.ClientPort = ClientPort;
- DbgPrint( "!!! scanner.sys --- connected, port=0x%p\n", ClientPort );
- return STATUS_SUCCESS;
- }
- VOID
- ScannerPortDisconnect(
- __in_opt PVOID ConnectionCookie
- )
- {
- UNREFERENCED_PARAMETER( ConnectionCookie );
- PAGED_CODE();
- DbgPrint( "!!! scanner.sys --- disconnected, port=0x%p\n", ScannerData.ClientPort );
- //关闭R3通信端口
- FltCloseClientPort( ScannerData.Filter, &ScannerData.ClientPort );
- //设置R3进程为0
- ScannerData.UserProcess = NULL;
- }
- NTSTATUS
- ScannerUnload (
- __in FLT_FILTER_UNLOAD_FLAGS Flags
- )
- {
- UNREFERENCED_PARAMETER( Flags );
- //
- // Close the server port.
- //
- if(g_LastDelFileName.Buffer)
- ExFreePool(g_LastDelFileName.Buffer);
- FltCloseCommunicationPort( ScannerData.ServerPort );
- //
- // Unregister the filter
- //
- FltUnregisterFilter( ScannerData.Filter );
- return STATUS_SUCCESS;
- }
- NTSTATUS
- ScannerInstanceSetup (
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __in FLT_INSTANCE_SETUP_FLAGS Flags,
- __in DEVICE_TYPE VolumeDeviceType,
- __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
- )
- {
- UNREFERENCED_PARAMETER( FltObjects );
- UNREFERENCED_PARAMETER( Flags );
- UNREFERENCED_PARAMETER( VolumeFilesystemType );
- PAGED_CODE();
- ASSERT( FltObjects->Filter == ScannerData.Filter );
- //
- // Don't attach to network volumes.
- //
- if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {
- return STATUS_FLT_DO_NOT_ATTACH;
- }
- return STATUS_SUCCESS;
- }
- NTSTATUS
- ScannerQueryTeardown (
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
- )
- {
- UNREFERENCED_PARAMETER( FltObjects );
- UNREFERENCED_PARAMETER( Flags );
- return STATUS_SUCCESS;
- }
- FLT_PREOP_CALLBACK_STATUS
- ScannerPreCreate (
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __deref_out_opt PVOID *CompletionContext
- )
- {
- UNREFERENCED_PARAMETER( FltObjects );
- UNREFERENCED_PARAMETER( CompletionContext );
- PAGED_CODE();
- //
- // See if this create is being done by our user process.
- //
- //DbgPrint("Pre Creta!\n");
- if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) {
- DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" );
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- return FLT_PREOP_SUCCESS_WITH_CALLBACK;
- }
- BOOLEAN
- ScannerpCheckExtension (
- __in PUNICODE_STRING Extension
- )
- {
- const UNICODE_STRING *ext;
- if (Extension->Length == 0) {
- return FALSE;
- }
- //
- // Check if it matches any one of our static extension list
- //
- ext = ScannerExtensionsToScan;
- while (ext->Buffer != NULL) {
- if (RtlCompareUnicodeString( Extension, ext, TRUE ) == 0) {
- //
- // A match. We are interested in this file
- //
- return TRUE;
- }
- ext++;
- }
- return FALSE;
- }
- //处理打开,创建时(一般这个时候提示的话就是已经被感染了)
- FLT_POSTOP_CALLBACK_STATUS
- ScannerPostCreate (
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __in_opt PVOID CompletionContext,
- __in FLT_POST_OPERATION_FLAGS Flags
- )
- {
- FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
- PFLT_FILE_NAME_INFORMATION nameInfo;
- NTSTATUS status;
- BOOLEAN safeToOpen, scanFile;
- UNICODE_STRING ustrRule = {0};
- ULONG Options;
- ULONG ulDisposition;
- BOOLEAN PopWindow = FALSE;
- FILE_DISPOSITION_INFORMATION fdi;
- UNREFERENCED_PARAMETER( CompletionContext );
- UNREFERENCED_PARAMETER( Flags );
- //UNREFERENCED_PARAMETER( Flags );
- //
- // If this create was failing anyway, don't bother scanning now.
- //
- //DbgPrint("Pos Creta!\n");
- 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;
- }
- status = FltGetFileNameInformation( Data,
- FLT_FILE_NAME_NORMALIZED |
- FLT_FILE_NAME_QUERY_DEFAULT,
- &nameInfo );
- if (!NT_SUCCESS( status )) {
- return FLT_POSTOP_FINISHED_PROCESSING;
- }
- FltParseFileNameInformation( nameInfo );
- //
- // Check if the extension matches the list of extensions we are interested in
- //
- RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");
- scanFile = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);
- //DbgPrint("%wZ\n",&nameInfo->Name);
- //scanFile = ScannerpCheckExtension( &nameInfo->Extension );
- //
- // Release file name info, we're done with it
- //
- FltReleaseFileNameInformation( nameInfo );
- if (!scanFile) {
- //
- // Not an extension we are interested in
- //
- return FLT_POSTOP_FINISHED_PROCESSING;
- }
- if(PopWindow)
- {
- MyScannerpScanFileInUserMode( FltObjects->Instance,
- FltObjects->FileObject,
- Data,
- 1,
- &safeToOpen );
- if (!safeToOpen) {
- //
- // Ask the filter manager to undo the create.
- //
- DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" );
- DbgPrint( "!!! scanner.sys -- undoing create \n" );
- //就算拒绝了 也会创建一个空文件 这里我们删除
- fdi.DeleteFile = TRUE;
- FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
- FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
- Data->IoStatus.Status = STATUS_ACCESS_DENIED;
- Data->IoStatus.Information = 0;
- returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
- }
- }
- return returnStatus;
- }
- //处理打开时 有写权限但 打开成功时是安全的,等它关闭的时候的我们来扫描它
- //触发这个回调的条件是文件引用技术为0,这个包括内核+R3的计数,一般是在上层使用了ZwClose或者CloseHandle时调用
- FLT_PREOP_CALLBACK_STATUS
- ScannerPreCleanup (
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __deref_out_opt PVOID *CompletionContext
- )
- {
- UNREFERENCED_PARAMETER( Data );
- UNREFERENCED_PARAMETER( FltObjects );
- UNREFERENCED_PARAMETER( CompletionContext );
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- //处理写关闭
- FLT_PREOP_CALLBACK_STATUS
- ScannerPreWrite (
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __deref_out_opt PVOID *CompletionContext
- )
- {
- FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
- UNREFERENCED_PARAMETER( CompletionContext );
- UNREFERENCED_PARAMETER( FltObjects );
- UNREFERENCED_PARAMETER( Data );
- //
- // If not client port just ignore this write.
- //
- //如果R3进程退出了
- if (ScannerData.ClientPort == NULL) {
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- return returnStatus;
- }
- BOOLEAN isNeedWatchFile(PFLT_CALLBACK_DATA Data)
- {
- BOOLEAN Ret = FALSE;
- UNICODE_STRING ustrRule = {0};
- PFLT_FILE_NAME_INFORMATION nameInfo = {0};
- NTSTATUS status = STATUS_SUCCESS;
- status = FltGetFileNameInformation( Data,
- FLT_FILE_NAME_NORMALIZED |
- FLT_FILE_NAME_QUERY_DEFAULT,
- &nameInfo );
- if (!NT_SUCCESS( status )) {
- return FALSE;
- }
- FltParseFileNameInformation( nameInfo );
- RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");
- Ret = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);
- FltReleaseFileNameInformation( nameInfo );
- return Ret;
- }
- VOID UnicodeToChar(PUNICODE_STRING src, char *dst)
- {
- ANSI_STRING string;
- RtlUnicodeStringToAnsiString(&string,src,TRUE);
- strcpy(dst,string.Buffer);
- RtlFreeAnsiString(&string);
- }
- BOOLEAN isRecycle(PFLT_CALLBACK_DATA Data ,PCFLT_RELATED_OBJECTS FltObje)
- {
- BOOLEAN Ret = FALSE;
- PFLT_FILE_NAME_INFORMATION nameInfo = {0};
- PFILE_RENAME_INFORMATION pRenameInfo = {0};
- NTSTATUS status = STATUS_SUCCESS;
- char *temp = (char*)ExAllocatePool(NonPagedPool,MAX_PATH*2);
- if(temp == NULL)
- return TRUE;
- memset(temp,'\0',MAX_PATH*2);
- //特殊情况,当字符串中包含$Recycle.Bin时是普通删除,实际上删除只是更名而已
- pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
- status = FltGetDestinationFileNameInformation(FltObje->Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&nameInfo);
- if(!NT_SUCCESS(status))
- {
- DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
- return TRUE;
- }
- UnicodeToChar(&nameInfo->Name,temp);
- if(strstr(temp,"Recycle.Bin"))
- Ret = TRUE;
- else
- Ret = FALSE;
- FltReleaseFileNameInformation(nameInfo);
- ExFreePool(temp);
- return Ret;
- }
- FLT_PREOP_CALLBACK_STATUS
- ScannerPreSetInforMation(
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __deref_out_opt PVOID *CompletionContext
- )
- {
- FLT_PREOP_CALLBACK_STATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;
- ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
- BOOLEAN isAllow = TRUE;//是否放行
- UNREFERENCED_PARAMETER(Data);
- UNREFERENCED_PARAMETER(FltObjects);
- UNREFERENCED_PARAMETER(CompletionContext);
- //UNREFERENCED_PARAMETER(FltObjects);
- if(ScannerData.ClientPort == NULL)
- {
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- if(ScannerData.UserProcess == PsGetCurrentProcess())
- {
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- /*
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
- */
- if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
- Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
- {
- switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
- {
- case FileRenameInformation:
- Options = 2;
- break;
- case FileDispositionInformation:
- Options = 3;
- break;
- default:
- Options = 0;//爆炸啦
- break;
- }
- //判断是不是我们要监控的
- if(!isNeedWatchFile(Data))
- {
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- if(Options == 2)
- {
- if(isRecycle(Data,FltObjects))
- {
- return FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- }
- //进程路径,操作类型,原路径,重命名后路径
- MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);
- if(!isAllow)
- {
- DbgPrint("ReName in PreSetInforMation !\n");
- Data->IoStatus.Status = STATUS_ACCESS_DENIED;
- Data->IoStatus.Information = 0;
- status = FLT_PREOP_COMPLETE;
- }else
- {
- status = FLT_PREOP_SUCCESS_NO_CALLBACK;
- }
- }
- return status;
- }
- FLT_POSTOP_CALLBACK_STATUS
- ScannerPostSetInforMation (
- __inout PFLT_CALLBACK_DATA Data,
- __in PCFLT_RELATED_OBJECTS FltObjects,
- __in_opt PVOID CompletionContext,
- __in FLT_POST_OPERATION_FLAGS Flags
- )
- {
- //FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
- //ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
- //BOOLEAN isAllow = TRUE;//是否放行
- UNREFERENCED_PARAMETER(Flags);
- UNREFERENCED_PARAMETER(Data);
- UNREFERENCED_PARAMETER(FltObjects);
- UNREFERENCED_PARAMETER(CompletionContext);
- /*
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
- lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
- */
- //if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
- // Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
- //{
- // switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
- // {
- // case FileRenameInformation:
- // Options = 2;
- // break;
- // case FileDispositionInformation:
- // Options = 3;
- // break;
- // default:
- // Options = 0;//爆炸啦
- // break;
- // }
- // //判断是不是我们要监控的
- // if(!isNeedWatchFile(Data))
- // {
- // return FLT_POSTOP_FINISHED_PROCESSING;
- // }
- // if(Options == 2)
- // {
- // if(isRecycle(Data,FltObjects))
- // {
- // return FLT_POSTOP_FINISHED_PROCESSING;
- // }
- // }
- // //进程路径,操作类型,原路径,重命名后路径
- // MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);
- // if(!isAllow)
- // {
- // DbgPrint("ReName in PostSetInforMation !\n");
- //
- // FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
- // Data->IoStatus.Status = STATUS_ACCESS_DENIED;
- // Data->IoStatus.Information = 0;
- //
- // status = FLT_POSTOP_FINISHED_PROCESSING;
- // }else
- // {
- // status = FLT_POSTOP_FINISHED_PROCESSING;
- // }
- //}
- //return status;
- return FLT_POSTOP_FINISHED_PROCESSING;
- }
- //操作类型 1创建 2重命名 3 删除
- NTSTATUS
- MyScannerpScanFileInUserMode (
- __in PFLT_INSTANCE Instance,
- __in PFILE_OBJECT FileObject,
- __in PFLT_CALLBACK_DATA Data,
- __in ULONG Operation,
- __out PBOOLEAN SafeToOpen
- )
- {
- NTSTATUS status = STATUS_SUCCESS;
- PSCANNER_NOTIFICATION notification = NULL;
- ULONG replyLength = 0;
- PEPROCESS pEprocess = 0;
- PUNICODE_STRING uSProcessPath = NULL;
- PFLT_FILE_NAME_INFORMATION nameInfo;
- PFLT_FILE_NAME_INFORMATION pOutReNameinfo;
- PFILE_RENAME_INFORMATION pRenameInfo;
- UNREFERENCED_PARAMETER( FileObject );
- UNREFERENCED_PARAMETER( Instance );
- *SafeToOpen = TRUE;
- //
- // If not client port just return.
- //
- if (ScannerData.ClientPort == NULL) {
- return STATUS_SUCCESS;
- }
- try {
- notification = ExAllocatePoolWithTag( NonPagedPool,
- sizeof( SCANNER_NOTIFICATION ),
- 'nacS' );
- if(NULL == notification)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
- leave;
- }
- //在这里获取进程路径,操作类型,目标路径
- //拷贝操作类型
- notification->Operation = Operation;
- pEprocess =
- Data->Thread ? IoThreadToProcess(Data->Thread) : PsGetCurrentProcess();
- if(pEprocess == NULL)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
- leave;
- }
- uSProcessPath = PsGetProcessFullName(pEprocess);//这里需要释放UNICODESTRING 的内存
- if(uSProcessPath == NULL)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
- leave;
- }
- //拷贝进程路径
- wcsncpy(¬ification->ProcessPath,uSProcessPath->Buffer,uSProcessPath->Length);
- //wcsncpy(¬ification->ProcessPath,L"test",wcslen(L"test"));
- status = FltGetFileNameInformation( Data,
- FLT_FILE_NAME_NORMALIZED |
- FLT_FILE_NAME_QUERY_DEFAULT,
- &nameInfo );
- //FltGetDestinationFileNameInformation(
- if (!NT_SUCCESS( status )) {
- status = STATUS_INSUFFICIENT_RESOURCES;
- leave;
- }
- //拷贝目标路径
- FltParseFileNameInformation( nameInfo );
- //这里应该注意下多线程的
- if(Operation == 3)
- {
- //DbgPrint("[DjWow]%wZ\n",&g_LastDelFileName);
- //DbgPrint("[DjWow]%wZ\n",&nameInfo->Name);
- if(wcsncmp(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength) == 0)
- {
- FltReleaseFileNameInformation( nameInfo );
- memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
- *SafeToOpen = TRUE;
- leave;
- }
- }
- if(Operation == 3)
- {
- wcsncpy(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
- }
- wcsncpy(¬ification->TargetPath,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
- FltReleaseFileNameInformation( nameInfo );
- if(Operation == 2)//重命名
- {
- 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);
- }
- replyLength = sizeof( SCANNER_REPLY );
- status = FltSendMessage( ScannerData.Filter,
- &ScannerData.ClientPort,
- notification,
- sizeof(SCANNER_NOTIFICATION),
- notification,
- &replyLength,
- NULL );
- if (STATUS_SUCCESS == status) {
- *SafeToOpen = ((PSCANNER_REPLY) notification)->SafeToOpen;
- } else {
- //
- // Couldn't send message
- //
- DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status );
- }
- } finally {
- if (NULL != notification) {
- ExFreePoolWithTag( notification, 'nacS' );
- }
- if(NULL != pEprocess)
- {
- //ObfDereferenceObject(pEprocess);
- }
- if(NULL != uSProcessPath)
- {
- ExFreePool(uSProcessPath);
- }
- }
- return status;
- }
#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, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase)
{
return FsRtlIsNameInExpression(
Expression,
Name,
IgnoreCase,//如果这里设置为TRUE,那么Expression必须是大写的
NULL
);
}
PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
{
PFILE_OBJECT pFileObject=NULL;
POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
return NULL;
if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
return NULL;
ObDereferenceObject(pFileObject);
return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
}
ULONG g_Count = 0;
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
PSECURITY_DESCRIPTOR sd;
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
g_LastDelFileName.Buffer = ExAllocatePool(NonPagedPool,MAX_PATH*2);
g_LastDelFileName.Length = g_LastDelFileName.MaximumLength = MAX_PATH*2;
memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
//注册回调
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&ScannerData.Filter );
if (!NT_SUCCESS( status )) {
return status;
}
//创建端口
RtlInitUnicodeString( &uniString, ScannerPortName );
//设置通信端口权限 ,只有管理员和系统进程才能操作
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
if (NT_SUCCESS( status )) {
InitializeObjectAttributes( &oa,
&uniString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
sd );
//创建通信端口,并设置对应的回调函数
status = FltCreateCommunicationPort( ScannerData.Filter,
&ScannerData.ServerPort,
&oa,//设置的名字
NULL,
ScannerPortConnect,//当R3连接时回调 主要是记录R3的进程ID或EPROCESS以便放过本进程 还有记录R3的通信端口,给后面主动通信的时候用
ScannerPortDisconnect,//当R3离线时回调 主要是关闭R3端口和设置R3的进程信息为NULL
NULL,//处理R3主动函数 比如R3下新的规则,
1 );//最后一个常为1
//设置好后需要释放权限的设置
FltFreeSecurityDescriptor( sd );
if (NT_SUCCESS( status )) {
//
// Start filtering I/O.
//
//开始过滤
status = FltStartFiltering( ScannerData.Filter );
if (NT_SUCCESS( status )) {
return STATUS_SUCCESS;
}
//失败就滚吧
FltCloseCommunicationPort( ScannerData.ServerPort );
}
}
//失败就滚吧
FltUnregisterFilter( ScannerData.Filter );
return status;
}
NTSTATUS
ScannerPortConnect (
__in PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie );
ASSERT( ScannerData.ClientPort == NULL );
ASSERT( ScannerData.UserProcess == NULL );
//设置本身进程 和 R3的的通信端口 给后面判断和通信时使用
ScannerData.UserProcess = PsGetCurrentProcess();
ScannerData.ClientPort = ClientPort;
DbgPrint( "!!! scanner.sys --- connected, port=0x%p\n", ClientPort );
return STATUS_SUCCESS;
}
VOID
ScannerPortDisconnect(
__in_opt PVOID ConnectionCookie
)
{
UNREFERENCED_PARAMETER( ConnectionCookie );
PAGED_CODE();
DbgPrint( "!!! scanner.sys --- disconnected, port=0x%p\n", ScannerData.ClientPort );
//关闭R3通信端口
FltCloseClientPort( ScannerData.Filter, &ScannerData.ClientPort );
//设置R3进程为0
ScannerData.UserProcess = NULL;
}
NTSTATUS
ScannerUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );
//
// Close the server port.
//
if(g_LastDelFileName.Buffer)
ExFreePool(g_LastDelFileName.Buffer);
FltCloseCommunicationPort( ScannerData.ServerPort );
//
// Unregister the filter
//
FltUnregisterFilter( ScannerData.Filter );
return STATUS_SUCCESS;
}
NTSTATUS
ScannerInstanceSetup (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_SETUP_FLAGS Flags,
__in DEVICE_TYPE VolumeDeviceType,
__in FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
ASSERT( FltObjects->Filter == ScannerData.Filter );
//
// Don't attach to network volumes.
//
if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {
return STATUS_FLT_DO_NOT_ATTACH;
}
return STATUS_SUCCESS;
}
NTSTATUS
ScannerQueryTeardown (
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
return STATUS_SUCCESS;
}
FLT_PREOP_CALLBACK_STATUS
ScannerPreCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
PAGED_CODE();
//
// See if this create is being done by our user process.
//
//DbgPrint("Pre Creta!\n");
if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) {
DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" );
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
BOOLEAN
ScannerpCheckExtension (
__in PUNICODE_STRING Extension
)
{
const UNICODE_STRING *ext;
if (Extension->Length == 0) {
return FALSE;
}
//
// Check if it matches any one of our static extension list
//
ext = ScannerExtensionsToScan;
while (ext->Buffer != NULL) {
if (RtlCompareUnicodeString( Extension, ext, TRUE ) == 0) {
//
// A match. We are interested in this file
//
return TRUE;
}
ext++;
}
return FALSE;
}
//处理打开,创建时(一般这个时候提示的话就是已经被感染了)
FLT_POSTOP_CALLBACK_STATUS
ScannerPostCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;
BOOLEAN safeToOpen, scanFile;
UNICODE_STRING ustrRule = {0};
ULONG Options;
ULONG ulDisposition;
BOOLEAN PopWindow = FALSE;
FILE_DISPOSITION_INFORMATION fdi;
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );
//UNREFERENCED_PARAMETER( Flags );
//
// If this create was failing anyway, don't bother scanning now.
//
//DbgPrint("Pos Creta!\n");
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;
}
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
if (!NT_SUCCESS( status )) {
return FLT_POSTOP_FINISHED_PROCESSING;
}
FltParseFileNameInformation( nameInfo );
//
// Check if the extension matches the list of extensions we are interested in
//
RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");
scanFile = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);
//DbgPrint("%wZ\n",&nameInfo->Name);
//scanFile = ScannerpCheckExtension( &nameInfo->Extension );
//
// Release file name info, we're done with it
//
FltReleaseFileNameInformation( nameInfo );
if (!scanFile) {
//
// Not an extension we are interested in
//
return FLT_POSTOP_FINISHED_PROCESSING;
}
if(PopWindow)
{
MyScannerpScanFileInUserMode( FltObjects->Instance,
FltObjects->FileObject,
Data,
1,
&safeToOpen );
if (!safeToOpen) {
//
// Ask the filter manager to undo the create.
//
DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" );
DbgPrint( "!!! scanner.sys -- undoing create \n" );
//就算拒绝了 也会创建一个空文件 这里我们删除
fdi.DeleteFile = TRUE;
FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
}
}
return returnStatus;
}
//处理打开时 有写权限但 打开成功时是安全的,等它关闭的时候的我们来扫描它
//触发这个回调的条件是文件引用技术为0,这个包括内核+R3的计数,一般是在上层使用了ZwClose或者CloseHandle时调用
FLT_PREOP_CALLBACK_STATUS
ScannerPreCleanup (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER( Data );
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
//处理写关闭
FLT_PREOP_CALLBACK_STATUS
ScannerPreWrite (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Data );
//
// If not client port just ignore this write.
//
//如果R3进程退出了
if (ScannerData.ClientPort == NULL) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return returnStatus;
}
BOOLEAN isNeedWatchFile(PFLT_CALLBACK_DATA Data)
{
BOOLEAN Ret = FALSE;
UNICODE_STRING ustrRule = {0};
PFLT_FILE_NAME_INFORMATION nameInfo = {0};
NTSTATUS status = STATUS_SUCCESS;
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
if (!NT_SUCCESS( status )) {
return FALSE;
}
FltParseFileNameInformation( nameInfo );
RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");
Ret = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);
FltReleaseFileNameInformation( nameInfo );
return Ret;
}
VOID UnicodeToChar(PUNICODE_STRING src, char *dst)
{
ANSI_STRING string;
RtlUnicodeStringToAnsiString(&string,src,TRUE);
strcpy(dst,string.Buffer);
RtlFreeAnsiString(&string);
}
BOOLEAN isRecycle(PFLT_CALLBACK_DATA Data ,PCFLT_RELATED_OBJECTS FltObje)
{
BOOLEAN Ret = FALSE;
PFLT_FILE_NAME_INFORMATION nameInfo = {0};
PFILE_RENAME_INFORMATION pRenameInfo = {0};
NTSTATUS status = STATUS_SUCCESS;
char *temp = (char*)ExAllocatePool(NonPagedPool,MAX_PATH*2);
if(temp == NULL)
return TRUE;
memset(temp,'\0',MAX_PATH*2);
//特殊情况,当字符串中包含$Recycle.Bin时是普通删除,实际上删除只是更名而已
pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
status = FltGetDestinationFileNameInformation(FltObje->Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&nameInfo);
if(!NT_SUCCESS(status))
{
DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
return TRUE;
}
UnicodeToChar(&nameInfo->Name,temp);
if(strstr(temp,"Recycle.Bin"))
Ret = TRUE;
else
Ret = FALSE;
FltReleaseFileNameInformation(nameInfo);
ExFreePool(temp);
return Ret;
}
FLT_PREOP_CALLBACK_STATUS
ScannerPreSetInforMation(
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
FLT_PREOP_CALLBACK_STATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;
ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
BOOLEAN isAllow = TRUE;//是否放行
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
//UNREFERENCED_PARAMETER(FltObjects);
if(ScannerData.ClientPort == NULL)
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
if(ScannerData.UserProcess == PsGetCurrentProcess())
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
/*
lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
*/
if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
{
switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
{
case FileRenameInformation:
Options = 2;
break;
case FileDispositionInformation:
Options = 3;
break;
default:
Options = 0;//爆炸啦
break;
}
//判断是不是我们要监控的
if(!isNeedWatchFile(Data))
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
if(Options == 2)
{
if(isRecycle(Data,FltObjects))
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
}
//进程路径,操作类型,原路径,重命名后路径
MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);
if(!isAllow)
{
DbgPrint("ReName in PreSetInforMation !\n");
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
Data->IoStatus.Information = 0;
status = FLT_PREOP_COMPLETE;
}else
{
status = FLT_PREOP_SUCCESS_NO_CALLBACK;
}
}
return status;
}
FLT_POSTOP_CALLBACK_STATUS
ScannerPostSetInforMation (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
//FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
//ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
//BOOLEAN isAllow = TRUE;//是否放行
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
/*
lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
*/
//if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
// Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
//{
// switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
// {
// case FileRenameInformation:
// Options = 2;
// break;
// case FileDispositionInformation:
// Options = 3;
// break;
// default:
// Options = 0;//爆炸啦
// break;
// }
// //判断是不是我们要监控的
// if(!isNeedWatchFile(Data))
// {
// return FLT_POSTOP_FINISHED_PROCESSING;
// }
// if(Options == 2)
// {
// if(isRecycle(Data,FltObjects))
// {
// return FLT_POSTOP_FINISHED_PROCESSING;
// }
// }
// //进程路径,操作类型,原路径,重命名后路径
// MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);
// if(!isAllow)
// {
// DbgPrint("ReName in PostSetInforMation !\n");
//
// FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
// Data->IoStatus.Status = STATUS_ACCESS_DENIED;
// Data->IoStatus.Information = 0;
//
// status = FLT_POSTOP_FINISHED_PROCESSING;
// }else
// {
// status = FLT_POSTOP_FINISHED_PROCESSING;
// }
//}
//return status;
return FLT_POSTOP_FINISHED_PROCESSING;
}
//操作类型 1创建 2重命名 3 删除
NTSTATUS
MyScannerpScanFileInUserMode (
__in PFLT_INSTANCE Instance,
__in PFILE_OBJECT FileObject,
__in PFLT_CALLBACK_DATA Data,
__in ULONG Operation,
__out PBOOLEAN SafeToOpen
)
{
NTSTATUS status = STATUS_SUCCESS;
PSCANNER_NOTIFICATION notification = NULL;
ULONG replyLength = 0;
PEPROCESS pEprocess = 0;
PUNICODE_STRING uSProcessPath = NULL;
PFLT_FILE_NAME_INFORMATION nameInfo;
PFLT_FILE_NAME_INFORMATION pOutReNameinfo;
PFILE_RENAME_INFORMATION pRenameInfo;
UNREFERENCED_PARAMETER( FileObject );
UNREFERENCED_PARAMETER( Instance );
*SafeToOpen = TRUE;
//
// If not client port just return.
//
if (ScannerData.ClientPort == NULL) {
return STATUS_SUCCESS;
}
try {
notification = ExAllocatePoolWithTag( NonPagedPool,
sizeof( SCANNER_NOTIFICATION ),
'nacS' );
if(NULL == notification)
{
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
//在这里获取进程路径,操作类型,目标路径
//拷贝操作类型
notification->Operation = Operation;
pEprocess =
Data->Thread ? IoThreadToProcess(Data->Thread) : PsGetCurrentProcess();
if(pEprocess == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
uSProcessPath = PsGetProcessFullName(pEprocess);//这里需要释放UNICODESTRING 的内存
if(uSProcessPath == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
//拷贝进程路径
wcsncpy(¬ification->ProcessPath,uSProcessPath->Buffer,uSProcessPath->Length);
//wcsncpy(¬ification->ProcessPath,L"test",wcslen(L"test"));
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
//FltGetDestinationFileNameInformation(
if (!NT_SUCCESS( status )) {
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
//拷贝目标路径
FltParseFileNameInformation( nameInfo );
//这里应该注意下多线程的
if(Operation == 3)
{
//DbgPrint("[DjWow]%wZ\n",&g_LastDelFileName);
//DbgPrint("[DjWow]%wZ\n",&nameInfo->Name);
if(wcsncmp(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength) == 0)
{
FltReleaseFileNameInformation( nameInfo );
memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
*SafeToOpen = TRUE;
leave;
}
}
if(Operation == 3)
{
wcsncpy(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
}
wcsncpy(¬ification->TargetPath,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
FltReleaseFileNameInformation( nameInfo );
if(Operation == 2)//重命名
{
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);
}
replyLength = sizeof( SCANNER_REPLY );
status = FltSendMessage( ScannerData.Filter,
&ScannerData.ClientPort,
notification,
sizeof(SCANNER_NOTIFICATION),
notification,
&replyLength,
NULL );
if (STATUS_SUCCESS == status) {
*SafeToOpen = ((PSCANNER_REPLY) notification)->SafeToOpen;
} else {
//
// Couldn't send message
//
DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status );
}
} finally {
if (NULL != notification) {
ExFreePoolWithTag( notification, 'nacS' );
}
if(NULL != pEprocess)
{
//ObfDereferenceObject(pEprocess);
}
if(NULL != uSProcessPath)
{
ExFreePool(uSProcessPath);
}
}
return status;
}
R3:
- // MiniFliter_MFCDlg.cpp : 实现文件
- //
- #include "stdafx.h"
- #include "MiniFliter_MFC.h"
- #include "MiniFliter_MFCDlg.h"
- #include "afxdialogex.h"
- #include "resource.h"
- #include <windows.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <winioctl.h>
- #include <string.h>
- #include <crtdbg.h>
- #include <assert.h>
- #include <fltuser.h>
- #include "../MiniFliter_Scaner/scanuk.h"
- #include "User.h"
- #include <dontuse.h>
- #include "PopupDlg.h"
- #pragma comment(lib,"fltlib.lib")
- #define SCANNER_DEFAULT_REQUEST_COUNT 5
- #define SCANNER_DEFAULT_THREAD_COUNT 2
- #define SCANNER_MAX_THREAD_COUNT 64
- typedef struct _SCANNER_THREAD_CONTEXT {
- HANDLE Port;
- HANDLE Completion;
- } SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;
- HANDLE g_port = 0;
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
- class CAboutDlg : public CDialogEx
- {
- public:
- CAboutDlg();
- // 对话框数据
- enum { IDD = IDD_ABOUTBOX };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
- // 实现
- protected:
- DECLARE_MESSAGE_MAP()
- public:
- //virtual INT_PTR DoModal();
- };
- CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
- {
- }
- void CAboutDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialogEx::DoDataExchange(pDX);
- }
- BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
- END_MESSAGE_MAP()
- // CMiniFliter_MFCDlg 对话框
- CMiniFliter_MFCDlg::CMiniFliter_MFCDlg(CWnd* pParent /*=NULL*/)
- : CDialogEx(CMiniFliter_MFCDlg::IDD, pParent)
- {
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- }
- void CMiniFliter_MFCDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialogEx::DoDataExchange(pDX);
- }
- BEGIN_MESSAGE_MAP(CMiniFliter_MFCDlg, CDialogEx)
- ON_WM_SYSCOMMAND()
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDC_START, &CMiniFliter_MFCDlg::OnBnClickedStart)
- END_MESSAGE_MAP()
- // CMiniFliter_MFCDlg 消息处理程序
- BOOL CMiniFliter_MFCDlg::OnInitDialog()
- {
- CDialogEx::OnInitDialog();
- // 将“关于...”菜单项添加到系统菜单中。
- // IDM_ABOUTBOX 必须在系统命令范围内。
- ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
- ASSERT(IDM_ABOUTBOX < 0xF000);
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- BOOL bNameValid;
- CString strAboutMenu;
- bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
- ASSERT(bNameValid);
- if (!strAboutMenu.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
- }
- }
- // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
- // 执行此操作
- SetIcon(m_hIcon, TRUE); // 设置大图标
- SetIcon(m_hIcon, FALSE); // 设置小图标
- return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
- }
- void CMiniFliter_MFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
- {
- if ((nID & 0xFFF0) == IDM_ABOUTBOX)
- {
- CAboutDlg dlgAbout;
- //dlgAbout.DoModal();
- }
- else
- {
- CDialogEx::OnSysCommand(nID, lParam);
- }
- }
- // 如果向对话框添加最小化按钮,则需要下面的代码
- // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
- // 这将由框架自动完成。
- void CMiniFliter_MFCDlg::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // 用于绘制的设备上下文
- SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
- // 使图标在工作区矩形中居中
- int cxIcon = GetSystemMetrics(SM_CXICON);
- int cyIcon = GetSystemMetrics(SM_CYICON);
- CRect rect;
- GetClientRect(&rect);
- int x = (rect.Width() - cxIcon + 1) / 2;
- int y = (rect.Height() - cyIcon + 1) / 2;
- // 绘制图标
- dc.DrawIcon(x, y, m_hIcon);
- }
- else
- {
- CDialogEx::OnPaint();
- }
- }
- //当用户拖动最小化窗口时系统调用此函数取得光标
- //显示。
- HCURSOR CMiniFliter_MFCDlg::OnQueryDragIcon()
- {
- return static_cast<HCURSOR>(m_hIcon);
- }
- DWORD HandData(LPCTSTR str)
- {
- CPopupDlg dlg;
- dlg.SetText(str);
- dlg.DoModal();
- if(dlg.m_Allow == TRUE)
- return 1;
- else
- return 0;
- }
- DWORD
- ScannerWorker(
- __in PSCANNER_THREAD_CONTEXT Context
- )
- {
- DWORD dwRet = 0;
- DWORD outSize = 0;
- HRESULT hr = 0;
- ULONG_PTR key = 0;
- BOOL result = TRUE;
- //CHAR strPop[MAX_PATH*2] = {0};
- WCHAR strOptions[50*2] = {0};//操作类型字符串
- WCHAR LastPath[MAX_PATH*2] = {0};
- BOOL LastResult = TRUE;
- LPOVERLAPPED pOvlp;
- PSCANNER_NOTIFICATION notification;
- SCANNER_REPLY_MESSAGE replyMessage;
- PSCANNER_MESSAGE message;
- //DWORD dwRet = 0;
- CString tip = NULL;
- memset(LastPath,'\0',MAX_PATH*2);
- #pragma warning(push)
- #pragma warning(disable:4127) // conditional expression is constant
- while (TRUE) {
- #pragma warning(pop)
- //
- // Poll for messages from the filter component to scan.
- //
- result = GetQueuedCompletionStatus( Context->Completion, &outSize, &key, &pOvlp, INFINITE );
- //
- // Obtain the message: note that the message we sent down via FltGetMessage() may NOT be
- // the one dequeued off the completion queue: this is solely because there are multiple
- // threads per single port handle. Any of the FilterGetMessage() issued messages can be
- // completed in random order - and we will just dequeue a random one.
- //
- message = CONTAINING_RECORD( pOvlp, SCANNER_MESSAGE, Ovlp );
- if (!result) {
- hr = HRESULT_FROM_WIN32( GetLastError() );
- break;
- }
- //printf( "Received message, size %d\n", pOvlp->InternalHigh );
- //tip.Format(L"Received message, size %d\n", pOvlp->InternalHigh );
- notification = &message->Notification;
- if(notification->Operation == 1)
- {
- if(wcsncmp(LastPath,notification->TargetPath,wcslen(notification->TargetPath))==0)
- {
- memset(LastPath,'\0',MAX_PATH*2);
- result = LastResult;
- goto EX;
- }
- }
- memset(strOptions,'\0',50);
- switch (notification->Operation)
- {
- case 1:
- wcscpy_s(strOptions,50,L"创建");
- break;
- case 2:
- wcscpy_s(strOptions,50,L"重命名");
- break;
- case 3:
- wcscpy_s(strOptions,50,L"删除");
- break;
- default:
- wcscpy_s(strOptions,50,L"爆炸");
- break;
- }
- //memset(strPop,'\0',MAX_PATH*2);
- if(notification->Operation == 2)
- {
- //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n重名为:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);
- tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n重名为:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);
- }else
- {
- //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);
- tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);
- }
- Sleep(1000);
- //dwRet = MessageBoxA(NULL,strPop,"监控到攻击行为",MB_YESNO);
- dwRet = HandData(tip);
- if(dwRet == 1)
- result = FALSE;
- else
- result = TRUE;
- LastResult = result;
- EX:
- wcsncpy_s(LastPath,MAX_PATH*2,notification->TargetPath,MAX_PATH*2);
- replyMessage.ReplyHeader.Status = 0;
- replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;
- replyMessage.Reply.SafeToOpen = !result;
- printf( "Replying message, ResultCode: %d\n", replyMessage.Reply.SafeToOpen );
- hr = FilterReplyMessage( Context->Port,
- (PFILTER_REPLY_HEADER) &replyMessage,
- sizeof( replyMessage ) );
- if (SUCCEEDED( hr )) {
- printf( "Replied message\n" );
- } else {
- printf( "Scanner: Error replying message. Error = 0x%X\n", hr );
- break;
- }
- memset( &message->Ovlp, 0, sizeof( OVERLAPPED ) );
- hr = FilterGetMessage( Context->Port,
- &message->MessageHeader,
- FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
- &message->Ovlp );
- if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {
- break;
- }
- }
- if (!SUCCEEDED( hr )) {
- if (hr == HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE )) {
- //
- // Scanner port disconncted.
- //
- printf( "Scanner: Port is disconnected, probably due to scanner filter unloading.\n" );
- } else {
- printf( "Scanner: Unknown error occured. Error = 0x%X\n", hr );
- }
- }
- free( message );
- return hr;
- }
- //此函数需放到线程中执行
- int InitFltUser()
- {
- DWORD dwDefRequestCount = SCANNER_DEFAULT_REQUEST_COUNT;
- DWORD dwDefThreadCount = SCANNER_DEFAULT_THREAD_COUNT;
- DWORD dwMaxThreadCount = SCANNER_MAX_THREAD_COUNT;
- SCANNER_THREAD_CONTEXT context;
- PSCANNER_MESSAGE msg;
- HANDLE threads[SCANNER_MAX_THREAD_COUNT];
- CString tip = NULL;
- DWORD threadId;
- DWORD i = 0;
- //连接到端口
- HRESULT hr = FilterConnectCommunicationPort(ScannerPortName,0,NULL,0,NULL,&g_port);
- if(IS_ERROR(hr))
- {
- AfxMessageBox(L"hr is null\n");
- return 0;
- }
- //为这个句柄创建一个Comption
- HANDLE completion = CreateIoCompletionPort( g_port,
- NULL,
- 0,
- dwDefThreadCount );
- if (completion == NULL)
- {
- tip.Format(L"ERROR: Creating completion port: %d\n", GetLastError());
- AfxMessageBox(tip);
- CloseHandle( g_port );
- return 0;
- }
- //tip.Format(L"Scanner: Port = 0x%p Completion = 0x%p\n", g_port, completion );
- //this->SetWindowTextW(tip);
- context.Port = g_port;
- context.Completion = completion;
- //创建规定的线程
- for (i = 0; i < dwDefThreadCount; i++)
- {
- //创建线程
- threads[i] = CreateThread( NULL,
- 0,
- (LPTHREAD_START_ROUTINE)ScannerWorker,
- &context,
- 0,
- &threadId );
- if (threads[i] == NULL)
- {
- hr = GetLastError();
- tip.Format(L"ERROR: Couldn't create thread: %d\n", hr );
- //this->SetWindowTextW(tip);
- goto main_cleanup;
- }
- for (DWORD j = 0; j < dwDefRequestCount; j++)
- {
- //
- // Allocate the message.
- //
- #pragma prefast(suppress:__WARNING_MEMORY_LEAK, "msg will not be leaked because it is freed in ScannerWorker")
- msg = (PSCANNER_MESSAGE)malloc( sizeof( SCANNER_MESSAGE ));
- if (msg == NULL) {
- hr = ERROR_NOT_ENOUGH_MEMORY;
- goto main_cleanup;
- }
- memset( &msg->Ovlp, 0, sizeof( OVERLAPPED ) );
- //
- // Request messages from the filter driver.
- //
- hr = FilterGetMessage( g_port,
- &msg->MessageHeader,
- FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
- &msg->Ovlp );
- if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING ))
- {
- free( msg );
- goto main_cleanup;
- }
- }
- }
- hr = S_OK;
- WaitForMultipleObjectsEx( i, threads, TRUE, INFINITE, FALSE );
- //返回线程数组和 数组个数
- main_cleanup:
- tip.Format(L"Scanner: All done. Result = 0x%08x\n", hr );
- //this->SetWindowTextW(tip);
- CloseHandle(g_port);
- CloseHandle(completion);
- return hr+1;
- }
- void CMiniFliter_MFCDlg::OnBnClickedStart()
- {
- CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)InitFltUser,NULL,0,NULL);
- }

浙公网安备 33010602011771号