minifilter/sfilter较为精确的判断是打开还是新建操作

Posted zhuhuibeishadiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了minifilter/sfilter较为精确的判断是打开还是新建操作相关的知识,希望对你有一定的参考价值。

写这篇文章的原因是看到一些代码判断不准确,

导致效果很奇怪很奇怪,当时我哭晕在WC.

见过奇奇怪怪的判断,很无语.

于是有了这篇文章.

 

createfile可以新建文件和打开文件

这个不多说了

在文件过滤系统中IRP_MJ_CREATE

怎么判断是open还是create

无论是minifilter还是sfilter,

判断基本都相同,只不过sfilter在完成例程,minifilter在post操作

 

在sfilter的完成例程中判断irp->iostatus.Information

在Minifilter的PostCreate中Data->IoStatus.Information

这个地方的取值如下:

#define FILE_SUPERSEDED                 0x00000000
#define FILE_OPENED                     0x00000001
#define FILE_CREATED                    0x00000002
#define FILE_OVERWRITTEN                0x00000003
#define FILE_EXISTS                     0x00000004
#define FILE_DOES_NOT_EXIST             0x00000005

根据不同的值可以知道此次是新建还是打开

以下是效果:

此图是测试文件全部不存在时

此图测试文件全部存在时

此图是其它文件

第二个图为什么把FILE_SUPERSEDE标记为新文件,

FILE_SUPERSEDE:删除原文件,新建一个文件

FILE_OVERWRITE:保留文件属性,清空内容.

 

下面是测试的代码:

#include "pch.h"

static WCHAR* g_szTestFileName[] = 
    L"\\\\??\\\\C:\\\\TestOpenIf.dat",
    L"\\\\??\\\\C:\\\\TestOverWriteIf.dat",
    L"\\\\??\\\\C:\\\\TestSupersed.dat"
;

PFLT_FILTER g_FilterHandle = NULL;

EXTERN_C static NTSTATUS FLTAPI
TestUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) 

    PAGED_CODE();
    UNREFERENCED_PARAMETER(Flags);

    FltUnregisterFilter(g_FilterHandle);

    return STATUS_SUCCESS;


EXTERN_C static const WCHAR* TestGetDispositionName(ULONG ulDisposition)

//#define FILE_SUPERSEDE                  0x00000000
//#define FILE_OPEN                       0x00000001
//#define FILE_CREATE                     0x00000002
//#define FILE_OPEN_IF                    0x00000003
//#define FILE_OVERWRITE                  0x00000004
//#define FILE_OVERWRITE_IF               0x00000005
    WCHAR const *szRet = nullptr;

    switch (ulDisposition)
    
    case FILE_SUPERSEDE:
        szRet = L"FILE_SUPERSEDE";
        break;
    case FILE_OPEN:
        szRet = L"FILE_OPEN";
        break;
    case FILE_CREATE:
        szRet = L"FILE_CREATE";
        break;
    case FILE_OPEN_IF:
        szRet = L"FILE_OPEN_IF";
        break;
    case FILE_OVERWRITE:
        szRet = L"FILE_OVERWRITE";
        break;
    case FILE_OVERWRITE_IF:
        szRet = L"FILE_OVERWRITE_IF";
        break;
    default:
        szRet = L"Error Disposition";
        break;
    

    return szRet;


EXTERN_C static const WCHAR* TestGetIoStatusInformationName(ULONG ulInformation)

    /*
#define FILE_SUPERSEDED                 0x00000000
#define FILE_OPENED                     0x00000001
#define FILE_CREATED                    0x00000002
#define FILE_OVERWRITTEN                0x00000003
#define FILE_EXISTS                     0x00000004
#define FILE_DOES_NOT_EXIST             0x00000005
    */
    WCHAR const *szRet = nullptr;

    switch (ulInformation)
    
    case FILE_SUPERSEDED:
        szRet = L"FILE_SUPERSEDED";
        break;
    case FILE_OPENED:
        szRet = L"FILE_OPENED";
        break;
    case FILE_CREATED:
        szRet = L"FILE_CREATED";
        break;
    case FILE_OVERWRITTEN:
        szRet = L"FILE_OVERWRITTEN";
        break;
    case FILE_EXISTS:
        szRet = L"FILE_EXISTS";
        break;
    case FILE_DOES_NOT_EXIST:
        szRet = L"FILE_DOES_NOT_EXIST";
        break;
    default:
        szRet = L"Error IoStatusInformation";
        break;
    

    return szRet;


