写这篇文章的原因是看到一些代码判断不准确,
导致效果很奇怪很奇怪,当时我哭晕在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;
}
版权声明:本文为zhuhuibeishadiao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。