C语言 区分文件创建和文件打开

b5buobof  于 2023-06-28  发布在  其他
关注(0)|答案(1)|浏览(81)

虽然这不是最终目标,但描述我所做工作的最佳方式是像Sysinternals Sysmon那样跟踪文件创建。我从here复制了nullfilter示例并进行了调整。以下代码将被截断以仅显示对示例的更改:
nullfilter.c

// ...
FLT_POSTOP_CALLBACK_STATUS
FLTAPI CheckPathLengthPost(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
);
// ...

CONST FLT_OPERATION_REGISTRATION callback[] =
{
    {
        IRP_MJ_CREATE,
        0,
        CheckPathLengthPre,
        CheckPathLengthPost
    },

    {IRP_MJ_OPERATION_END}
};

CONST FLT_REGISTRATION FilterRegistration = {

    sizeof( FLT_REGISTRATION ),         //  Size
    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags

    NULL,                               //  Context
    callback,                           //  Operation callbacks

    NullUnload,                         //  FilterUnload

    NULL,                               //  InstanceSetup
    NullQueryTeardown,                  //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart
    NULL,                               //  InstanceTeardownComplete

    NULL,                               //  GenerateFileName
    NULL,                               //  GenerateDestinationFileName
    NULL                                //  NormalizeNameComponent

};
// ...
FLT_PREOP_CALLBACK_STATUS
FLTAPI CheckPathLengthPre(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{

    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext);

    if (Data->RequestorMode == KernelMode)
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

    PFLT_FILE_NAME_INFORMATION info = NULL;
    NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT | FLT_FILE_NAME_DO_NOT_CACHE, &info);
    if (!(NT_SUCCESS(status))) {
        DbgPrint("nullfilter|CheckPathLengthPre: FltGetFileNameInformation failed: %#x", status);
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    ULONG createDisp = (Data->Iopb->Parameters.Create.Options >> 24) & 0x000000FF;

    BOOLEAN isCreation = ((createDisp == FILE_CREATE) ||
        (createDisp == FILE_SUPERSEDE) ||
        (createDisp == FILE_OVERWRITE) ||
        (createDisp == FILE_OVERWRITE_IF) ||
        (createDisp == FILE_OPEN_IF));

    // File or folder is being created
    if ((Data->Iopb->Parameters.Create.Options) & FILE_NON_DIRECTORY_FILE) {
        if (isCreation == 1) {
            DbgPrint("nullfilter: isFile: %d, isDir: %d, createDisp: <%08x>, Path: %wZ", 1, 0, createDisp, info->Name);
        }
    }
    else if ((Data->Iopb->Parameters.Create.Options) & FILE_DIRECTORY_FILE) {
        if (isCreation == 1) {
            DbgPrint("nullfilter: isFile: %d, isDir: %d, createDisp: <%08x>, Path: %wZ", 0, 1, createDisp, info->Name);
        }
    }

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

nullfilter.inf

[Version]
Signature   = "$Windows NT$"
Class       = "Bottom"             ;This is determined by the work this filter driver does
ClassGuid   = {21D41938-DAA8-4615-86AE-E37344C18BD8}    ;This value is determined by the Class
Provider    = %ProviderString%
DriverVer   = 06/16/2007,1.0.0.0
CatalogFile = nullfilter.cat
; ...
[NullFilter.Service]
DisplayName      = %ServiceName%
Description      = %ServiceDescription%
ServiceBinary    = %12%\%DriverName%.sys    ;%windir%\system32\drivers\
Dependencies     = "FltMgr"
ServiceType      = 2                        ;SERVICE_FILE_SYSTEM_DRIVER
StartType        = 3                        ;SERVICE_DEMAND_START
ErrorControl     = 1                        ;SERVICE_ERROR_NORMAL
LoadOrderGroup   = "FSFilter Bottom"
AddReg           = NullFilter.AddRegistry
; ...
[Strings]
; ...
DefaultInstance         = "Null Instance"
Instance1.Name          = "Null Instance"
Instance1.Altitude      = "47777"
Instance1.Flags         = 0

这可能是我在提供来源方面发现的最好的问题:Minifilter Check new file create on harddisk?
问题是它跟踪打开和创建。我找不到任何能缩小范围的东西。这是我发现的任何其他讨论的问题:

其中大部分都是有限代码的讨论。它们似乎都暗示了我上面已经尝试过的东西。也许我在错误的位置,也许在这个低层次没有区别?

kx5bkwkv

kx5bkwkv1#

看了看https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/irp-mj-create(又一次?我想我发现了什么。
nullfilter.c

// ...
FLT_POSTOP_CALLBACK_STATUS
FLTAPI CheckPathLengthPost(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
);
// ...
FLT_PREOP_CALLBACK_STATUS
FLTAPI CheckPathLengthPre(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{

    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext);

    if (Data->RequestorMode == KernelMode)
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

    NTSTATUS status;
    PFLT_FILE_NAME_INFORMATION info = NULL;
    if (NULL != FltObjects->FileObject) {
        status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT | FLT_FILE_NAME_DO_NOT_CACHE, &info);
    }
    else {
        status = STATUS_UNSUCCESSFUL;
    }

    if (!(NT_SUCCESS(status))) {
        DbgPrint("nullfilter|CheckPathLengthPre: FltGetFileNameInformation failed: %#x", status);
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

FLT_POSTOP_CALLBACK_STATUS
FLTAPI CheckPathLengthPost(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
)
{
    PFLT_FILE_NAME_INFORMATION info;

    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext);
    UNREFERENCED_PARAMETER(Flags);

    UINT16 isCreation = ((Data->IoStatus.Information == FILE_CREATED));

    info = (PFLT_FILE_NAME_INFORMATION)CompletionContext;
    
    if (isCreation == 1) {
        DbgPrint("nullfilter|CheckPathLengthPost: Path: %wZ\r\n", info->Name);
    }

    return FLT_POSTOP_FINISHED_PROCESSING;
}

在思考了我的问题之后,我想知道为什么我又一次相信这“不起作用”。DbgView 显示了太多的活动,当然,一秒钟内没有创建数千个文件。我发现我的创作倾向太广泛了。本次测试,我只关心文件。此外,我添加了一个创建后回调,因为我相信IOStatus在预创建中是不正确的。
更改后,DbgView 的输出明显减少。列出的文件是缓存或日记文件,这两种文件肯定都是新文件。打开文件不会被“错误地”处理。

相关问题