I am working on a simple process filtering minifilter driver. Managed to make it work in test mode, also managed to get it signed by Microsoft. Problem is: built it in release mode with the linker's /INTEGRITYCHECK option, signed it, works perfect on my machine, and on the virtual machines that i have hosted on my local machine for testing (hyper-V).

As soon as I asked my colleague to run it, he gets a BSOD with "UNEXPECTED KERNEL MODE TRAP" after just opening some processes.

I am attaching myself to PsSetCreateProcessNotifyRoutineEx, code below. Not sure where to look at this point, I fail to understand why can't I reproduce the issue.

Registering with this:

KdPrint((DRIVER_PREFIX "Registering process callback\n"));
        //PROCESS CALLBACKS
        status = PsSetCreateProcessNotifyRoutineEx(OnProcessNotify, FALSE);
        if (!NT_SUCCESS(status)) {
            KdPrint((DRIVER_PREFIX "failed to register process callback (0x%08X)\n", status));
            KdPrint((DRIVER_PREFIX "Unregistering OnProcessNotify... \r\n"));
            PsSetCreateProcessNotifyRoutineEx(OnProcessNotify, TRUE);
            KdPrint((DRIVER_PREFIX "Unregistered OnProcessNotify \r\n"));
            return status;
        }

The structure that I'm sending to the clients:

typedef struct _ACCESS_DATA
{
    UINT32  ProcessID;
    UINT32  EventType;
    WCHAR   Path[MAX_PATH]; // [260 bytes] Max size of a full path in windows.
    WCHAR   CommandLine[MAX_CMDLINE]; // [8191 bytes] Max size of a commandline
} ACCESS_DATA, * PACCESS_DATA;

The reply structure that I'm waiting from the clients:

typedef struct _REPLY_DATA
{
    BOOLEAN Allow;      // TRUE if request is permitted, FALSE if not permitted.
    UINT32  Reserved;   // Alignment. Must be NULL.
} REPLY_DATA, * PREPLY_DATA;

The main method that I'm using. Basically upon any process interception, I am asking the client apps whether I should allow it or not. I have two separate communication channel to ask two separate applications. Again, this works perfectly on my computer and on any virtual machine I create on my computer. Not on two of my colleagues machines, nor on some other virtual machines hosted on a different on-prem server. Can't figure out why. All of them are Windows 10 x64, the driver was built for Windows 10 x64.

