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.