diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp index 758862f4..6d42e6f4 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp @@ -332,11 +332,12 @@ CommandTestQueryPreAllocPoolsState() /** * @brief test command for setting target tasks to halted cores + * @param Synchronous * * @return VOID */ VOID -CommandTestSetTargetTaskToHaltedCores() +CommandTestSetTargetTaskToHaltedCores(BOOLEAN Synchronous) { if (!g_IsSerialConnectedToRemoteDebuggee) { @@ -348,7 +349,29 @@ CommandTestSetTargetTaskToHaltedCores() // // Send the target tasks to the halted cores // - KdSendTestQueryPacketToDebuggee(TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES); + KdSendTestQueryPacketToDebuggee(Synchronous ? TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS : TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS); +} + +/** + * @brief test command for setting target task to the specified core + * @param CoreNumber + * + * @return VOID + */ +VOID +CommandTestSetTargetTaskToTargetCore(UINT32 CoreNumber) +{ + if (!g_IsSerialConnectedToRemoteDebuggee) + { + ShowMessages("err, query state of the debuggee is only possible when you connected " + "in debugger mode\n"); + return; + } + + // + // Send the target task to the target halted core + // + KdSendTestQueryPacketWithContextToDebuggee(TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES, (UINT64)CoreNumber); } /** @@ -389,6 +412,8 @@ CommandTestSetBreakpointState(BOOLEAN State) VOID CommandTest(vector SplittedCommand, string Command) { + UINT64 Context = NULL; + if (SplittedCommand.size() == 1) { // @@ -417,12 +442,32 @@ CommandTest(vector SplittedCommand, string Command) // CommandTestQueryPreAllocPoolsState(); } - else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("task")) + else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("sync-task")) { // - // Send target task to the halted cores in debugger mode + // Send target task to the halted cores in debugger mode (synchronous) // - CommandTestSetTargetTaskToHaltedCores(); + CommandTestSetTargetTaskToHaltedCores(TRUE); + } + else if (SplittedCommand.size() == 2 && !SplittedCommand.at(1).compare("async-task")) + { + // + // Send target task to the halted cores in debugger mode (asynchronous) + // + CommandTestSetTargetTaskToHaltedCores(FALSE); + } + else if (SplittedCommand.size() == 3 && !SplittedCommand.at(1).compare("target-core-task")) + { + if (!ConvertStringToUInt64(SplittedCommand.at(2), &Context)) + { + ShowMessages("err, you should enter a valid hex number as the core id\n\n"); + return; + } + + // + // Send target task to the specific halted core in debugger mode + // + CommandTestSetTargetTaskToTargetCore((UINT32)Context); } else if (SplittedCommand.size() == 3 && !SplittedCommand.at(1).compare("breakpoint")) { diff --git a/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp b/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp index 5dd9bbd6..280985a5 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/core/debugger.cpp @@ -391,6 +391,13 @@ ShowErrorMessage(UINT32 Error) Error); break; + case DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE: + ShowMessages("err, you cannot specify process id while the debugger is paused in the debugger mode. " + "You can use the '.process' or the '.thread' command to switch to the target process's " + "memory layout (%x)\n", + Error); + break; + default: ShowMessages("err, error not found (%x)\n", Error); diff --git a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp b/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp index 967e1834..fc04f55c 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kd.cpp @@ -417,6 +417,7 @@ KdSendCallStackPacketToDebuggee(UINT64 BaseAddress, * @brief Send a test query request to the debuggee * * @param Type + * * @return BOOLEAN */ BOOLEAN @@ -446,6 +447,42 @@ KdSendTestQueryPacketToDebuggee(DEBUGGER_TEST_QUERY_STATE Type) return TRUE; } +/** + * @brief Send a test query request to the debuggee with the specified context + * + * @param Type + * @param Context + * + * @return BOOLEAN + */ +BOOLEAN +KdSendTestQueryPacketWithContextToDebuggee(DEBUGGER_TEST_QUERY_STATE Type, UINT64 Context) +{ + DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket = {0}; + + TestQueryPacket.RequestType = Type; + TestQueryPacket.Context = Context; + + // + // Send 'test query' command as query packet + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_TEST_QUERY, + (CHAR *)&TestQueryPacket, + sizeof(DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER))) + { + return FALSE; + } + + // + // Wait until the result of test query is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_TEST_QUERY); + + return TRUE; +} + /** * @brief Send symbol reload packet to the debuggee * diff --git a/hyperdbg/hprdbgctrl/header/kd.h b/hyperdbg/hprdbgctrl/header/kd.h index cea14efd..35bf01c7 100644 --- a/hyperdbg/hprdbgctrl/header/kd.h +++ b/hyperdbg/hprdbgctrl/header/kd.h @@ -121,6 +121,9 @@ KdSendCallStackPacketToDebuggee(UINT64 BaseAddress, BOOLEAN KdSendTestQueryPacketToDebuggee(DEBUGGER_TEST_QUERY_STATE Type); +BOOLEAN +KdSendTestQueryPacketWithContextToDebuggee(DEBUGGER_TEST_QUERY_STATE Type, UINT64 Context); + BOOLEAN KdSendSymbolReloadPacketToDebuggee(UINT32 ProcessId); diff --git a/hyperdbg/hprdbgkd/code/common/Common.c b/hyperdbg/hprdbgkd/code/common/Common.c index 32db604d..fa3ee699 100644 --- a/hyperdbg/hprdbgkd/code/common/Common.c +++ b/hyperdbg/hprdbgkd/code/common/Common.c @@ -243,3 +243,27 @@ CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod) // return TRUE; } + +/** + * @brief Validate core number + * @param CoreNumber + * + * @return BOOLEAN + */ +_Use_decl_annotations_ +BOOLEAN +CommonValidateCoreNumber(UINT32 CoreNumber) +{ + ULONG CoreCount; + + CoreCount = KeQueryActiveProcessorCount(0); + + if (CoreNumber >= CoreCount) + { + return FALSE; + } + else + { + return TRUE; + } +} diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c b/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c index 2e1d8f6c..6d82cbfa 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c +++ b/hyperdbg/hprdbgkd/code/debugger/commands/BreakpointCommands.c @@ -835,7 +835,6 @@ BOOLEAN BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) { PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL; - UINT32 ProcessorCount; CR3_TYPE GuestCr3; BOOLEAN IsAddress32Bit = FALSE; @@ -860,10 +859,8 @@ BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg) // // Check if the core number is not invalid // - ProcessorCount = KeQueryActiveProcessorCount(0); - if (BpDescriptorArg->Core != DEBUGGEE_BP_APPLY_TO_ALL_CORES && - BpDescriptorArg->Core >= ProcessorCount) + !CommonValidateCoreNumber(BpDescriptorArg->Core)) { // // Core is invalid (Set the error) diff --git a/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c b/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c index f0c586ec..2c8f5b40 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c +++ b/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c @@ -2105,33 +2105,24 @@ DebuggerRemoveEvent(UINT64 Tag) } /** - * @brief Routine for validating and parsing events - * that came from user-mode + * @brief validating events * * @param EventDetails The structure that describes event that came - * from the user-mode + * from the user-mode or VMX-root mode * @param BufferLength Length of the buffer - * @param ResultsToReturnUsermode Result buffer that should be returned to + * @param ResultsToReturn Result buffer that should be returned to * the user-mode - * @return BOOLEAN TRUE if the event was valid an regisered without error, - * otherwise returns FALSE + * @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL + * + * @return BOOLEAN TRUE if the event was valid otherwise returns FALSE */ BOOLEAN -DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode) +DebuggerValidateEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, + UINT32 BufferLength, + PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn, + BOOLEAN InputFromVmxRoot) { - PDEBUGGER_EVENT Event; - UINT64 PagesBytes; - UINT32 TempPid; - UINT32 ProcessorCount; - BOOLEAN ResultOfApplyingEvent = FALSE; - - ProcessorCount = KeQueryActiveProcessorCount(0); - - // - // ---------------------------------------------------------------------------------- - // *** Validating the Event's parameters *** - // ---------------------------------------------------------------------------------- - // + UINT32 TempPid; // // Check whether the event mode (calling stage) to see whether @@ -2143,8 +2134,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION) && EventDetails->EnableShortCircuiting == TRUE) { - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_USING_SHORT_CIRCUITING_EVENT_WITH_POST_EVENT_MODE_IS_FORBIDDEDN; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_USING_SHORT_CIRCUITING_EVENT_WITH_POST_EVENT_MODE_IS_FORBIDDEDN; return FALSE; } @@ -2157,14 +2148,14 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // Check if the core number is not invalid // - if (EventDetails->CoreId >= ProcessorCount) + if (!CommonValidateCoreNumber(EventDetails->CoreId)) { // // CoreId is invalid (Set the error) // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_CORE_ID; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_CORE_ID; return FALSE; } } @@ -2176,13 +2167,19 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT if (EventDetails->ProcessId != DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES && EventDetails->ProcessId != 0) { // - // The used specified a special pid, let's check if it's valid or not + // Here we prefer not to validate the process id, if it's applied from VMX-root mode // - if (!CommonIsProcessExist(EventDetails->ProcessId)) + if (!InputFromVmxRoot) { - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_PROCESS_ID; - return FALSE; + // + // The used specified a special pid, let's check if it's valid or not + // + if (!CommonIsProcessExist(EventDetails->ProcessId)) + { + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_PROCESS_ID; + return FALSE; + } } } @@ -2199,8 +2196,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // more than 32 indexes we should use pin-based external interrupt // exiting which is completely different // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES; return FALSE; } } @@ -2215,8 +2212,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // The IDT Entry is either invalid or is not in the range // of the pin-based external interrupt exiting controls // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID; return FALSE; } } @@ -2232,8 +2229,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // The execution mode is not correctly applied // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID; return FALSE; } } @@ -2243,21 +2240,55 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // First check if the address are valid // TempPid = EventDetails->ProcessId; + if (TempPid == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES) { TempPid = PsGetCurrentProcessId(); } - if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL) + // + // Check if input is coming from VMX-root or not + // If it's coming from VMX-root, then as switching + // to another process is not possible, we'll return + // an error + // + if (InputFromVmxRoot && TempPid != PsGetCurrentProcessId()) { - // - // Address is invalid (Set the error) - // - - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE; return FALSE; } + + // + // Check whether address is valid or not based on whether the event needs + // to be applied directly from VMX-root mode or not + // + if (InputFromVmxRoot) + { + if (VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam1) == NULL) + { + // + // Address is invalid (Set the error) + // + + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + } + else + { + if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL) + { + // + // Address is invalid (Set the error) + // + + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + } } else if (EventDetails->EventType == HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE || EventDetails->EventType == HIDDEN_HOOK_READ_AND_WRITE || @@ -2276,92 +2307,90 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT TempPid = PsGetCurrentProcessId(); } - if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL || VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam2, TempPid) == NULL) + // + // Check if input is coming from VMX-root or not + // If it's coming from VMX-root, then as switching + // to another process is not possible, we'll return + // an error + // + if (InputFromVmxRoot && TempPid != PsGetCurrentProcessId()) { - // - // Address is invalid (Set the error) - // - - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE; return FALSE; } + // + // Check whether address is valid or not based on whether the event needs + // to be applied directly from VMX-root mode or not + // + if (InputFromVmxRoot) + { + if (VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam1) == NULL || + VirtualAddressToPhysicalAddressOnTargetProcess(EventDetails->OptionalParam2) == NULL) + { + // + // Address is invalid (Set the error) + // + + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + } + else + { + if (VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam1, TempPid) == NULL || + VirtualAddressToPhysicalAddressByProcessId(EventDetails->OptionalParam2, TempPid) == NULL) + { + // + // Address is invalid (Set the error) + // + + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + return FALSE; + } + } + // // Check if the 'to' is greater that 'from' // if (EventDetails->OptionalParam1 >= EventDetails->OptionalParam2) { - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ADDRESS; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS; return FALSE; } } // - // ---------------------------------------------------------------------------------- - // Create Event - // ---------------------------------------------------------------------------------- + // As we reached, all the checks are passed and it means the event is valid // + return TRUE; +} - // - // We initialize event with disabled mode as it doesn't have action yet - // - if (EventDetails->ConditionBufferSize != 0) - { - // - // Conditional Event - // - Event = DebuggerCreateEvent(FALSE, - EventDetails->CoreId, - EventDetails->ProcessId, - EventDetails->EventType, - EventDetails->Tag, - EventDetails->OptionalParam1, - EventDetails->OptionalParam2, - EventDetails->OptionalParam3, - EventDetails->OptionalParam4, - EventDetails->ConditionBufferSize, - (UINT64)EventDetails + sizeof(DEBUGGER_GENERAL_EVENT_DETAIL)); - } - else - { - // - // Unconditional Event - // - Event = DebuggerCreateEvent(FALSE, - EventDetails->CoreId, - EventDetails->ProcessId, - EventDetails->EventType, - EventDetails->Tag, - EventDetails->OptionalParam1, - EventDetails->OptionalParam2, - EventDetails->OptionalParam3, - EventDetails->OptionalParam4, - 0, - NULL); - } - - if (Event == NULL) - { - // - // Set the error - // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT; - return FALSE; - } - - // - // Register the event - // - DebuggerRegisterEvent(Event); - - // - // ---------------------------------------------------------------------------------- - // Apply & Enable Event - // ---------------------------------------------------------------------------------- - // +/** + * @brief Applying events + * + * @param EventDetails The structure that describes event that came + * from the user-mode or VMX-root mode + * @param BufferLength Length of the buffer + * @param ResultsToReturn Result buffer that should be returned to + * the user-mode + * @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL + * + * @return BOOLEAN TRUE if the event was applied otherwise returns FALSE + */ +BOOLEAN +DebuggerApplyEvent(PDEBUGGER_EVENT Event, + PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, + UINT32 BufferLength, + PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn, + BOOLEAN InputFromVmxRoot) +{ + UINT64 PagesBytes; + BOOLEAN ResultOfApplyingEvent = FALSE; // // Now we should configure the cpu to generate the events @@ -2447,8 +2476,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT default: LogError("Err, Invalid monitor hook type"); - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID; goto ClearTheEventAfterCreatingEvent; @@ -2500,8 +2529,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // if (!ResultOfApplyingEvent) { - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DebuggerGetLastError(); + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DebuggerGetLastError(); goto ClearTheEventAfterCreatingEvent; } @@ -2528,8 +2557,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // There was an error applying this event, so we're setting // the event // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DebuggerGetLastError(); + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DebuggerGetLastError(); goto ClearTheEventAfterCreatingEvent; } @@ -2561,8 +2590,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // There was an error applying this event, so we're setting // the event // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DebuggerGetLastError(); + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DebuggerGetLastError(); goto ClearTheEventAfterCreatingEvent; } @@ -3011,8 +3040,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // Set the error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID; goto ClearTheEventAfterCreatingEvent; break; @@ -3046,8 +3075,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // Set the status // - ResultsToReturnUsermode->IsSuccessful = TRUE; - ResultsToReturnUsermode->Error = 0; + ResultsToReturn->IsSuccessful = TRUE; + ResultsToReturn->Error = 0; // // Event was applied successfully @@ -3056,15 +3085,127 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT ClearTheEventAfterCreatingEvent: + return FALSE; +} + +/** + * @brief Routine for parsing events + * + * @param EventDetails The structure that describes event that came + * from the user-mode + * @param BufferLength Length of the buffer + * @param ResultsToReturn Result buffer that should be returned to + * the user-mode + * @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL + * + * @return BOOLEAN TRUE if the event was valid an regisered without error, + * otherwise returns FALSE + */ +BOOLEAN +DebuggerParseEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, + UINT32 BufferLength, + PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn, + BOOLEAN InputFromVmxRoot) +{ + PDEBUGGER_EVENT Event; + // - // Remove the event as it was not successfull + // ---------------------------------------------------------------------------------- + // *** Validating the Event's parameters *** + // ---------------------------------------------------------------------------------- // - if (Event != NULL) + + // + // Validate the event parameters + // + if (!DebuggerValidateEvent(EventDetails, BufferLength, ResultsToReturn, InputFromVmxRoot)) { - DebuggerRemoveEvent(Event->Tag); + // + // Input event is not valid + // + return FALSE; } - return FALSE; + // + // ---------------------------------------------------------------------------------- + // *** Create Event *** + // ---------------------------------------------------------------------------------- + // + + // + // We initialize event with disabled mode as it doesn't have action yet + // + if (EventDetails->ConditionBufferSize != 0) + { + // + // Conditional Event + // + Event = DebuggerCreateEvent(FALSE, + EventDetails->CoreId, + EventDetails->ProcessId, + EventDetails->EventType, + EventDetails->Tag, + EventDetails->OptionalParam1, + EventDetails->OptionalParam2, + EventDetails->OptionalParam3, + EventDetails->OptionalParam4, + EventDetails->ConditionBufferSize, + (UINT64)EventDetails + sizeof(DEBUGGER_GENERAL_EVENT_DETAIL)); + } + else + { + // + // Unconditional Event + // + Event = DebuggerCreateEvent(FALSE, + EventDetails->CoreId, + EventDetails->ProcessId, + EventDetails->EventType, + EventDetails->Tag, + EventDetails->OptionalParam1, + EventDetails->OptionalParam2, + EventDetails->OptionalParam3, + EventDetails->OptionalParam4, + 0, + NULL); + } + + if (Event == NULL) + { + // + // Set the error + // + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT; + return FALSE; + } + + // + // Register the event + // + DebuggerRegisterEvent(Event); + + // + // ---------------------------------------------------------------------------------- + // *** Apply & Enable Event *** + // ---------------------------------------------------------------------------------- + // + if (DebuggerApplyEvent(Event, EventDetails, BufferLength, ResultsToReturn, InputFromVmxRoot)) + { + return TRUE; + } + else + { + // + // Remove the event as it was not successfull + // + if (Event != NULL) + { + DebuggerRemoveEvent(Event->Tag); + } + + return FALSE; + } } /** @@ -3075,13 +3216,13 @@ ClearTheEventAfterCreatingEvent: * @param Action Structure that describes the action that comes from the * user-mode * @param BufferLength Length of the buffer that comes from user-mode - * @param ResultsToReturnUsermode The buffer address that should be returned + * @param ResultsToReturn The buffer address that should be returned * to the user-mode as the result * @return BOOLEAN if action was parsed and added successfully, return TRUE * otherwise, returns FALSE */ BOOLEAN -DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode) +DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn) { // // Check if Tag is valid or not @@ -3093,8 +3234,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe // // Set the appropriate error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_TAG_NOT_EXISTS; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_TAG_NOT_EXISTS; // // Show that the @@ -3112,8 +3253,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe // // Set the appropriate error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO; // // Show that the @@ -3150,8 +3291,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe // // Set the appropriate error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO; // // Show that the @@ -3192,8 +3333,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe // // Set the appropriate error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_INVALID_ACTION_TYPE; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ACTION_TYPE; // // Show that the @@ -3201,8 +3342,8 @@ DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLe return FALSE; } - ResultsToReturnUsermode->IsSuccessful = TRUE; - ResultsToReturnUsermode->Error = 0; + ResultsToReturn->IsSuccessful = TRUE; + ResultsToReturn->Error = 0; return TRUE; } diff --git a/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c b/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c index 3e72eb6f..a428da75 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c +++ b/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c @@ -32,24 +32,108 @@ HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState, } /** - * @brief Broadcast tasks to halted cores + * @brief Run the task on a single halted core * @details This function should be called from VMX root-mode * - * @param DbgState The state of the debugger on the current core + * @param TargetCoreId The target core's ID (to just run on this core) * @param TargetTask The target task * @param LockAgainAfterTask Lock the core after the task * * @return VOID */ VOID -HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, - UINT32 TargetTask, - BOOLEAN LockAgainAfterTask) +HaltedCoreApplyTaskOnTargetCore(UINT32 TargetCoreId, + UINT32 TargetTask, + BOOLEAN LockAgainAfterTask) +{ + PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[TargetCoreId]; + + // + // Activate running the halted task + // + DbgState->HaltedCoreTask.PerformHaltedTask = TRUE; + + DbgState->HaltedCoreTask.KernelStatus = NULL; + DbgState->HaltedCoreTask.LockAgainAfterTask = LockAgainAfterTask; + DbgState->HaltedCoreTask.TargetTask = TargetTask; + + // + // Unlock halted core + // + KdUnlockTheHaltedCore(DbgState); +} + +/** + * @brief Run the task on a single halted core + * @details This function should be called from VMX root-mode + * + * @param TargetCoreId The target core's ID (to just run on this core) + * @param TargetTask The target task + * @param LockAgainAfterTask Lock the core after the task + * + * @return VOID + */ +VOID +HaltedCoreRunTaskOnSingleCore(UINT32 TargetCoreId, + UINT32 TargetTask, + BOOLEAN LockAgainAfterTask) +{ + // + // Check if the task needs to be executed for the current + // core or any other cores + // + if (TargetCoreId == KeGetCurrentProcessorNumberEx(NULL)) + { + // + // *** Perform the task for the current core *** + // + HaltedCorePerformTargetTask(&g_DbgState[TargetCoreId], TargetTask); + } + else + { + // + // *** Perform the task for another core *** + // + + // + // apply task to the target core + // + HaltedCoreApplyTaskOnTargetCore(TargetCoreId, TargetTask, LockAgainAfterTask); + } +} + +/** + * @brief Broadcast tasks to halted cores + * @details This function should be called from VMX root-mode + * + * @param DbgState The state of the debugger on the current core + * @param TargetTask The target task + * @param LockAgainAfterTask Lock the core after the task + * @param Synchronize Whether the function should wait for all cores to synchronize + * and lock again or not + * + * @return BOOLEAN + */ +BOOLEAN +HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, + UINT32 TargetTask, + BOOLEAN LockAgainAfterTask, + BOOLEAN Synchronize) { ULONG CoreCount; CoreCount = KeQueryActiveProcessorCount(0); + // + // Synchronization is not possible when the locking after the task is + // not expected + // + if (Synchronize && !LockAgainAfterTask) + { + LogWarning("Synchronization is not possible when the locking after the task is not expected"); + return FALSE; + } + // // Apply the task to all cores except current core // @@ -58,23 +142,53 @@ HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, if (DbgState->CoreId != i) { // - // Activate running the halted task + // apply task to the target core // - g_DbgState[i].HaltedCoreTask.PerformHaltedTask = TRUE; - - g_DbgState[i].HaltedCoreTask.KernelStatus = NULL; - g_DbgState[i].HaltedCoreTask.LockAgainAfterTask = LockAgainAfterTask; - g_DbgState[i].HaltedCoreTask.TargetTask = TargetTask; - + HaltedCoreApplyTaskOnTargetCore(i, TargetTask, LockAgainAfterTask); + } + else + { // - // Unlock halted core + // Perform the task for the current core // - KdUnlockTheHaltedCore(&g_DbgState[i]); + HaltedCorePerformTargetTask(DbgState, TargetTask); } } // - // Perform the task for the current core + // If synchronization is expected, we need to check to make sure + // all cores are synchronized (locked) at this point or not // - HaltedCorePerformTargetTask(DbgState, TargetTask); + if (Synchronize) + { + for (size_t i = 0; i < CoreCount; i++) + { + if (DbgState->CoreId != i) + { + // + // Wait until the core is locked again + // + while (TRUE) + { + // + // Keep checking to make sure the target core finished the + // execution its task and locked again + // + if (KdCheckTheHaltedCore(&g_DbgState[i]) == FALSE) + { + continue; + } + else + { + break; + } + } + } + } + } + + // + // All cores locked again + // + return TRUE; } diff --git a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c index 6828cebd..28d5da30 100644 --- a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c @@ -1591,7 +1591,7 @@ KdQuerySystemState() for (size_t i = 0; i < CoreCount; i++) { - if (g_DbgState[i].Lock) + if (SpinlockCheckLock(&g_DbgState[i].Lock)) { LogInfo("Core : %d is locked", i); } @@ -1623,7 +1623,7 @@ KdQuerySystemState() /** * @brief unlock the target core * - * @param DbgState The state of the debugger on the current core + * @param DbgState The state of the debugger on the target core * * @return VOID */ @@ -1633,6 +1633,19 @@ KdUnlockTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState) SpinlockUnlock(&DbgState->Lock); } +/** + * @brief check the lock state of the target core + * + * @param DbgState The state of the debugger on the target core + * + * @return BOOLEAN + */ +BOOLEAN +KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState) +{ + return SpinlockCheckLock(&DbgState->Lock); +} + /** * @brief routines to break page-in * @@ -1680,6 +1693,150 @@ KdBringPagein(PROCESSOR_DEBUGGING_STATE * DbgState, } } +/** + * @brief Perform the test packet's operation + * + * @param DbgState The state of the debugger on the current core + * @param TestQueryPacket test packet request + * + * @return VOID + */ +VOID +KdPerformTheTestPacketOperation(PROCESSOR_DEBUGGING_STATE * DbgState, + DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER * TestQueryPacket) +{ + // + // Dispatch the request + // + switch (TestQueryPacket->RequestType) + { + case TEST_QUERY_HALTING_CORE_STATUS: + + // + // Query state of the system + // + KdQuerySystemState(); + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_QUERY_TRAP_STATE: + + // + // Query state of the trap + // + KdQueryRflagTrapState(); + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_QUERY_PREALLOCATED_POOL_STATE: + + // + // Query state of pre-allocated pools + // + PoolManagerShowPreAllocatedPools(); + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS: + case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS: + + // + // Send request for the target task to the halted cores (synchronized and unsynchronized) + // + HaltedCoreBroadcastTaskAllCores(DbgState, + 0x55, + TRUE, + TestQueryPacket->RequestType == TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS ? TRUE : FALSE); + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES: + + // + // Validate core number + // + if (!CommonValidateCoreNumber(TestQueryPacket->Context)) + { + // + // Core number is invalid + // + TestQueryPacket->KernelStatus = DEBUGGER_ERROR_INVALID_CORE_ID; + } + else + { + // + // Send request for the target task to the target halted core + // + HaltedCoreRunTaskOnSingleCore((UINT32)TestQueryPacket->Context, 0x8585, TRUE); + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + } + + break; + + case TEST_BREAKPOINT_TURN_OFF_BPS: + + // + // Turn off the breakpoint interception + // + g_InterceptBreakpoints = TRUE; + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_BREAKPOINT_TURN_ON_BPS: + + // + // Turn on the breakpoint interception + // + g_InterceptBreakpoints = FALSE; + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER: + + // + // Turn off the breakpoints and events interception before executing the commands in the remote computer + // + g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = TRUE; + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + case TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER: + + // + // Turn on the breakpoints and events interception after finishing the commands in the remote computer + // + g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = FALSE; + + TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + + break; + + default: + + // + // Query index not found + // + TestQueryPacket->KernelStatus = DEBUGGER_ERROR_UNKNOWN_TEST_QUERY_RECEIVED; + + break; + } +} + /** * @brief Perform modify the state of short-circuiting * @@ -2168,107 +2325,9 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) TestQueryPacket = (DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); // - // Dispatch the request + // Perform the test packet operation // - switch (TestQueryPacket->RequestType) - { - case TEST_QUERY_HALTING_CORE_STATUS: - - // - // Query state of the system - // - KdQuerySystemState(); - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_QUERY_TRAP_STATE: - - // - // Query state of the trap - // - KdQueryRflagTrapState(); - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_QUERY_PREALLOCATED_POOL_STATE: - - // - // Query state of pre-allocated pools - // - PoolManagerShowPreAllocatedPools(); - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES: - - // - // Send request for the target task to the halted cores - // - HaltedCoreBroadcasTaskToAllCores(DbgState, 0x55, TRUE); - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_BREAKPOINT_TURN_OFF_BPS: - - // - // Turn off the breakpoint interception - // - g_InterceptBreakpoints = TRUE; - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_BREAKPOINT_TURN_ON_BPS: - - // - // Turn on the breakpoint interception - // - g_InterceptBreakpoints = FALSE; - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER: - - // - // Turn off the breakpoints and events interception before executing the commands in the remote computer - // - g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = TRUE; - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - case TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER: - - // - // Turn on the breakpoints and events interception after finishing the commands in the remote computer - // - g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer = FALSE; - - TestQueryPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; - - break; - - default: - - // - // Query index not found - // - TestQueryPacket->KernelStatus = DEBUGGER_ERROR_UNKNOWN_TEST_QUERY_RECEIVED; - - break; - } + KdPerformTheTestPacketOperation(DbgState, TestQueryPacket); // // Send the result of query system state to the debuggee diff --git a/hyperdbg/hprdbgkd/code/driver/Ioctl.c b/hyperdbg/hprdbgkd/code/driver/Ioctl.c index 8ef3b648..141f306d 100644 --- a/hyperdbg/hprdbgkd/code/driver/Ioctl.c +++ b/hyperdbg/hprdbgkd/code/driver/Ioctl.c @@ -310,11 +310,12 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) // // Both usermode and to send to usermode and the comming buffer are - // at the same place + // at the same place (not comming from the VMX-root mode) // - DebuggerParseEventFromUsermode(DebuggerNewEventRequest, - InBuffLength, - (PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER)Irp->AssociatedIrp.SystemBuffer); + DebuggerParseEvent(DebuggerNewEventRequest, + InBuffLength, + (PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER)Irp->AssociatedIrp.SystemBuffer, + FALSE); Irp->IoStatus.Information = sizeof(DEBUGGER_EVENT_AND_ACTION_REG_BUFFER); Status = STATUS_SUCCESS; diff --git a/hyperdbg/hprdbgkd/header/common/Common.h b/hyperdbg/hprdbgkd/header/common/Common.h index fc63b188..3a7325c9 100644 --- a/hyperdbg/hprdbgkd/header/common/Common.h +++ b/hyperdbg/hprdbgkd/header/common/Common.h @@ -98,3 +98,6 @@ CommonGetProcessNameFromProcessControlBlock(PEPROCESS Eprocess); BOOLEAN CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod); + +BOOLEAN +CommonValidateCoreNumber(UINT32 CoreNumber); diff --git a/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h b/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h index 2bf6db4b..8ca8ba97 100644 --- a/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h +++ b/hyperdbg/hprdbgkd/header/debugger/core/Debugger.h @@ -220,10 +220,13 @@ BOOLEAN DebuggerQueryDebuggerStatus(); BOOLEAN -DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode); +DebuggerParseEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, + UINT32 BufferLength, + PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn, + BOOLEAN InputFromVmxRoot); BOOLEAN -DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturnUsermode); +DebuggerParseActionFromUsermode(PDEBUGGER_GENERAL_ACTION Action, UINT32 BufferLength, PDEBUGGER_EVENT_AND_ACTION_REG_BUFFER ResultsToReturn); BOOLEAN DebuggerParseEventsModificationFromUsermode(PDEBUGGER_MODIFY_EVENTS DebuggerEventModificationRequest); diff --git a/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h b/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h index 95543245..5f9c059a 100644 --- a/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h +++ b/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h @@ -20,6 +20,12 @@ HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 TargetTask); VOID -HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, - UINT32 TargetTask, - BOOLEAN LockAgainAfterTask); +HaltedCoreRunTaskOnSingleCore(UINT32 TargetCoreId, + UINT32 TargetTask, + BOOLEAN LockAgainAfterTask); + +BOOLEAN +HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, + UINT32 TargetTask, + BOOLEAN LockAgainAfterTask, + BOOLEAN Synchronize); diff --git a/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h b/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h index f8ec6def..d8b399d6 100644 --- a/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h +++ b/hyperdbg/hprdbgkd/header/debugger/kernel-level/Kd.h @@ -230,6 +230,9 @@ KdHandleNmiBroadcastDebugBreaks(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler); VOID KdUnlockTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState); +BOOLEAN +KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState); + BOOLEAN KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32 CoreId, DEBUGGER_THREAD_PROCESS_TRACING TracingType); diff --git a/hyperdbg/include/SDK/Headers/ErrorCodes.h b/hyperdbg/include/SDK/Headers/ErrorCodes.h index 20a6b4b7..410b5744 100644 --- a/hyperdbg/include/SDK/Headers/ErrorCodes.h +++ b/hyperdbg/include/SDK/Headers/ErrorCodes.h @@ -422,6 +422,12 @@ */ #define DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID 0xc000003f +/** + * @brief error, the process id cannot be specified while the debugger is in VMX-root mode + * + */ +#define DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE 0xc0000040 + // // WHEN YOU ADD ANYTHING TO THIS LIST OF ERRORS, THEN // MAKE SURE TO ADD AN ERROR MESSAGE TO ShowErrorMessage(UINT32 Error) diff --git a/hyperdbg/include/SDK/Headers/RequestStructures.h b/hyperdbg/include/SDK/Headers/RequestStructures.h index 0ec19f0c..15710eac 100644 --- a/hyperdbg/include/SDK/Headers/RequestStructures.h +++ b/hyperdbg/include/SDK/Headers/RequestStructures.h @@ -266,14 +266,16 @@ typedef struct _DEBUGGER_FLUSH_LOGGING_BUFFERS */ typedef enum _DEBUGGER_TEST_QUERY_STATE { - TEST_QUERY_HALTING_CORE_STATUS = 1, // Query constant to show detail of halting of core - TEST_QUERY_PREALLOCATED_POOL_STATE = 2, // Query pre-allocated pool state - TEST_QUERY_TRAP_STATE = 3, // Query trap state - TEST_BREAKPOINT_TURN_OFF_BPS = 4, // Turn off the breakpoints - TEST_BREAKPOINT_TURN_ON_BPS = 5, // Turn on the breakpoints - TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 6, // Turn off the breakpoints and events for executing the commands in the remote computer - TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 7, // Turn on the breakpoints and events for executing the commands in the remote computer - TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES = 8, // For test purposes + TEST_QUERY_HALTING_CORE_STATUS = 1, // Query constant to show detail of halting of core + TEST_QUERY_PREALLOCATED_POOL_STATE = 2, // Query pre-allocated pool state + TEST_QUERY_TRAP_STATE = 3, // Query trap state + TEST_BREAKPOINT_TURN_OFF_BPS = 4, // Turn off the breakpoints + TEST_BREAKPOINT_TURN_ON_BPS = 5, // Turn on the breakpoints + TEST_BREAKPOINT_TURN_OFF_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 6, // Turn off the breakpoints and events for executing the commands in the remote computer + TEST_BREAKPOINT_TURN_ON_BPS_AND_EVENTS_FOR_COMMANDS_IN_REMOTE_COMPUTER = 7, // Turn on the breakpoints and events for executing the commands in the remote computer + TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS = 8, // For testing synchronized event + TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_ASYNCHRONOUS = 9, // For testing unsynchronized event + TEST_SETTING_TARGET_TASKS_ON_TARGET_HALTED_CORES = 10, // Send the task to the halted core } DEBUGGER_TEST_QUERY_STATE; @@ -284,6 +286,7 @@ typedef enum _DEBUGGER_TEST_QUERY_STATE typedef struct _DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER { DEBUGGER_TEST_QUERY_STATE RequestType; + UINT64 Context; UINT32 KernelStatus; } DEBUGGER_DEBUGGER_TEST_QUERY_BUFFER, *PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER; diff --git a/hyperdbg/include/components/spinlock/code/Spinlock.c b/hyperdbg/include/components/spinlock/code/Spinlock.c index 66564f0c..53c47c8b 100644 --- a/hyperdbg/include/components/spinlock/code/Spinlock.c +++ b/hyperdbg/include/components/spinlock/code/Spinlock.c @@ -159,3 +159,21 @@ SpinlockUnlock(volatile LONG * Lock) { *Lock = 0; } + +/** + * @brief Check the lock without changing the state + * + * @param LONG Lock variable + */ +BOOLEAN +SpinlockCheckLock(volatile LONG * Lock) +{ + if (*Lock) + { + return TRUE; + } + else + { + return FALSE; + } +} diff --git a/hyperdbg/include/components/spinlock/header/Spinlock.h b/hyperdbg/include/components/spinlock/header/Spinlock.h index 5dc4e016..e12369c3 100644 --- a/hyperdbg/include/components/spinlock/header/Spinlock.h +++ b/hyperdbg/include/components/spinlock/header/Spinlock.h @@ -18,6 +18,9 @@ BOOLEAN SpinlockTryLock(volatile LONG * Lock); +BOOLEAN +SpinlockCheckLock(volatile LONG * Lock); + void SpinlockLock(volatile LONG * Lock);