From 98a87fe63df132e045a0e938bfd4edc2e27a58c2 Mon Sep 17 00:00:00 2001 From: Sinaei Date: Tue, 10 Oct 2023 21:46:05 +0900 Subject: [PATCH] add the synchronization implementation of vmx-root broadcast --- .../commands/debugging-commands/test.cpp | 18 +- .../code/debugger/core/debugger.cpp | 7 + .../hprdbgkd/code/debugger/core/Debugger.c | 266 +++++++++++++----- .../hprdbgkd/code/debugger/core/HaltedCore.c | 60 +++- .../hprdbgkd/code/debugger/kernel-level/Kd.c | 239 +++++++++------- hyperdbg/hprdbgkd/code/driver/Ioctl.c | 9 +- .../hprdbgkd/header/debugger/core/Debugger.h | 7 +- .../header/debugger/core/HaltedCore.h | 9 +- .../header/debugger/kernel-level/Kd.h | 3 + hyperdbg/include/SDK/Headers/ErrorCodes.h | 6 + .../include/SDK/Headers/RequestStructures.h | 3 +- .../components/spinlock/code/Spinlock.c | 18 ++ .../components/spinlock/header/Spinlock.h | 3 + 13 files changed, 450 insertions(+), 198 deletions(-) diff --git a/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp b/hyperdbg/hprdbgctrl/code/debugger/commands/debugging-commands/test.cpp index 758862f4..db0b7c23 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,7 @@ 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); } /** @@ -417,12 +418,19 @@ 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("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/hprdbgkd/code/debugger/core/Debugger.c b/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c index f0c586ec..f676be67 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c +++ b/hyperdbg/hprdbgkd/code/debugger/core/Debugger.c @@ -2105,34 +2105,29 @@ 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 + * @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 -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; + UINT32 ProcessorCount; + UINT32 TempPid; ProcessorCount = KeQueryActiveProcessorCount(0); - // - // ---------------------------------------------------------------------------------- - // *** Validating the Event's parameters *** - // ---------------------------------------------------------------------------------- - // - // // Check whether the event mode (calling stage) to see whether // short-cicuiting event is used along with the post-event, @@ -2143,8 +2138,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; } @@ -2163,8 +2158,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // 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 +2171,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 +2200,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 +2216,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 +2233,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 +2244,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,31 +2311,112 @@ 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; } } + // + // As we reached, all the checks are passed and it means the event is valid + // + return TRUE; +} + +/** + * @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; + UINT64 PagesBytes; + BOOLEAN ResultOfApplyingEvent = FALSE; + // // ---------------------------------------------------------------------------------- - // Create Event + // *** Validating the Event's parameters *** + // ---------------------------------------------------------------------------------- + // + + // + // Validate the event parameters + // + if (!DebuggerValidateEvent(EventDetails, BufferLength, ResultsToReturn, InputFromVmxRoot)) + { + // + // Input event is not valid + // + return FALSE; + } + + // + // ---------------------------------------------------------------------------------- + // *** Create Event *** // ---------------------------------------------------------------------------------- // @@ -2347,8 +2463,8 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // Set the error // - ResultsToReturnUsermode->IsSuccessful = FALSE; - ResultsToReturnUsermode->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT; + ResultsToReturn->IsSuccessful = FALSE; + ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT; return FALSE; } @@ -2359,7 +2475,7 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT // // ---------------------------------------------------------------------------------- - // Apply & Enable Event + // *** Apply & Enable Event *** // ---------------------------------------------------------------------------------- // @@ -2447,8 +2563,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 +2616,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 +2644,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 +2677,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 +3127,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 +3162,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 @@ -3075,13 +3191,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 +3209,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 +3228,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 +3266,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 +3308,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 +3317,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..8b138457 100644 --- a/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c +++ b/hyperdbg/hprdbgkd/code/debugger/core/HaltedCore.c @@ -38,18 +38,31 @@ HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState, * @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 VOID + * @return BOOLEAN */ -VOID -HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, - UINT32 TargetTask, - BOOLEAN LockAgainAfterTask) +BOOLEAN +HaltedCoreBroadcastTaskToAllCores(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 // @@ -77,4 +90,41 @@ HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, // Perform the task for the current core // HaltedCorePerformTargetTask(DbgState, TargetTask); + + // + // If synchronization is expected, we need to check to make sure + // all cores are synchronized (locked) at this point or not + // + 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..f18daa68 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,126 @@ 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) + // + HaltedCoreBroadcastTaskToAllCores(DbgState, + 0x55, + TRUE, + TestQueryPacket->RequestType == TEST_SETTING_TARGET_TASKS_ON_HALTED_CORES_SYNCHRONOUS ? TRUE : FALSE); + + 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 +2301,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/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..b1d21397 100644 --- a/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h +++ b/hyperdbg/hprdbgkd/header/debugger/core/HaltedCore.h @@ -19,7 +19,8 @@ VOID HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE * DbgState, UINT32 TargetTask); -VOID -HaltedCoreBroadcasTaskToAllCores(PROCESSOR_DEBUGGING_STATE * DbgState, - UINT32 TargetTask, - BOOLEAN LockAgainAfterTask); +BOOLEAN +HaltedCoreBroadcastTaskToAllCores(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..64520c86 100644 --- a/hyperdbg/include/SDK/Headers/RequestStructures.h +++ b/hyperdbg/include/SDK/Headers/RequestStructures.h @@ -273,7 +273,8 @@ typedef enum _DEBUGGER_TEST_QUERY_STATE 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_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 } DEBUGGER_TEST_QUERY_STATE; 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);