void OnProcessNotify(_Inout_ PEPROCESS Process, _In_ HANDLE ProcessId, _Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo) {

    UNREFERENCED_PARAMETER(Process);

    KdPrint((DRIVER_PREFIX "Started something \r\n"));
    if (CreateInfo) {

        if (CreateInfo->FileOpenNameAvailable && CreateInfo->ImageFileName)
        {
            //KdPrint(("Pid: %p\n", ProcessId));
            KdPrint((DRIVER_PREFIX "ImageFilePath: %wZ\r\n", CreateInfo->ImageFileName));
            KdPrint((DRIVER_PREFIX "CmdLine: %wZ\r\n", CreateInfo->CommandLine));

            PREPLY_DATA pReplyData = NULL;
            PREPLY_DATA ac_pReplyData = NULL;
            PAGED_CODE();

            pReplyData = ExAllocatePoolWithTag(NonPagedPool, sizeof(REPLY_DATA), REPLY_DATA_TAG);
            ac_pReplyData = ExAllocatePoolWithTag(NonPagedPool, sizeof(REPLY_DATA), REPLY_DATA_TAG);
            if (pReplyData != NULL && ac_pReplyData != NULL) {
                PPROCESS_ACCESS_DATA pAccessData;
                pAccessData = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_ACCESS_DATA), ACCESS_DATA_TAG);
                if (pAccessData != NULL) {
                    //do work
                    pAccessData->ProcessID = (UINT32)HandleToPid(ProcessId);
                    //(UINT32)(((ULONG_PTR)ProcessId) & 0xFFFFFFFF);
                    pAccessData->EventType = 8;
                    pAccessData->ParentProcessID = (UINT32)HandleToPid(CreateInfo->ParentProcessId);

                    WCHAR ProcessPath[MAX_PATH] = { 0 };
                    RtlCopyMemory(ProcessPath, CreateInfo->ImageFileName->Buffer, CreateInfo->ImageFileName->MaximumLength);
                    
                    RtlZeroMemory(pAccessData->Path, MAX_PATH * sizeof(wchar_t));
                    //RtlCopyMemory(pAccessData->Path, FileNameInfo->Name.Buffer, FileNameInfo->Name.Length);
                    RtlCopyMemory(pAccessData->Path, ProcessPath, MAX_PATH * sizeof(wchar_t));

                    WCHAR CommandLine[MAX_CMDLINE] = { 0 };
                    RtlCopyMemory(CommandLine, CreateInfo->CommandLine->Buffer, CreateInfo->CommandLine->MaximumLength);

                    RtlZeroMemory(pAccessData->CommandLine, MAX_CMDLINE * sizeof(wchar_t));
                    //RtlCopyMemory(pAccessData->CommandLine, FileNameInfo->Name.Buffer, FileNameInfo->Name.Length);
                    RtlCopyMemory(pAccessData->CommandLine, CommandLine, MAX_CMDLINE * sizeof(wchar_t));

                    KdPrint((DRIVER_PREFIX "File trying to Execute: %ws\r\n", CreateInfo->ImageFileName->Buffer));

                    //begin send the request to the first client app, if connected
                    LARGE_INTEGER Timeout;
                    Timeout.QuadPart = -((LONGLONG)1 * 1 * 1000 * 1000); // 1000 milliseconds
                    NTSTATUS status;
                    ULONG ReplyDataSize = sizeof(REPLY_DATA);
                    status = FltSendMessage(FilterHandle, &IN_ProcessPort, pAccessData, sizeof(PROCESS_ACCESS_DATA), pReplyData, &ReplyDataSize, &Timeout);
                    if (Timeout.QuadPart != 0 && NT_SUCCESS(status))
                    {
                        //block or not block
                        if (pReplyData->Allow == TRUE)
                        {
                            KdPrint((DRIVER_PREFIX "File Allowed to Execute: %ws\r\n", CreateInfo->ImageFileName->Buffer));
                        }
                        else
                        {
                            CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
                            KdPrint((DRIVER_PREFIX "Process DENIED to Execute: %ws\r\n", CreateInfo->ImageFileName->Buffer));
                        }
                    }
                    //end send the request to the first client app, if connected

                    //begin send the request to the second client app, if connected
                    LARGE_INTEGER AC_Timeout;
                    AC_Timeout.QuadPart = -((LONGLONG)10 * 1000 * (1000 * 10) /*nanoseconds*/); // 10 seconds
                    NTSTATUS ac_status;
                    ULONG AC_ReplyDataSize = sizeof(REPLY_DATA);
                    ac_status = FltSendMessage(FilterHandle, &AC_ProcessPort, pAccessData, sizeof(PROCESS_ACCESS_DATA), ac_pReplyData, &AC_ReplyDataSize, &AC_Timeout);
                    if (AC_Timeout.QuadPart != 0 && NT_SUCCESS(ac_status))
                    {
                        //block or not block
                        if (ac_pReplyData->Allow == FALSE)
                        {
                            CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
                            KdPrint((DRIVER_PREFIX "Process DENIED to Execute: %ws\r\n", CreateInfo->ImageFileName->Buffer));
                        }
                        else
                        {
                            KdPrint((DRIVER_PREFIX "File Allowed to Execute: %ws\r\n", CreateInfo->ImageFileName->Buffer));
                        }
                    }
                    //end send the request to the first client app, if connected

                    

                    ExFreePoolWithTag(pAccessData, ACCESS_DATA_TAG);
                }
                ExFreePoolWithTag(pReplyData, REPLY_DATA_TAG);
                ExFreePoolWithTag(ac_pReplyData, REPLY_DATA_TAG);
            }
        }
    }
0

There are 0 best solutions below