Callbacks does not register in minifilter-driver
07:50 20 Apr 2025

I had problem with driver. Callback func BeforeIO doesn't call in any case. Here is the code of nullfilter (minifilter-driver). However driver is working and DebugView shows that config was read. Maybe the problem is in volume, but I am not sure.

What is more, if I trying to attach driver to any volumes, windows crashes. The driver is unsigned and windows in testing mode. The problem is that DebugView doesn't show DbgPrint("sdsddsds!\n"); when I do some stuff with read and write.

#include 
#include 
#include 
#include 
#include 
#define MAX_PATH 260

#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")

typedef struct _NULL_FILTER_DATA {
    PFLT_FILTER FilterHandle;
} NULL_FILTER_DATA, * PNULL_FILTER_DATA;

NULL_FILTER_DATA NullFilterData;

enum role {
    breaker, 
    reader,
    writer,
    admin 
};

enum operation {
    reading,
    writing
};

struct oneItem {
    CHAR process[30];
    enum role rl;
};

struct oneItem processItems[20];
INT count_processItems = 0;
WCHAR targetDirectory[MAX_PATH] = { 0 };


FLT_PREOP_CALLBACK_STATUS
BeforeIO(
    PFLT_CALLBACK_DATA Data,
    PCFLT_RELATED_OBJECTS FltObjects,
    PVOID* CompletionContext
)
{
    PFLT_FILE_NAME_INFORMATION FileNameInfo;
    NTSTATUS status;
    WCHAR parentDirectory[MAX_PATH] = { 0 };
    DbgPrint("sdsddsds!\n");
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

NTSTATUS readConfig()
{
    UNICODE_STRING uniName;
    OBJECT_ATTRIBUTES objAttr;
    RtlInitUnicodeString(&uniName, L"\\??\\C:\\Users\\Art\\Desktop\\nullFilter\\conf.txt");
    InitializeObjectAttributes(&objAttr, &uniName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    HANDLE handle;
    NTSTATUS ntstatus;
    IO_STATUS_BLOCK ioStatusBlock;
    LARGE_INTEGER byteOffset;

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

    ntstatus = ZwCreateFile(&handle, GENERIC_READ, &objAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    if (!NT_SUCCESS(ntstatus)) {
        DbgPrint("Opening config file: Error %d\n", RtlNtStatusToDosError(ntstatus));
        return ntstatus;
    }
    DbgPrint("Opening config file: Success\n");

    byteOffset.LowPart = byteOffset.HighPart = 0;
    CHAR confBuffer[1024] = { 0 };
    ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock, confBuffer, sizeof(confBuffer) - 1, &byteOffset, NULL);
    if (!NT_SUCCESS(ntstatus)) {
        ZwClose(handle);
        return ntstatus;
    }

    confBuffer[ioStatusBlock.Information] = '\0';

    INT i = 2, j = 0;
    for (; confBuffer[i] != '\n' && confBuffer[i] != 13; i++, j++)
        targetDirectory[j] = confBuffer[i];
    targetDirectory[j] = '\0';
    i += 2;
    DbgPrint("Parsed targetDirectory: %ws\n", targetDirectory);
    INT size = (INT)strlen(confBuffer);
    while (i < size) {
        CHAR rule_str[50];
        j = 0;
        while (confBuffer[i] != '\n' && confBuffer[i] != '\0' && j < 49) {
            rule_str[j++] = confBuffer[i++];
        }
        rule_str[j] = '\0';
        i++;

        INT k = 0;
        while (rule_str[k] != ':' && k < 30) {
            processItems[count_processItems].process[k] = rule_str[k];
            k++;
        }
        processItems[count_processItems].process[k] = '\0';
        k++;

        for (int y = k; y < strlen(rule_str); y++) {
            if (rule_str[y] == 13)
                rule_str[y] = '\0';
        }

        if (strcmp((rule_str + k), "reader") == 0)
            processItems[count_processItems].rl = reader;
        else if (strcmp((rule_str + k), "writer") == 0)
            processItems[count_processItems].rl = writer;
        else if (strcmp((rule_str + k), "admin") == 0)
            processItems[count_processItems].rl = admin;
        else
            processItems[count_processItems].rl = breaker;

        DbgPrint("Process: %s Role: %d\n", processItems[count_processItems].process, processItems[count_processItems].rl);
        count_processItems++;
    }

    ZwClose(handle);
    return STATUS_SUCCESS;
}

// ------------------------- Callbacks -------------------------

NTSTATUS
NullUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{
    DbgPrint("NullFilter unload.\n");
    UNREFERENCED_PARAMETER(Flags);
    PAGED_CODE();
    FltUnregisterFilter(NullFilterData.FilterHandle);
    return STATUS_SUCCESS;
}

NTSTATUS
NullQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(Flags);
    PAGED_CODE();
    return STATUS_SUCCESS;
}

NTSTATUS NullInstanceSetup(
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ FLT_INSTANCE_SETUP_FLAGS Flags,
    _In_ DEVICE_TYPE VolumeDeviceType,
    _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
) {
    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(Flags);
    UNREFERENCED_PARAMETER(VolumeDeviceType);

    // Разрешаем прикрепление только к NTFS (можно убрать проверку)
    if (VolumeFilesystemType == FLT_FSTYPE_NTFS) {
        return STATUS_SUCCESS;
    }
    return STATUS_FLT_DO_NOT_ATTACH;
}


const FLT_OPERATION_REGISTRATION Callbacks[] = {
    {IRP_MJ_READ, 0, BeforeIO, NULL},
    {IRP_MJ_WRITE, 0, BeforeIO, NULL},
    {IRP_MJ_OPERATION_END}
};


const FLT_REGISTRATION FilterRegistration = {
    sizeof(FLT_REGISTRATION),
    FLT_REGISTRATION_VERSION,
    0,
    NULL,
    Callbacks,
    NullUnload,
    NullInstanceSetup,
    NullQueryTeardown,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};

// ------------------------- Entry -------------------------

NTSTATUS
DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
    DbgPrint("NullFilter driver loaded successfully.\n");
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Your message here\n");

    UNREFERENCED_PARAMETER(RegistryPath);
    NTSTATUS status;
    //DbgPrint("NullFilter driver loaded successfully.\n");
    status = FltRegisterFilter(DriverObject, &FilterRegistration, &NullFilterData.FilterHandle);
    if (!NT_SUCCESS(status))
        return status;

    status = readConfig();
    if (!NT_SUCCESS(status)) {
        DbgPrint("dddd\n");
        FltUnregisterFilter(NullFilterData.FilterHandle);
        return status;
    }

    status = FltStartFiltering(NullFilterData.FilterHandle);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to start filtering\n");
        FltUnregisterFilter(NullFilterData.FilterHandle);
    }
    return status;
}
windows callback driver minifilter