[MiniFilter]驱动隐藏文件夹的实现(支持Win7)
刚完成一个利用驱动隐藏文件夹的程序,隐藏文件的类似,现在贴出来共享给大家。
代码相对比较简单,我是在别人代码的基础上改的。
因为现在在网上找到的代码都是不支持XP以上版本的,所以我在别人代码的基础上添加了XP以上版本的支持。
现在该代码同时支持XP以下及XP以上版本(本人仅测试XP和Win7)。
利用驱动实现文件的隐藏主要是在IRP_MJ_DIRECTORY_CONTROL的后操作回调函数中处理其输入参数FLT_CALLBACK_DATA结构中的缓冲区数据。
该缓冲地址的获取是重点,Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer(或MdlAddress)
网上现有代码不支持XP以上版本的原因是Vista或Win7返回的FileInformationClass结构不再是FileBothDirectoryInformation,而是FileIdBothDirectoryInformation
【注】虽然利用驱动隐藏文件无法利用“显示隐藏文件”查看,但文件实际仍存在,通过路径仍然可以访问。
实现代码如下:
C 代码
//[Modify By js2854 2010-10-29 Support Windows 7]
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")
//
// This is how FltMgr was released (from oldest to newest) [仅编译时决定,而非运行时]
// This defines items that only exist in longhorn or later [判断系统版本是否VISTA以上版本]
//
#define FLT_MGR_LONGHORN (NTDDI_VERSION >= NTDDI_VISTA)
PFLT_FILTER filterHandle;
PWCHAR prefixName = L"HideDir";//要隐藏的文件夹名字的前缀
/*************************************************************************
Prototypes
*************************************************************************/
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath );
NTSTATUS PtUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags );
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, PtUnload)
#endif
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{ IRP_MJ_DIRECTORY_CONTROL,
0,
NULL,
HideFilePostDirCtrl },
{ IRP_MJ_OPERATION_END }
};
CONST FLT_REGISTRATION FilterRegistration =
{
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
NULL, // Context
Callbacks, // Operation callbacks
PtUnload, // MiniFilterUnload
NULL, // InstanceSetup
NULL, // InstanceQueryTeardown
NULL, // InstanceTeardownStart
NULL, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath )
{
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
status = FltRegisterFilter( DriverObject, &FilterRegistration, &filterHandle );
if (NT_SUCCESS( status ))
{
status = FltStartFiltering( filterHandle );
if (!NT_SUCCESS( status ))
{
FltUnregisterFilter( filterHandle );
}
}
return status;
}
NTSTATUS PtUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags )
{
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
FltUnregisterFilter( filterHandle );
return STATUS_SUCCESS;
}
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags )
{
ULONG nextOffset = 0;
int modified = 0;
int removedAllEntries = 1;
PVOID SafeBuffer;
#if FLT_MGR_LONGHORN
PFILE_ID_BOTH_DIR_INFORMATION currentFileInfo = 0;
PFILE_ID_BOTH_DIR_INFORMATION nextFileInfo = 0;
PFILE_ID_BOTH_DIR_INFORMATION previousFileInfo = 0;
#else
PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;
#endif
UNICODE_STRING fileName;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) )
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
//vista或win7返回的FileInformationClass结构不再是FileBothDirectoryInformation.
//而是FileidBothDirectoryInformation
if( Data->Iopb->MinorFunction == IRP_MN_QUERY_DIRECTORY &&
(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation ) &&
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length > 0 &&
NT_SUCCESS(Data->IoStatus.Status))
{
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
{
SafeBuffer=MmGetSystemAddressForMdlSafe(
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
NormalPagePriority );
}
else
{
SafeBuffer=Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
}
if(SafeBuffer==NULL)
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
#if FLT_MGR_LONGHORN
currentFileInfo = (PFILE_ID_BOTH_DIR_INFORMATION)SafeBuffer;
#else
currentFileInfo = (PFILE_BOTH_DIR_INFORMATION)SafeBuffer;
#endif
previousFileInfo = currentFileInfo;
do
{
//Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
nextOffset = currentFileInfo->NextEntryOffset;
#if FLT_MGR_LONGHORN
nextFileInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);
#else
nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);
#endif
//若满足条件,隐藏之
if(_wcsnicmp(currentFileInfo->FileName,prefixName,wcslen(prefixName))==0)
{
if( nextOffset == 0 )
{
previousFileInfo->NextEntryOffset = 0;
}
else
{
previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
}
modified = 1;
}
else
{
removedAllEntries = 0;
//前驱结点指针后移
previousFileInfo = currentFileInfo;
}
//当前指针后移
currentFileInfo = nextFileInfo;
} while( nextOffset != 0 );
if( modified )
{
if( removedAllEntries )
{
Data->IoStatus.Status = STATUS_NO_MORE_FILES;
}
else
{
FltSetCallbackDataDirty( Data );
}
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
注意以上代码使用的是宏开关,只是在编译时起作用,而非运行时。要想XP和win7都可以正常隐藏文件目录需要分别编译。
要想XP和win7同时起作用,需要去掉宏开关,然后把HideFilePostDirCtrl 改成一下代码
View Code
//实现目录隐藏,支持XP及以上版本 JiaSong[2010-11-1]
FLT_POSTOP_CALLBACK_STATUS
HideFilePostDirCtrl (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
ULONG nextOffset = 0;
int modified = 0;
int removedAllEntries = 1;
PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;
PFILE_ID_BOTH_DIR_INFORMATION currentFileIdInfo = 0;
PFILE_ID_BOTH_DIR_INFORMATION nextFileIdInfo = 0;
PFILE_ID_BOTH_DIR_INFORMATION previousFileIdInfo = 0;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
//不满足过滤条件的直接放过
if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) ||
Data->Iopb->MinorFunction != IRP_MN_QUERY_DIRECTORY ||
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length <= 0 ||
!NT_SUCCESS(Data->IoStatus.Status))
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
//XP及其以下版本,需要过滤 FileBothDirectoryInformation 类型的信息
if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
{
//我们可以得到一个缓存区,这个缓存里面就保留着文件夹中所有的文件信息。
//根据这个缓存的结构遍历处理,过滤掉要隐藏的文件名就能达到隐藏的目的了
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
{//缓存地址
currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe(
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
NormalPagePriority );
}
else
{//缓存地址
currentFileInfo=(PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
}
if(currentFileInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
previousFileInfo = currentFileInfo;
do
{
//Byte offset of the next FILE_BOTH_DIR_INFORMATION entry
nextOffset = currentFileInfo->NextEntryOffset;
//后继结点指针
nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);
KdPrint(("1.FileName: %S, ShortName: %S\n",currentFileInfo->FileName,currentFileInfo->ShortName));
if(_wcsnicmp(currentFileInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
{
KdPrint(("1.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileInfo->FileName));
if( nextOffset == 0 )
{
previousFileInfo->NextEntryOffset = 0;
}
else
{//更改前驱结点中指向下一结点的偏移量,略过要隐藏的文件的文件结点,达到隐藏目的
previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
}
modified = 1;
}
else
{
removedAllEntries = 0;
//前驱结点指针后移
previousFileInfo = currentFileInfo;
}
//当前指针后移
currentFileInfo = nextFileInfo;
} while( nextOffset != 0 );
}
//vista或win7返回的结构不再是FileBothDirectoryInformation.而是FileIdBothDirectoryInformation
else if(Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass ==FileIdBothDirectoryInformation)
{
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
{
currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)MmGetSystemAddressForMdlSafe(
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
NormalPagePriority );
}
else
{
currentFileIdInfo=(PFILE_ID_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
}
if(currentFileIdInfo==NULL)return FLT_POSTOP_FINISHED_PROCESSING;
previousFileIdInfo = currentFileIdInfo;
do
{
//Byte offset of the next FILE_ID_BOTH_DIR_INFORMATION entry
nextOffset = currentFileIdInfo->NextEntryOffset;
nextFileIdInfo = (PFILE_ID_BOTH_DIR_INFORMATION)((PCHAR)(currentFileIdInfo) + nextOffset);
KdPrint(("2.FileName: %S, ShortName: %S\n",currentFileIdInfo->FileName,currentFileIdInfo->ShortName));
if(_wcsnicmp(currentFileIdInfo->FileName,g_prefixName,wcslen(g_prefixName))==0)
{
KdPrint(("2.g_prefixName: %S, currentFileInfo->FileName: %S\n",g_prefixName,currentFileIdInfo->FileName));
if( nextOffset == 0 )
{
previousFileIdInfo->NextEntryOffset = 0;
}
else
{
previousFileIdInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileIdInfo - (PCHAR)previousFileIdInfo) + nextOffset;
}
modified = 1;
}
else
{
removedAllEntries = 0;
previousFileIdInfo = currentFileIdInfo;
}
currentFileIdInfo = nextFileIdInfo;
} while( nextOffset != 0 );
}
if( modified )
{
if( removedAllEntries )
{
Data->IoStatus.Status = STATUS_NO_MORE_FILES;
}
else
{
FltSetCallbackDataDirty( Data );
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
作者:
js2854
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。