EXTERN_C static FLT_POSTOP_CALLBACK_STATUS FLTAPI
TestPostCreate(_Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_opt_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags) 

    UNREFERENCED_PARAMETER(CompletionContext);
    UNREFERENCED_PARAMETER(Flags);

    BOOLEAN isDir = FALSE;
    BOOLEAN bNewFile = FALSE;

    if (KeGetCurrentIrql() != PASSIVE_LEVEL) 
    
        return FLT_POSTOP_FINISHED_PROCESSING;
    

    auto status = Data->IoStatus.Status;

    if (!NT_SUCCESS(status) || (status == STATUS_REPARSE))
    
        return FLT_POSTOP_FINISHED_PROCESSING;
    

    status = FltIsDirectory(FltObjects->FileObject,
        FltObjects->Instance,
        &isDir);

    if (isDir || !NT_SUCCESS(status))
    
        return FLT_POSTOP_FINISHED_PROCESSING;
    

    //auto ulOptions = Data->Iopb->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
    auto ulDisposition = (Data->Iopb->Parameters.Create.Options & 0xFF000000) >> 24;
    //auto DesiredAccess = Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
    //auto Attributes = Data->Iopb->Parameters.Create.FileAttributes;
    
    PFLT_FILE_NAME_INFORMATION fileNameInformation = nullptr;

    status = FltGetFileNameInformationUnsafe(
        FltObjects->FileObject, FltObjects->Instance, FLT_FILE_NAME_NORMALIZED,
        &fileNameInformation);
    if (!NT_SUCCESS(status)) 
    
        return FLT_POSTOP_FINISHED_PROCESSING;
    

    status = FltParseFileNameInformation(fileNameInformation);
    if (!NT_SUCCESS(status)) 
        FltReleaseFileNameInformation(fileNameInformation);
        return FLT_POSTOP_FINISHED_PROCESSING;
    

    if (Data->IoStatus.Information == FILE_CREATED || Data->IoStatus.Information == FILE_SUPERSEDED)
        bNewFile = TRUE;

    if (bNewFile)
        DPRINT("New File:%wZ,%ws,%ws\\n", &fileNameInformation->Name, TestGetIoStatusInformationName(Data->IoStatus.Information), TestGetDispositionName(ulDisposition));
    else
        DPRINT("Open File:%wZ,%ws,%ws\\n", &fileNameInformation->Name, TestGetIoStatusInformationName(Data->IoStatus.Information), TestGetDispositionName(ulDisposition));

    FltReleaseFileNameInformation(fileNameInformation);

    return FLT_POSTOP_FINISHED_PROCESSING;


EXTERN_C static FLT_PREOP_CALLBACK_STATUS FLTAPI TestPreCreate(
    _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Outptr_result_maybenull_ PVOID *CompletionContext) 

    UNREFERENCED_PARAMETER(CompletionContext);

    ULONG_PTR stackLow;
    ULONG_PTR stackHigh;
    PFILE_OBJECT FileObject = Data->Iopb->TargetFileObject;

    if (KeGetCurrentIrql() != PASSIVE_LEVEL) 
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    IoGetStackLimits(&stackLow, &stackHigh);

    if (((ULONG_PTR)FileObject > stackLow) &&
        ((ULONG_PTR)FileObject < stackHigh)) 

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    if (FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE)) 

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY)) 

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    if (FlagOn(Data->Iopb->OperationFlags, SL_OPEN_PAGING_FILE)) 

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    if (FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN)) 

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    

    return FLT_PREOP_SYNCHRONIZE;


