"The stub received bad data" message after stripping rights from handle access mask

I’m currently writing my first kernel-mode driver in order to test out the ObRegisterCallbacks API and protect specific processes from outside tampering. After a lot of fighting with WinDbg and Hyper-V, I can get my driver to run (SERVICE_SYSTEM_START), step through it in the debugger, and see debug output.

However, when I try to strip rights from the access mask (like PROCESS_TERMINATE), it causes a bunch of issues in Windows. The Start menu / search bar don’t work, Task Manager won’t open, and running tasklist only prints “ERROR: The stub received bad data”. I tried to google about the root cause of this error, but I’m only finding high-level tech support articles saying to update Windows and run sfc /scannow. When I asked in another driver development community, they asked if I was stripping SYNCHRONIZE or PROCESS_QUERY_LIMITED_INFORMATION (which I’m not). Here’s my callback function:

#define PROCESS_TERMINATE                  (0x0001)  

OB_PREOP_CALLBACK_STATUS pre_handle_create(void* RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) {
    ACCESS_MASK* desired_access = NULL;
    ACCESS_MASK* original_desired_access = NULL;

    switch (OperationInformation->Operation) {
        case OB_OPERATION_HANDLE_CREATE:
            desired_access = &OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
            original_desired_access = &OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess;
            break;
        case OB_OPERATION_HANDLE_DUPLICATE:
            desired_access = &OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;
            original_desired_access = &OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess;
            break;
        default:
            // This should never happen...return failure
            return 1;
            break;

    }
    ACCESS_MASK strip_flags = PROCESS_TERMINATE;

    // Leave kernel handles alone
    if (OperationInformation->KernelHandle != 1) {
        // Strip termination rights from process handles
        if (OperationInformation->ObjectType == *PsProcessType) {
            *desired_access &= ~strip_flags;
        }
    }

    UNREFERENCED_PARAMETER(RegistrationContext);
    return OB_PREOP_SUCCESS;
}

I don’t think it matters because the API doesn’t require it, but I’m not creating a device in my DriverEntry. I only register my callbacks and then return. My post-operation callback is a stub which returns immediately, which I think should be fine because I don’t initialize my registration context at all.

Does anyone know the root cause of this error message or what stub it’s referring to? Is the logic in my bit operation incorrect, (or maybe I need to do something with the original_desired_access field)?
I can provide the entire source code if needed, it’s only 1 C file about 120 lines long. This is based on Microsoft’s ObRegisterCallback driver sample on GitHub.

Sure, because those are standard processes and they expect to get the
rights they request. So your task is not quite as simple as ‘deny all these
access rights to everybody’. You are going to need to allow some processes.

Mark Roddy

@Mark_Roddy said:
Sure, because those are standard processes and they expect to get the
rights they request. So your task is not quite as simple as ‘deny all these
access rights to everybody’. You are going to need to allow some processes.

Mark Roddy

Oh right, that makes complete sense, actually. I forgot that it’s common to just request PROCESS_ALL_ACCESS sometimes. I’ll try protecting just one or two processes as a test and see how it goes. Thanks!

So you need to restrict the processes you protect and you need to allow some well known processes to do their thing.