VOID CBTdPostOperationCallback ( _In_ PVOID RegistrationContext, _In_ POB_POST_OPERATION_INFORMATION PostInfo ) { PTD_CALLBACK_REGISTRATION CallbackRegistration = (PTD_CALLBACK_REGISTRATION)RegistrationContext; TdCheckAndFreeCallContext (PostInfo, CallbackRegistration); if (PostInfo->ObjectType == *PsProcessType) { // // Ignore requests for processes other than our target process. // if (CallbackRegistration->TargetProcess != NULL && CallbackRegistration->TargetProcess != PostInfo->Object ) { return; } // // Also ignore requests that are trying to open/duplicate the current // process. // if (PostInfo->Object == PsGetCurrentProcess()) { return; } } else if (PostInfo->ObjectType == *PsThreadType) { HANDLE ProcessIdOfTargetThread = PsGetThreadProcessId ((PETHREAD)PostInfo->Object); // // Ignore requests for threads belonging to processes other than our // target process. // if (CallbackRegistration->TargetProcess != NULL && CallbackRegistration->TargetProcessId != ProcessIdOfTargetThread ) { return; } // // Also ignore requests for threads belonging to the current processes. // if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { return; } } else { TD_ASSERT (FALSE); } }
static void send_kd_state_change(DBGKD_ANY_WAIT_STATE_CHANGE* StateChange) { InException = TRUE; switch (StateChange->NewState) { case DbgKdLoadSymbolsStateChange: { /* We don't care about symbols loading */ KdpManipulateStateHandler = ContinueManipulateStateHandler; break; } case DbgKdExceptionStateChange: { PETHREAD Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; /* Save current state for later GDB queries */ CurrentStateChange = *StateChange; KDDBGPRINT("Exception 0x%08x in thread p%p.%p.\n", StateChange->u.Exception.ExceptionRecord.ExceptionCode, PsGetThreadProcessId(Thread), PsGetThreadId(Thread)); /* Set the current debugged process/thread accordingly */ gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); #if MONOPROCESS gdb_dbg_pid = 0; #else gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); #endif gdb_send_exception(FALSE); /* Next receive call will ask for the context */ KdpManipulateStateHandler = GetContextManipulateHandler; break; } default: KDDBGPRINT("Unknown StateChange %u.\n", StateChange->NewState); while (1); } }
static VOID FirstSendHandler( _In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData) { DBGKD_ANY_WAIT_STATE_CHANGE* StateChange = (DBGKD_ANY_WAIT_STATE_CHANGE*)MessageHeader->Buffer; PETHREAD Thread; if (PacketType == PACKET_TYPE_KD_DEBUG_IO) { /* This is not the packet we are waiting for */ send_kd_debug_io((DBGKD_DEBUG_IO*)MessageHeader->Buffer, MessageData); return; } if (PacketType != PACKET_TYPE_KD_STATE_CHANGE64) { KDDBGPRINT("First KD packet is not a state change!\n"); /* FIXME: What should we send back to KD ? */ while(1); } KDDBGPRINT("KDGDB: START!\n"); Thread = (PETHREAD)(ULONG_PTR)StateChange->Thread; /* Set up the current state */ CurrentStateChange = *StateChange; gdb_dbg_tid = handle_to_gdb_tid(PsGetThreadId(Thread)); #if MONOPROCESS gdb_dbg_pid = 0; #else gdb_dbg_pid = handle_to_gdb_pid(PsGetThreadProcessId(Thread)); #endif /* This is the idle process. Save it! */ TheIdleThread = Thread; TheIdleProcess = (PEPROCESS)Thread->Tcb.ApcState.Process; KDDBGPRINT("Pid Tid of the first message: %" PRIxPTR", %" PRIxPTR ".\n", gdb_dbg_pid, gdb_dbg_tid); /* The next receive call will be asking for the version data */ KdpSendPacketHandler = NULL; KdpManipulateStateHandler = GetVersionManipulateStateHandler; }
// // CBTdPreOperationCallback // OB_PREOP_CALLBACK_STATUS CBTdPreOperationCallback ( _In_ PVOID RegistrationContext, _Inout_ POB_PRE_OPERATION_INFORMATION PreInfo ) { PTD_CALLBACK_REGISTRATION CallbackRegistration; ACCESS_MASK AccessBitsToClear = 0; ACCESS_MASK AccessBitsToSet = 0; ACCESS_MASK InitialDesiredAccess = 0; ACCESS_MASK OriginalDesiredAccess = 0; PACCESS_MASK DesiredAccess = NULL; LPCWSTR ObjectTypeName = NULL; LPCWSTR OperationName = NULL; // Not using driver specific values at this time CallbackRegistration = (PTD_CALLBACK_REGISTRATION)RegistrationContext; TD_ASSERT (PreInfo->CallContext == NULL); // Only want to filter attempts to access protected process // all other processes are left untouched if (PreInfo->ObjectType == *PsProcessType) { // // Ignore requests for processes other than our target process. // // if (TdProtectedTargetProcess != NULL && // TdProtectedTargetProcess != PreInfo->Object) if (TdProtectedTargetProcess != PreInfo->Object) { goto Exit; } // // Also ignore requests that are trying to open/duplicate the current // process. // if (PreInfo->Object == PsGetCurrentProcess()) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: ignore process open/duplicate from the protected process itself\n"); goto Exit; } ObjectTypeName = L"PsProcessType"; AccessBitsToClear = CB_PROCESS_TERMINATE; AccessBitsToSet = 0; } else if (PreInfo->ObjectType == *PsThreadType) { HANDLE ProcessIdOfTargetThread = PsGetThreadProcessId ((PETHREAD)PreInfo->Object); // // Ignore requests for threads belonging to processes other than our // target process. // // if (CallbackRegistration->TargetProcess != NULL && // CallbackRegistration->TargetProcessId != ProcessIdOfTargetThread) if (TdProtectedTargetProcessId != ProcessIdOfTargetThread) { goto Exit; } // // Also ignore requests for threads belonging to the current processes. // if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: ignore thread open/duplicate from the protected process itself\n"); goto Exit; } ObjectTypeName = L"PsThreadType"; AccessBitsToClear = CB_THREAD_TERMINATE; AccessBitsToSet = 0; } else { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: unexpected object type\n"); goto Exit; } switch (PreInfo->Operation) { case OB_OPERATION_HANDLE_CREATE: DesiredAccess = &PreInfo->Parameters->CreateHandleInformation.DesiredAccess; OriginalDesiredAccess = PreInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess; OperationName = L"OB_OPERATION_HANDLE_CREATE"; break; case OB_OPERATION_HANDLE_DUPLICATE: DesiredAccess = &PreInfo->Parameters->DuplicateHandleInformation.DesiredAccess; OriginalDesiredAccess = PreInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess; OperationName = L"OB_OPERATION_HANDLE_DUPLICATE"; break; default: TD_ASSERT (FALSE); break; } InitialDesiredAccess = *DesiredAccess; // Filter only if request made outside of the kernel if (PreInfo->KernelHandle != 1) { *DesiredAccess &= ~AccessBitsToClear; *DesiredAccess |= AccessBitsToSet; } // // Set call context. // TdSetCallContext (PreInfo, CallbackRegistration); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: PROTECTED process %p (ID 0x%p)\n", TdProtectedTargetProcess, (PVOID)TdProtectedTargetProcessId ); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback\n" " Client Id: %p:%p\n" " Object: %p\n" " Type: %ls\n" " Operation: %ls (KernelHandle=%d)\n" " OriginalDesiredAccess: 0x%x\n" " DesiredAccess (in): 0x%x\n" " DesiredAccess (out): 0x%x\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), PreInfo->Object, ObjectTypeName, OperationName, PreInfo->KernelHandle, OriginalDesiredAccess, InitialDesiredAccess, *DesiredAccess ); Exit: return OB_PREOP_SUCCESS; }
/* q* packets */ static void handle_gdb_query(void) { if (strncmp(gdb_input, "qSupported:", 11) == 0) { #if MONOPROCESS send_gdb_packet("PacketSize=1000;"); #else send_gdb_packet("PacketSize=1000;multiprocess+;"); #endif return; } if (strncmp(gdb_input, "qAttached", 9) == 0) { #if MONOPROCESS send_gdb_packet("1"); #else UINT_PTR queried_pid = hex_to_pid(&gdb_input[10]); /* Let's say we created system process */ if (gdb_pid_to_handle(queried_pid) == NULL) send_gdb_packet("0"); else send_gdb_packet("1"); #endif return; } if (strncmp(gdb_input, "qRcmd,", 6) == 0) { send_gdb_packet("OK"); return; } if (strcmp(gdb_input, "qC") == 0) { char gdb_out[64]; #if MONOPROCESS sprintf(gdb_out, "QC:%"PRIxPTR";", handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))); #else sprintf(gdb_out, "QC:p%"PRIxPTR".%"PRIxPTR";", handle_to_gdb_pid(PsGetThreadProcessId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread)), handle_to_gdb_tid(PsGetThreadId((PETHREAD)(ULONG_PTR)CurrentStateChange.Thread))); #endif send_gdb_packet(gdb_out); return; } if ((strncmp(gdb_input, "qfThreadInfo", 12) == 0) || (strncmp(gdb_input, "qsThreadInfo", 12) == 0)) { BOOLEAN FirstThread = TRUE; PEPROCESS Process; PETHREAD Thread; char gdb_out[1024]; char* ptr = gdb_out; BOOLEAN Resuming = strncmp(gdb_input, "qsThreadInfo", 12) == 0; /* Keep track of where we are. */ static LIST_ENTRY* CurrentProcessEntry; static LIST_ENTRY* CurrentThreadEntry; ptr = gdb_out; *ptr++ = 'm'; /* NULL terminate in case we got nothing more to iterate */ *ptr = '\0'; if (!Resuming) { /* Initialize the entries */ CurrentProcessEntry = ProcessListHead->Flink; CurrentThreadEntry = NULL; /* Start with idle thread */ #if MONOPROCESS ptr = gdb_out + sprintf(gdb_out, "m1"); #else ptr = gdb_out + sprintf(gdb_out, "mp1.1"); #endif FirstThread = FALSE; } if (CurrentProcessEntry == NULL) /* Ps is not initialized */ { send_gdb_packet(Resuming ? "l" : gdb_out); return; } /* List all the processes */ for ( ; CurrentProcessEntry != ProcessListHead; CurrentProcessEntry = CurrentProcessEntry->Flink) { Process = CONTAINING_RECORD(CurrentProcessEntry, EPROCESS, ActiveProcessLinks); if (CurrentThreadEntry != NULL) CurrentThreadEntry = CurrentThreadEntry->Flink; else CurrentThreadEntry = Process->ThreadListHead.Flink; /* List threads from this process */ for ( ; CurrentThreadEntry != &Process->ThreadListHead; CurrentThreadEntry = CurrentThreadEntry->Flink) { Thread = CONTAINING_RECORD(CurrentThreadEntry, ETHREAD, ThreadListEntry); /* See if we should add a comma */ if (FirstThread) { FirstThread = FALSE; } else { *ptr++ = ','; } #if MONOPROCESS ptr += _snprintf(ptr, 1024 - (ptr - gdb_out), "%p", handle_to_gdb_tid(Thread->Cid.UniqueThread)); #else ptr += _snprintf(ptr, 1024 - (ptr - gdb_out), "p%p.%p", handle_to_gdb_pid(Process->UniqueProcessId), handle_to_gdb_tid(Thread->Cid.UniqueThread)); #endif if (ptr > (gdb_out + 1024)) { /* send what we got */ send_gdb_packet(gdb_out); /* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo packet */ return; } } /* We're done for this process */ CurrentThreadEntry = NULL; } if (gdb_out[1] == '\0') { /* We didn't iterate over anything, meaning we were already done */ send_gdb_packet("l"); } else { send_gdb_packet(gdb_out); } /* GDB can ask anything at this point, it isn't necessarily a qsThreadInfo packet */ return; } if (strncmp(gdb_input, "qThreadExtraInfo,", 17) == 0) { ULONG_PTR Pid, Tid; PETHREAD Thread; PEPROCESS Process; char out_string[64]; STRING String = {0, 64, out_string}; KDDBGPRINT("Giving extra info for"); #if MONOPROCESS Pid = 0; Tid = hex_to_tid(&gdb_input[17]); KDDBGPRINT(" %p.\n", Tid); Thread = find_thread(Pid, Tid); Process = CONTAINING_RECORD(Thread->Tcb.Process, EPROCESS, Pcb); #else Pid = hex_to_pid(&gdb_input[2]); Tid = hex_to_tid(strstr(gdb_input, ".") + 1); /* We cannot use PsLookupProcessThreadByCid as we could be running at any IRQL. * So loop. */ KDDBGPRINT(" p%p.%p.\n", Pid, Tid); Process = find_process(Pid); Thread = find_thread(Pid, Tid); #endif if (PsGetThreadProcessId(Thread) == 0) { String.Length = sprintf(out_string, "SYSTEM"); } else { String.Length = sprintf(out_string, "%.*s", 16, Process->ImageFileName); } gdb_send_debug_io(&String, FALSE); return; } if (strncmp(gdb_input, "qOffsets", 8) == 0) { /* We load ntoskrnl at 0x80800000 while compiling it at 0x00800000 base adress */ send_gdb_packet("TextSeg=80000000"); return; } if (strcmp(gdb_input, "qTStatus") == 0) { /* No tracepoint support */ send_gdb_packet("T0"); return; } KDDBGPRINT("KDGDB: Unknown query: %s\n", gdb_input); send_gdb_packet(""); return; }