EXTERN_C static VOID TestThread(
    _In_ PVOID StartContext
)

    HANDLE file_handle = NULL;
    NTSTATUS status;
    IO_STATUS_BLOCK io_status;
    OBJECT_ATTRIBUTES object_attributes;
    UNICODE_STRING ufile_name =  0 ;
    ULONG ulCreateDisposition = FILE_OPEN_IF;

    for (size_t i = 0; i < sizeof(g_szTestFileName) / sizeof(WCHAR*); i++)
    
        RtlInitUnicodeString(&ufile_name, g_szTestFileName[i]);

        if (i == 0)
            ulCreateDisposition = FILE_OPEN_IF;

        if (i == 1)
            ulCreateDisposition = FILE_OVERWRITE_IF;

        if (i == 2)
            ulCreateDisposition = FILE_SUPERSEDE;

        InitializeObjectAttributes(&object_attributes, &ufile_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

        status = ZwCreateFile(

            &file_handle,

            GENERIC_READ | GENERIC_WRITE,

            &object_attributes,

            &io_status,

            NULL,

            FILE_ATTRIBUTE_NORMAL,

            FILE_SHARE_READ,

            ulCreateDisposition,

            FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,

            NULL,

            0

        );

        if (status == STATUS_SUCCESS) 

            DPRINT("file create success %wZ\\n", &ufile_name);
            ZwClose(file_handle);
        

        else 

            DPRINT("file create failed %wZ 0x%x\\n", &ufile_name, status);

        
    

    PsTerminateSystemThread(STATUS_SUCCESS);


EXTERN_C static VOID PostDriverEntry(
    _In_ struct _DRIVER_OBJECT *DriverObject,
    _In_opt_ PVOID Context,
    _In_ ULONG Count
)

    HANDLE hThread = NULL;

    PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, TestThread, NULL);

    if (hThread)
        ZwClose(hThread);


EXTERN_C NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath) 

    const FLT_OPERATION_REGISTRATION fltCallbacks[] = 
        
            IRP_MJ_CREATE, FLTFL_OPERATION_REGISTRATION_SKIP_PAGING_IO, 
            TestPreCreate,
            TestPostCreate,
        ,
        IRP_MJ_OPERATION_END ;

    const FLT_REGISTRATION filterRegistration = 
        sizeof(filterRegistration),  //  Size
        FLT_REGISTRATION_VERSION,    //  Version
        0,                           //  Flags
        nullptr,                     //  Context
        fltCallbacks,                //  Operation callbacks
        TestUnload,                 //  FilterUnload
        nullptr,                     //  InstanceSetup
        nullptr,                     //  InstanceQueryTeardown
        nullptr,                     //  InstanceTeardownStart
        nullptr,                     //  InstanceTeardownComplete
        nullptr,                     //  GenerateFileName
        nullptr,                     //  GenerateDestinationFileName
        nullptr,                     //  NormalizeNameComponent
    ;

    PAGED_CODE();
    UNREFERENCED_PARAMETER(RegistryPath);

    // Register and start a mini filter driver
    auto status = FltRegisterFilter(DriverObject, &filterRegistration,
        &g_FilterHandle);

    if (!NT_SUCCESS(status)) 
    
        DPRINT("flt register: 0x%x\\n", status);
        return status;
    

    status = FltStartFiltering(g_FilterHandle);
    if (!NT_SUCCESS(status)) 
    
        FltUnregisterFilter(g_FilterHandle);
        DPRINT("flt start: 0x%x\\n", status);
        return status;
    

    DPRINT("flt start installed.\\n");

    IoRegisterDriverReinitialization(DriverObject, PostDriverEntry, NULL);

    return status;

 

以上是关于minifilter/sfilter较为精确的判断是打开还是新建操作的主要内容,如果未能解决你的问题,请参考以下文章

C语言初级较为详细的闰年判断方法

JS 如何判断精确的判断数据类(数组对象)

js判断先判断是不是是数字或者小数,只能精确到小数点后两位,如果不是就提示,要求重新填写

BigDecimal

js精确的加减乘除

bigDecimal学习