• [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;
    }
  • 相关阅读:
    通向KDE4之路(七):文档反省器Okular和Ligature
    KDE言语绑定──KDEBindings
    KDEEdu(教诲性质软件)引见
    KDEMultimedia(KDE多媒体东西)引见
    KDESDK(KDE斥地工具)引见
    通向KDE4之路(十五):Konsole年夜整修
    企业信息化规划http://www.blogcn.com/User/fieldnet/index.html
    写在博客一周年
    Delphi 的内存操作函数(3): 给结构体指针分配内存
    在 Delphi 2009 中, for in 循环都能用在什么地方?
  • 原文地址:https://www.cnblogs.com/js2854/p/HideDir.html
Copyright © 2020-2023  润新知