HyperDbg/hyperdbg/hyperkd/code/debugger/core/Debugger.c

3874 lines
111 KiB
C
Raw Permalink Normal View History

/**
* @file Debugger.c
2022-01-18 22:38:56 +03:30
* @author Sina Karvandi (sina@hyperdbg.org)
2020-05-12 13:12:21 -07:00
* @brief Implementation of Debugger functions
* @details
2022-06-28 09:52:24 -07:00
*
* @version 0.1
* @date 2020-04-13
2022-06-28 09:52:24 -07:00
*
* @copyright This project is released under the GNU Public License v3.
2022-06-28 09:52:24 -07:00
*
*/
#include "pch.h"
2020-10-25 10:09:52 -07:00
2021-03-11 16:27:30 +03:30
/**
* @brief A wrapper for GetRegValue() in script-engine
2022-06-28 09:52:24 -07:00
*
2021-03-11 16:27:30 +03:30
* @return BOOLEAN Value of register
*/
UINT64
DebuggerGetRegValueWrapper(PGUEST_REGS GuestRegs, UINT32 /* REGS_ENUM */ RegId)
{
return GetRegValue(GuestRegs, RegId);
}
/**
* @brief Debugger get the last error
2022-06-28 09:52:24 -07:00
*
* @return UINT32 Error value
*/
UINT32
DebuggerGetLastError()
{
return g_LastError;
}
/**
* @brief Debugger set the last error
* @param LastError The value of last error
2022-06-28 09:52:24 -07:00
*
* @return VOID
*/
2023-03-22 17:45:52 +09:00
VOID
DebuggerSetLastError(UINT32 LastError)
{
g_LastError = LastError;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Initialize script engine global variables and per-core stack buffers
2022-06-28 09:52:24 -07:00
*
* @return BOOLEAN Shows whether the initialization process was successful
2020-08-28 04:03:12 -07:00
* or not
*/
BOOLEAN
DebuggerInitializeScriptEngine()
{
2024-03-03 16:27:16 +09:00
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
2023-03-22 17:45:52 +09:00
PROCESSOR_DEBUGGING_STATE * CurrentDebuggerState = NULL;
2023-01-15 06:58:56 +09:00
//
// Initialize script engines global variables holder
2023-01-15 06:58:56 +09:00
//
if (!g_ScriptGlobalVariables)
2023-03-22 17:45:52 +09:00
{
g_ScriptGlobalVariables = PlatformMemAllocateNonPagedPool(MAX_VAR_COUNT * sizeof(UINT64));
2023-01-15 06:58:56 +09:00
}
if (!g_ScriptGlobalVariables)
2023-03-22 17:45:52 +09:00
{
//
// Out of resource, initialization of script engine's global variable holders failed
//
return FALSE;
}
//
// Zero the global variables memory
//
RtlZeroMemory(g_ScriptGlobalVariables, MAX_VAR_COUNT * sizeof(UINT64));
//
// Initialize the local and temp variables
//
for (SIZE_T i = 0; i < ProcessorsCount; i++)
2023-03-22 17:45:52 +09:00
{
CurrentDebuggerState = &g_DbgState[i];
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
{
CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer = PlatformMemAllocateNonPagedPool(MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
}
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
{
//
// Out of resource, initialization of script engine's stack buffer holders failed
//
return FALSE;
}
//
// Zero stack buffer memory
//
RtlZeroMemory(CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
}
return TRUE;
}
/**
* @brief Initialize trap flag state and breakpoint related structures
*
* @return BOOLEAN Shows whether the initialization process was successful
* or not
*/
BOOLEAN
DebuggerInitializeTrapsAndBreakpoints()
{
//
// Zero the TRAP FLAG state memory
//
RtlZeroMemory(&g_TrapFlagState, sizeof(DEBUGGER_TRAP_FLAG_STATE));
//
// Request pages for breakpoint detail
//
PoolManagerRequestAllocation(sizeof(DEBUGGEE_BP_DESCRIPTOR),
MAXIMUM_BREAKPOINTS_WITHOUT_CONTINUE,
BREAKPOINT_DEFINITION_STRUCTURE);
//
// Initialize list of breakpoints and breakpoint id
//
g_MaximumBreakpointId = 0;
InitializeListHead(&g_BreakpointsListHead);
return TRUE;
}
/**
2026-06-04 00:55:05 +02:00
* @brief Initialize VMM operations (events and related operations)
*
* @return BOOLEAN Shows whether the initialization process was successful
* or not
*/
BOOLEAN
2026-06-04 00:55:05 +02:00
DebuggerInitializeVmmOperations()
{
//
// Initialize lists relating to the debugger events store
//
2020-06-22 16:26:44 -07:00
InitializeListHead(&g_Events->EptHookExecCcEventsHead);
2023-07-07 01:21:07 +09:00
InitializeListHead(&g_Events->HiddenHookReadAndWriteAndExecuteEventsHead);
2020-06-22 16:26:44 -07:00
InitializeListHead(&g_Events->HiddenHookReadAndWriteEventsHead);
2023-07-07 01:21:07 +09:00
InitializeListHead(&g_Events->HiddenHookReadAndExecuteEventsHead);
InitializeListHead(&g_Events->HiddenHookWriteAndExecuteEventsHead);
2020-06-22 16:26:44 -07:00
InitializeListHead(&g_Events->HiddenHookReadEventsHead);
InitializeListHead(&g_Events->HiddenHookWriteEventsHead);
2023-07-07 01:21:07 +09:00
InitializeListHead(&g_Events->HiddenHookExecuteEventsHead);
2020-06-22 13:59:21 -07:00
InitializeListHead(&g_Events->EptHook2sExecDetourEventsHead);
InitializeListHead(&g_Events->SyscallHooksEferSyscallEventsHead);
InitializeListHead(&g_Events->SyscallHooksEferSysretEventsHead);
2020-05-30 07:20:06 -07:00
InitializeListHead(&g_Events->CpuidInstructionExecutionEventsHead);
InitializeListHead(&g_Events->RdmsrInstructionExecutionEventsHead);
InitializeListHead(&g_Events->WrmsrInstructionExecutionEventsHead);
InitializeListHead(&g_Events->ExceptionOccurredEventsHead);
2020-06-02 11:41:37 -07:00
InitializeListHead(&g_Events->TscInstructionExecutionEventsHead);
2020-06-02 15:17:03 -07:00
InitializeListHead(&g_Events->PmcInstructionExecutionEventsHead);
InitializeListHead(&g_Events->InInstructionExecutionEventsHead);
InitializeListHead(&g_Events->OutInstructionExecutionEventsHead);
InitializeListHead(&g_Events->DebugRegistersAccessedEventsHead);
InitializeListHead(&g_Events->ExternalInterruptOccurredEventsHead);
2020-07-03 04:50:48 -07:00
InitializeListHead(&g_Events->VmcallInstructionExecutionEventsHead);
InitializeListHead(&g_Events->TrapExecutionModeChangedEventsHead);
InitializeListHead(&g_Events->TrapExecutionInstructionTraceEventsHead);
InitializeListHead(&g_Events->ControlRegister3ModifiedEventsHead);
InitializeListHead(&g_Events->ControlRegisterModifiedEventsHead);
2025-08-21 00:17:26 +02:00
InitializeListHead(&g_Events->XsetbvInstructionExecutionEventsHead);
2020-04-19 11:53:03 -07:00
2020-04-15 14:11:54 -07:00
//
// Initialize NMI broadcasting mechanism
2020-04-15 14:11:54 -07:00
//
VmFuncVmxBroadcastInitialize();
2020-04-15 14:11:54 -07:00
2020-08-28 04:03:12 -07:00
//
// Set initial state of triggering events for VMCALLs
//
2023-01-19 21:34:45 +09:00
VmFuncSetTriggerEventForVmcalls(FALSE);
2020-08-28 04:03:12 -07:00
//
// Set initial state of triggering events for CPUIDs
2020-08-28 04:03:12 -07:00
//
2023-01-19 21:34:45 +09:00
VmFuncSetTriggerEventForCpuids(FALSE);
2020-08-28 04:03:12 -07:00
//
// Pre-allocate pools for possible EPT hooks
//
ConfigureEptHookReservePreallocatedPoolsForEptHooks(MAXIMUM_NUMBER_OF_INITIAL_PREALLOCATED_EPT_HOOKS);
if (!PoolManagerCheckAndPerformAllocationAndDeallocation())
{
LogWarning("Warning, cannot allocate the pre-allocated pools for EPT hooks");
//
// BTW, won't fail the starting phase because of this
//
}
//
// Enabled Debugger VMX Events
//
g_EnableDebuggerVmxEvents = TRUE;
return TRUE;
}
2026-06-04 00:55:05 +02:00
/**
* @brief Initialize Debugger Structures and Routines
*
* @return BOOLEAN Shows whether the initialization process was successful
* or not
*/
BOOLEAN
DebuggerInitialize()
{
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
//
// Also allocate the debugging state
//
if (!GlobalDebuggingStateAllocateZeroedMemory())
{
return FALSE;
}
2023-07-21 21:51:56 +09:00
//
// Allocate buffer for saving events
2023-07-21 21:51:56 +09:00
//
if (GlobalEventsAllocateZeroedMemory() == FALSE)
2023-03-22 17:45:52 +09:00
{
return FALSE;
}
2023-07-21 21:51:56 +09:00
//
// Set the core's IDs
//
for (UINT32 i = 0; i < ProcessorsCount; i++)
2023-03-22 17:45:52 +09:00
{
g_DbgState[i].CoreId = i;
}
//
// Initialize Pool Manager
//
if (!PoolManagerInitialize())
{
LogError("Err, could not initialize pool manager");
return FALSE;
}
//
// Initialize script engine global variables and per-core stack buffers
//
if (!DebuggerInitializeScriptEngine())
{
return FALSE;
}
2022-04-24 20:57:08 +04:30
//
// Initialize trap flag state and breakpoint related structures
2022-04-24 20:57:08 +04:30
//
if (!DebuggerInitializeTrapsAndBreakpoints())
2023-03-22 17:45:52 +09:00
{
2022-02-15 23:37:49 +03:30
return FALSE;
}
2022-04-24 20:57:08 +04:30
2022-02-15 23:37:49 +03:30
//
// Initialize attaching mechanism,
// we'll use the functionalities of the attaching in reading modules
// of user mode applications (other than attaching mechanism itself)
//
2023-03-22 17:45:52 +09:00
if (!AttachingInitialize())
{
2022-02-15 23:37:49 +03:30
return FALSE;
}
return TRUE;
}
2020-09-05 08:09:04 -07:00
/**
2026-06-04 00:55:05 +02:00
* @brief Uninitialize Debugger VMM Operations (Events and other related operations)
2022-06-28 09:52:24 -07:00
*
2026-06-04 00:55:05 +02:00
* @return VOID
2020-09-05 08:09:04 -07:00
*/
2023-03-22 17:45:52 +09:00
VOID
2026-06-04 00:55:05 +02:00
DebuggerUninitializeVmmOperations()
2020-09-05 08:09:04 -07:00
{
//
// *** Disable, terminate and clear all the events ***
//
//
// Because we want to delete all the objects and buffers (pools)
// after we finished termination, the debugger might still use
// the buffers for events and action, for solving this problem
// we first disable the tag(s) and this way the debugger no longer
// use that event and this way we can safely remove and deallocate
// the buffers later after termination
//
2023-07-06 16:12:28 +09:00
//
// Disable triggering events
//
g_EnableDebuggerVmxEvents = FALSE;
2023-07-06 16:12:28 +09:00
2020-09-05 08:09:04 -07:00
//
2023-10-22 01:14:36 +09:00
// Clear all events (Check if the kernel debugger is enable
// and whether the instant event mechanism is working or not)
2020-09-05 08:09:04 -07:00
//
2023-10-22 01:14:36 +09:00
if (g_KernelDebuggerState && EnableInstantEventMechanism)
{
DebuggerClearAllEvents(FALSE, TRUE);
2023-10-22 01:14:36 +09:00
}
else
{
DebuggerClearAllEvents(FALSE, FALSE);
2023-10-22 01:14:36 +09:00
}
//
// Uninitialize kernel debugger
//
KdUninitializeKernelDebugger();
//
// Uninitialize user debugger
//
UdUninitializeUserDebugger();
2022-04-24 20:57:08 +04:30
//
// Uninitialize NMI broadcasting mechanism
2022-04-24 20:57:08 +04:30
//
VmFuncVmxBroadcastUninitialize();
2026-06-04 00:55:05 +02:00
}
/**
* @brief Uninitialize Debugger Structures and Routines
*
* @return VOID
*/
VOID
DebuggerUninitialize()
{
ULONG ProcessorsCount;
PROCESSOR_DEBUGGING_STATE * CurrentDebuggerState = NULL;
ProcessorsCount = KeQueryActiveProcessorCount(0);
//
// Free the Pool manager
//
PoolManagerUninitialize();
//
// Free g_Events
//
GlobalEventsFreeMemory();
//
// Free g_ScriptGlobalVariables
//
2023-03-22 17:45:52 +09:00
if (g_ScriptGlobalVariables != NULL)
{
PlatformMemFreePool(g_ScriptGlobalVariables);
2023-07-06 16:12:28 +09:00
g_ScriptGlobalVariables = NULL;
}
//
// Free core specific local and temp variables
//
2024-03-03 16:27:16 +09:00
for (SIZE_T i = 0; i < ProcessorsCount; i++)
2023-03-22 17:45:52 +09:00
{
CurrentDebuggerState = &g_DbgState[i];
2024-06-15 02:10:03 +08:00
if (CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer != NULL)
{
PlatformMemFreePool(CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer);
CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer = NULL;
}
}
//
// Free g_DbgState
//
GlobalDebuggingStateFreeMemory();
2020-09-05 08:09:04 -07:00
}
2020-08-28 04:03:12 -07:00
/**
* @brief Create an Event Object
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @details should NOT be called in vmx-root
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Enabled Is the event enabled or disabled
* @param CoreId The core id that this event is allowed to run
* @param ProcessId The process id that this event is allowed to run
* @param EventType The type of event
* @param Tag User-mode generated unique tag (id) of the event
* @param Options Optional parameters for the event
2020-08-28 04:03:12 -07:00
* @param ConditionsBufferSize Size of condition code buffer (if any)
* @param ConditionBuffer Address of condition code buffer (if any)
* @param ResultsToReturn Result buffer that should be returned to
* the user-mode
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2020-08-28 04:03:12 -07:00
* @return PDEBUGGER_EVENT Returns null in the case of error and event
* object address when it's successful
*/
PDEBUGGER_EVENT
DebuggerCreateEvent(BOOLEAN Enabled,
UINT32 CoreId,
UINT32 ProcessId,
VMM_EVENT_TYPE_ENUM EventType,
UINT64 Tag,
DEBUGGER_EVENT_OPTIONS * Options,
UINT32 ConditionsBufferSize,
PVOID ConditionBuffer,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
PDEBUGGER_EVENT Event = NULL;
UINT32 EventBufferSize = sizeof(DEBUGGER_EVENT) + ConditionsBufferSize;
//
// Initialize the event structure
//
if (InputFromVmxRoot)
{
//
// *** The buffer is coming from VMX-root mode ***
//
//
2023-10-17 18:20:21 +09:00
// If the buffer is smaller than regular instant events
//
if (REGULAR_INSTANT_EVENT_CONDITIONAL_BUFFER >= EventBufferSize)
{
//
// The buffer fits into a regular instant event
//
2024-03-01 15:59:58 +09:00
Event = (DEBUGGER_EVENT *)PoolManagerRequestPool(INSTANT_REGULAR_EVENT_BUFFER, TRUE, REGULAR_INSTANT_EVENT_CONDITIONAL_BUFFER);
if (!Event)
{
//
// Here we try again to see if we could store it into a big instant event instead
//
2024-03-01 15:59:58 +09:00
Event = (DEBUGGER_EVENT *)PoolManagerRequestPool(INSTANT_BIG_EVENT_BUFFER, TRUE, BIG_INSTANT_EVENT_CONDITIONAL_BUFFER);
if (!Event)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_REGULAR_PREALLOCATED_BUFFER_NOT_FOUND;
//
// There is a problem with allocating event
//
return NULL;
}
}
}
else if (BIG_INSTANT_EVENT_CONDITIONAL_BUFFER >= EventBufferSize)
{
//
// The buffer fits into a big instant event
//
2024-03-01 15:59:58 +09:00
Event = (DEBUGGER_EVENT *)PoolManagerRequestPool(INSTANT_BIG_EVENT_BUFFER, TRUE, BIG_INSTANT_EVENT_CONDITIONAL_BUFFER);
if (!Event)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_BIG_PREALLOCATED_BUFFER_NOT_FOUND;
//
// There is a problem with allocating event
//
return NULL;
}
}
else
{
//
// The buffer doesn't fit into any of the regular or big event's preallocated buffers
//
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
2024-03-17 18:17:38 +09:00
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_PREALLOCATED_BUFFER_IS_NOT_ENOUGH_FOR_EVENT_AND_CONDITIONALS;
return NULL;
}
}
else
2023-03-22 17:45:52 +09:00
{
//
// If it's not coming from the VMX-root mode then we're allocating it from the OS buffers
//
Event = PlatformMemAllocateZeroedNonPagedPool(EventBufferSize);
if (!Event)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_EVENT;
//
// There is a problem with allocating event
//
return NULL;
}
}
2023-03-22 17:45:52 +09:00
Event->CoreId = CoreId;
Event->ProcessId = ProcessId;
Event->Enabled = Enabled;
Event->EventType = EventType;
Event->Tag = Tag;
Event->CountOfActions = 0; // currently there is no action
2023-10-14 21:28:08 +09:00
//
// Copy Options
//
memcpy(&Event->InitOptions, Options, sizeof(DEBUGGER_EVENT_OPTIONS));
//
// check if this event is conditional or not
//
2023-03-22 17:45:52 +09:00
if (ConditionBuffer != 0)
{
//
2024-03-17 18:17:38 +09:00
// It's conditional
//
2023-03-22 17:45:52 +09:00
Event->ConditionsBufferSize = ConditionsBufferSize;
2024-03-01 15:59:58 +09:00
Event->ConditionBufferAddress = (PVOID)((UINT64)Event + sizeof(DEBUGGER_EVENT));
//
2024-03-17 18:17:38 +09:00
// copy the condition buffer to the end of the buffer of the event
//
memcpy(Event->ConditionBufferAddress, ConditionBuffer, ConditionsBufferSize);
2023-03-22 17:45:52 +09:00
}
else
{
//
// It's unconditioanl
//
Event->ConditionsBufferSize = 0;
}
2020-04-15 12:37:24 -07:00
//
// Make the action lists ready
//
InitializeListHead(&Event->ActionsListHead);
//
// Return our event
//
return Event;
}
/**
* @brief Allocates buffer for requested safe buffer
*
* @param SizeOfRequestedSafeBuffer The size of the requested safe buffer
* @param ResultsToReturn The buffer address that should be returned
* to the user-mode as the result
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
* @return PVOID
*/
PVOID
DebuggerAllocateSafeRequestedBuffer(SIZE_T SizeOfRequestedSafeBuffer,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
PVOID RequestedBuffer = NULL;
//
// Check whether the buffer comes from VMX-root mode or non-root mode
//
if (InputFromVmxRoot)
{
//
// *** The buffer is coming from VMX-root mode ***
//
//
// If the requested safe buffer is smaller than regular safe buffers
//
if (REGULAR_INSTANT_EVENT_REQUESTED_SAFE_BUFFER >= SizeOfRequestedSafeBuffer)
{
//
// The buffer fits into a regular safe requested buffer
//
2024-03-01 15:59:58 +09:00
RequestedBuffer = (PVOID)PoolManagerRequestPool(INSTANT_REGULAR_SAFE_BUFFER_FOR_EVENTS, TRUE, REGULAR_INSTANT_EVENT_REQUESTED_SAFE_BUFFER);
if (!RequestedBuffer)
{
//
// Here we try again to see if we could store it into a big instant event safe requested buffer instead
//
2024-03-01 15:59:58 +09:00
RequestedBuffer = (PVOID)PoolManagerRequestPool(INSTANT_BIG_SAFE_BUFFER_FOR_EVENTS, TRUE, BIG_INSTANT_EVENT_REQUESTED_SAFE_BUFFER);
if (!RequestedBuffer)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_REGULAR_REQUESTED_SAFE_BUFFER_NOT_FOUND;
//
// There is a problem with allocating requested safe buffer
//
return NULL;
}
}
}
else if (BIG_INSTANT_EVENT_REQUESTED_SAFE_BUFFER >= SizeOfRequestedSafeBuffer)
{
//
// The buffer fits into a big instant requested safe buffer
//
2024-03-01 15:59:58 +09:00
RequestedBuffer = (PVOID)PoolManagerRequestPool(INSTANT_BIG_SAFE_BUFFER_FOR_EVENTS, TRUE, BIG_INSTANT_EVENT_REQUESTED_SAFE_BUFFER);
if (!RequestedBuffer)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_BIG_REQUESTED_SAFE_BUFFER_NOT_FOUND;
//
// There is a problem with allocating event
//
return NULL;
}
}
else
{
//
// The buffer doesn't fit into any of the regular or big safe requested buffers
//
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_PREALLOCATED_BUFFER_IS_NOT_ENOUGH_FOR_REQUESTED_SAFE_BUFFER;
return NULL;
}
}
else
{
RequestedBuffer = PlatformMemAllocateZeroedNonPagedPool(SizeOfRequestedSafeBuffer);
if (!RequestedBuffer)
{
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_ALLOCATE_REQUESTED_SAFE_BUFFER;
return NULL;
}
}
return RequestedBuffer;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Create an action and add the action to an event
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Event Target event object
* @param ActionType Type of action
* @param SendTheResultsImmediately whether the results should be received
* by the user-mode immediately
* @param InTheCaseOfCustomCode Custom code structure (if any)
2020-10-08 01:16:51 -07:00
* @param InTheCaseOfRunScript Run script structure (if any)
2023-10-17 18:20:21 +09:00
* @param ResultsToReturn The buffer address that should be returned
* to the user-mode as the result
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2022-06-28 09:52:24 -07:00
* @return PDEBUGGER_EVENT_ACTION
2020-08-28 04:03:12 -07:00
*/
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT_ACTION
2023-03-22 17:45:52 +09:00
DebuggerAddActionToEvent(PDEBUGGER_EVENT Event,
DEBUGGER_EVENT_ACTION_TYPE_ENUM ActionType,
BOOLEAN SendTheResultsImmediately,
PDEBUGGER_EVENT_REQUEST_CUSTOM_CODE InTheCaseOfCustomCode,
2023-10-17 18:20:21 +09:00
PDEBUGGER_EVENT_ACTION_RUN_SCRIPT_CONFIGURATION InTheCaseOfRunScript,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
2020-04-15 12:37:24 -07:00
PDEBUGGER_EVENT_ACTION Action;
2023-10-17 18:20:21 +09:00
SIZE_T ActionBufferSize;
PVOID RequestedBuffer = NULL;
//
// Allocate action + allocate code for custom code
//
2023-03-22 17:45:52 +09:00
if (InTheCaseOfCustomCode != NULL)
{
//
2020-10-22 08:14:59 -07:00
// We should allocate extra buffer for custom code
//
2023-10-17 18:20:21 +09:00
ActionBufferSize = sizeof(DEBUGGER_EVENT_ACTION) + InTheCaseOfCustomCode->CustomCodeBufferSize;
2023-03-22 17:45:52 +09:00
}
else if (InTheCaseOfRunScript != NULL)
{
2020-10-22 08:14:59 -07:00
//
// We should allocate extra buffer for script
//
2023-10-17 18:20:21 +09:00
ActionBufferSize = sizeof(DEBUGGER_EVENT_ACTION) + InTheCaseOfRunScript->ScriptLength;
2023-03-22 17:45:52 +09:00
}
else
{
2020-04-15 12:37:24 -07:00
//
2020-10-22 08:14:59 -07:00
// We shouldn't allocate extra buffer as there is no custom code
2020-04-15 12:37:24 -07:00
//
2023-10-17 18:20:21 +09:00
ActionBufferSize = sizeof(DEBUGGER_EVENT_ACTION);
2020-08-28 04:03:12 -07:00
}
2023-10-17 18:20:21 +09:00
//
// Allocate buffer for storing the action
//
if (InputFromVmxRoot)
{
//
// *** The buffer is coming from VMX-root mode ***
//
//
// If the buffer is smaller than regular instant events's action
//
if (REGULAR_INSTANT_EVENT_ACTION_BUFFER >= ActionBufferSize)
{
//
// The buffer fits into a regular instant event's action
//
2024-03-01 15:59:58 +09:00
Action = (DEBUGGER_EVENT_ACTION *)PoolManagerRequestPool(INSTANT_REGULAR_EVENT_ACTION_BUFFER, TRUE, REGULAR_INSTANT_EVENT_ACTION_BUFFER);
2023-10-17 18:20:21 +09:00
if (!Action)
{
//
// Here we try again to see if we could store it into a big instant event's action buffer instead
//
2024-03-01 15:59:58 +09:00
Action = (DEBUGGER_EVENT_ACTION *)PoolManagerRequestPool(INSTANT_BIG_EVENT_ACTION_BUFFER, TRUE, BIG_INSTANT_EVENT_ACTION_BUFFER);
2023-10-17 18:20:21 +09:00
if (!Action)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_ACTION_REGULAR_PREALLOCATED_BUFFER_NOT_FOUND;
//
// There is a problem with allocating event's action
//
return NULL;
}
}
}
else if (BIG_INSTANT_EVENT_ACTION_BUFFER >= ActionBufferSize)
{
//
// The buffer fits into a big instant event's action buffer
//
2024-03-01 15:59:58 +09:00
Action = (DEBUGGER_EVENT_ACTION *)PoolManagerRequestPool(INSTANT_BIG_EVENT_ACTION_BUFFER, TRUE, BIG_INSTANT_EVENT_ACTION_BUFFER);
2023-10-17 18:20:21 +09:00
if (!Action)
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_ACTION_BIG_PREALLOCATED_BUFFER_NOT_FOUND;
//
// There is a problem with allocating event's action buffer
//
return NULL;
}
}
else
{
//
// The buffer doesn't fit into any of the regular or big event's action preallocated buffers
//
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_PREALLOCATED_BUFFER_IS_NOT_ENOUGH_FOR_ACTION_BUFFER;
2020-04-15 12:37:24 -07:00
2023-10-17 18:20:21 +09:00
return NULL;
}
}
else
2023-03-22 17:45:52 +09:00
{
2020-08-28 04:03:12 -07:00
//
2023-10-17 18:20:21 +09:00
// If it's not coming from the VMX-root mode then we're allocating it from the OS buffers
2020-08-28 04:03:12 -07:00
//
Action = PlatformMemAllocateZeroedNonPagedPool(ActionBufferSize);
2023-10-17 18:20:21 +09:00
if (Action == NULL)
{
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_UNABLE_TO_CREATE_ACTION_CANNOT_ALLOCATE_BUFFER;
//
// There was an error in allocation
//
return NULL;
}
2020-04-15 12:37:24 -07:00
}
//
// If the user needs a buffer to be passed to the debugger then
// we should allocate it here (Requested buffer is only available for custom code types)
//
2024-03-01 22:27:09 +09:00
if (ActionType == RUN_CUSTOM_CODE &&
InTheCaseOfCustomCode != NULL &&
InTheCaseOfCustomCode->OptionalRequestedBufferSize != 0)
2023-03-22 17:45:52 +09:00
{
//
// Check if the optional buffer is not more that the size
// we can send to usermode
//
2023-03-22 17:45:52 +09:00
if (InTheCaseOfCustomCode->OptionalRequestedBufferSize >= MaximumPacketsCapacity)
{
2020-10-22 08:14:59 -07:00
//
// There was an error
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
}
else
{
PlatformMemFreePool(Action);
}
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_REQUESTED_OPTIONAL_BUFFER_IS_BIGGER_THAN_DEBUGGERS_SEND_RECEIVE_STACK;
2023-10-17 18:20:21 +09:00
2020-05-14 08:28:28 -07:00
return NULL;
}
//
// User needs a buffer to play with
//
RequestedBuffer = DebuggerAllocateSafeRequestedBuffer(InTheCaseOfCustomCode->OptionalRequestedBufferSize, ResultsToReturn, InputFromVmxRoot);
2023-03-22 17:45:52 +09:00
if (!RequestedBuffer)
{
//
// There was an error in allocation
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
}
else
{
PlatformMemFreePool(Action);
}
2023-10-17 18:20:21 +09:00
//
// Not need to set error as the above function already adjust the error
//
2020-05-14 08:28:28 -07:00
return NULL;
}
2021-10-05 21:43:07 +03:30
//
// Add it to the action
//
Action->RequestedBuffer.EnabledRequestBuffer = TRUE;
2023-03-22 17:45:52 +09:00
Action->RequestedBuffer.RequestBufferSize = InTheCaseOfCustomCode->OptionalRequestedBufferSize;
2024-02-29 19:26:14 +09:00
Action->RequestedBuffer.RequstBufferAddress = (UINT64)RequestedBuffer;
}
2020-10-22 08:14:59 -07:00
//
// If the user needs a buffer to be passed to the debugger script then
// we should allocate it here (Requested buffer is only available for custom code types)
//
2024-03-01 23:20:18 +09:00
if (ActionType == RUN_SCRIPT &&
InTheCaseOfRunScript != NULL &&
InTheCaseOfRunScript->OptionalRequestedBufferSize != 0)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// Check if the optional buffer is not more that the size
// we can send to usermode
//
2023-03-22 17:45:52 +09:00
if (InTheCaseOfRunScript->OptionalRequestedBufferSize >= MaximumPacketsCapacity)
{
2020-10-22 08:14:59 -07:00
//
// There was an error
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
}
else
{
PlatformMemFreePool(Action);
}
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INSTANT_EVENT_REQUESTED_OPTIONAL_BUFFER_IS_BIGGER_THAN_DEBUGGERS_SEND_RECEIVE_STACK;
2023-10-17 18:20:21 +09:00
2020-10-22 08:14:59 -07:00
return NULL;
}
//
// User needs a buffer to play with
//
RequestedBuffer = DebuggerAllocateSafeRequestedBuffer(InTheCaseOfRunScript->OptionalRequestedBufferSize, ResultsToReturn, InputFromVmxRoot);
2020-10-22 08:14:59 -07:00
2023-03-22 17:45:52 +09:00
if (!RequestedBuffer)
{
2020-10-22 08:14:59 -07:00
//
// There was an error in allocation
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
}
else
{
PlatformMemFreePool(Action);
}
2023-10-17 18:20:21 +09:00
//
// Not need to set error as the above function already adjust the error
//
2020-10-22 08:14:59 -07:00
return NULL;
}
2021-10-05 21:43:07 +03:30
2020-10-22 08:14:59 -07:00
//
// Add it to the action
//
Action->RequestedBuffer.EnabledRequestBuffer = TRUE;
2023-03-22 17:45:52 +09:00
Action->RequestedBuffer.RequestBufferSize = InTheCaseOfRunScript->OptionalRequestedBufferSize;
2024-02-29 19:26:14 +09:00
Action->RequestedBuffer.RequstBufferAddress = (UINT64)RequestedBuffer;
2020-10-22 08:14:59 -07:00
}
2024-03-01 23:20:18 +09:00
if (ActionType == RUN_CUSTOM_CODE && InTheCaseOfCustomCode != NULL)
2023-03-22 17:45:52 +09:00
{
//
// Check if it's a Custom code without custom code buffer which is invalid
//
2024-03-01 22:27:09 +09:00
if (InTheCaseOfCustomCode != NULL && InTheCaseOfCustomCode->CustomCodeBufferSize == 0)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// There was an error
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
if (RequestedBuffer != NULL)
{
2024-03-01 15:59:58 +09:00
PoolManagerFreePool((UINT64)RequestedBuffer);
}
}
else
{
PlatformMemFreePool(Action);
if (RequestedBuffer != NULL)
{
PlatformMemFreePool(RequestedBuffer);
}
}
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
2020-05-14 08:28:28 -07:00
return NULL;
2020-10-22 08:14:59 -07:00
}
//
// Move the custom code buffer to the end of the action
//
2023-03-22 17:45:52 +09:00
Action->CustomCodeBufferSize = InTheCaseOfCustomCode->CustomCodeBufferSize;
2024-03-01 15:59:58 +09:00
Action->CustomCodeBufferAddress = (PVOID)((UINT64)Action + sizeof(DEBUGGER_EVENT_ACTION));
//
// copy the custom code buffer to the end of the buffer of the action
//
2020-04-15 12:37:24 -07:00
memcpy(Action->CustomCodeBufferAddress, InTheCaseOfCustomCode->CustomCodeBufferAddress, InTheCaseOfCustomCode->CustomCodeBufferSize);
}
//
2020-10-08 01:16:51 -07:00
// If it's run script action type
2020-04-15 12:37:24 -07:00
//
2024-03-01 23:20:18 +09:00
else if (ActionType == RUN_SCRIPT && InTheCaseOfRunScript != NULL)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// Check the buffers of run script
//
2024-03-03 15:15:38 +09:00
if (InTheCaseOfRunScript->ScriptBuffer == NULL64_ZERO || InTheCaseOfRunScript->ScriptLength == NULL_ZERO)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// There was an error
2020-10-22 08:14:59 -07:00
//
if (InputFromVmxRoot)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Action);
if (RequestedBuffer != 0)
{
2024-03-01 15:59:58 +09:00
PoolManagerFreePool((UINT64)RequestedBuffer);
}
}
else
{
PlatformMemFreePool(Action);
if (RequestedBuffer != 0)
{
PlatformMemFreePool(RequestedBuffer);
}
}
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
2023-10-17 18:20:21 +09:00
2020-10-22 08:14:59 -07:00
return NULL;
}
//
// Allocate the buffer from a non-page pool on the script
//
2024-03-01 15:59:58 +09:00
Action->ScriptConfiguration.ScriptBuffer = (UINT64)((BYTE *)Action + sizeof(DEBUGGER_EVENT_ACTION));
2020-10-22 08:14:59 -07:00
//
// Copy the memory of script to our non-paged pool
//
RtlCopyMemory((PVOID)Action->ScriptConfiguration.ScriptBuffer, (const PVOID)InTheCaseOfRunScript->ScriptBuffer, InTheCaseOfRunScript->ScriptLength);
2020-10-22 08:14:59 -07:00
//
// Set other fields
//
2023-03-22 17:45:52 +09:00
Action->ScriptConfiguration.ScriptLength = InTheCaseOfRunScript->ScriptLength;
Action->ScriptConfiguration.ScriptPointer = InTheCaseOfRunScript->ScriptPointer;
2020-10-22 08:14:59 -07:00
Action->ScriptConfiguration.OptionalRequestedBufferSize = InTheCaseOfRunScript->OptionalRequestedBufferSize;
}
//
// Create an order code for the current action
// and also increase the Count of action in event
//
Event->CountOfActions++;
Action->ActionOrderCode = Event->CountOfActions;
//
// Fill other parts of the action
//
Action->ImmediatelySendTheResults = SendTheResultsImmediately;
2023-03-22 17:45:52 +09:00
Action->ActionType = ActionType;
Action->Tag = Event->Tag;
2020-04-15 12:37:24 -07:00
//
// Now we should add the action to the event's LIST_ENTRY of actions
//
InsertHeadList(&Event->ActionsListHead, &(Action->ActionsList));
2020-05-14 08:28:28 -07:00
return Action;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Register an event to a list of active events
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Event Event structure
* @return BOOLEAN TRUE if it successfully registered and FALSE if not registered
*/
BOOLEAN
DebuggerRegisterEvent(PDEBUGGER_EVENT Event)
{
PLIST_ENTRY TargetEventList = NULL;
//
// Register the event
//
TargetEventList = DebuggerGetEventListByEventType(Event->EventType);
2023-03-22 17:45:52 +09:00
if (TargetEventList != NULL)
{
InsertHeadList(TargetEventList, &(Event->EventsOfSameTypeList));
2020-08-28 04:03:12 -07:00
return TRUE;
2023-03-22 17:45:52 +09:00
}
else
{
2020-04-15 17:08:13 -07:00
return FALSE;
}
}
2020-08-28 04:03:12 -07:00
/**
* @brief Trigger events of a special type to be managed by debugger
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param EventType Type of events
* @param CallingStage Stage of calling (pre-event or post-event)
2020-08-28 04:03:12 -07:00
* @param Context An optional parameter (different in each event)
* @param PostEventRequired Whether the caller is requested to
* trigger a post-event event
2022-12-09 14:49:25 +09:00
* @param Regs Guest gp-registers
*
2024-03-17 18:17:38 +09:00
* @return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE returns the status
2022-06-15 12:55:44 +04:30
* of handling events
2020-08-28 04:03:12 -07:00
*/
2023-01-29 04:06:01 +09:00
VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE
2023-03-22 17:45:52 +09:00
DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType,
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE CallingStage,
PVOID Context,
BOOLEAN * PostEventRequired,
GUEST_REGS * Regs)
{
PROCESSOR_DEBUGGING_STATE * DbgState = NULL;
DebuggerCheckForCondition * ConditionFunc;
2024-03-01 18:11:24 +09:00
DEBUGGER_TRIGGERED_EVENT_DETAILS EventTriggerDetail = {0};
PEPT_HOOKS_CONTEXT EptContext;
PLIST_ENTRY TempList = 0;
PLIST_ENTRY TempList2 = 0;
const PVOID OriginalContext = Context;
2022-12-09 14:49:25 +09:00
2020-04-16 10:40:20 -07:00
//
// Check if triggering debugging actions are allowed or not
//
if (!g_EnableDebuggerVmxEvents || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer)
2023-03-22 17:45:52 +09:00
{
2020-04-16 10:40:20 -07:00
//
// Debugger is not enabled
//
2023-01-29 04:06:01 +09:00
return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_DEBUGGER_NOT_ENABLED;
2020-04-16 10:40:20 -07:00
}
2023-01-29 07:12:19 +09:00
//
// Find the debugging state structure
//
DbgState = &g_DbgState[KeGetCurrentProcessorNumberEx(NULL)];
2023-01-29 07:12:19 +09:00
2020-04-15 17:08:13 -07:00
//
// Find the debugger events list base on the type of the event
//
2023-03-22 17:45:52 +09:00
TempList = DebuggerGetEventListByEventType(EventType);
TempList2 = TempList;
2022-06-15 12:55:44 +04:30
2023-03-22 17:45:52 +09:00
if (TempList == NULL)
{
2023-01-29 04:06:01 +09:00
return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_INVALID_EVENT_TYPE;
2020-04-16 06:21:50 -07:00
}
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
2020-04-16 06:21:50 -07:00
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
2020-04-16 06:21:50 -07:00
//
// check if the event is enabled or not
//
2023-03-22 17:45:52 +09:00
if (!CurrentEvent->Enabled)
{
2020-04-16 06:21:50 -07:00
continue;
2020-04-15 17:08:13 -07:00
}
2020-04-16 06:21:50 -07:00
//
// Check if this event is for this core or not
//
2023-03-22 17:45:52 +09:00
if (CurrentEvent->CoreId != DEBUGGER_EVENT_APPLY_TO_ALL_CORES && CurrentEvent->CoreId != DbgState->CoreId)
{
//
// This event is not related to either or core or all cores
//
continue;
}
//
// Check if this event is for this process or not
//
2024-03-01 23:02:03 +09:00
if (CurrentEvent->ProcessId != DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES && CurrentEvent->ProcessId != HANDLE_TO_UINT32(PsGetCurrentProcessId()))
2023-03-22 17:45:52 +09:00
{
//
// This event is not related to either our process or all processes
//
continue;
}
//
// Check event type specific conditions, if the event is not mentioned
// here, it means that it doesn't have any special condition
//
2023-03-22 17:45:52 +09:00
switch (CurrentEvent->EventType)
{
2020-06-13 03:12:44 -07:00
case EXTERNAL_INTERRUPT_OCCURRED:
2020-06-13 03:12:44 -07:00
//
// For external interrupt exiting events we check whether the
// vector match the event's vector or not
//
// Context is the physical address
//
2024-03-01 15:59:58 +09:00
if ((UINT64)Context != CurrentEvent->Options.OptionalParam1)
2023-03-22 17:45:52 +09:00
{
//
// The interrupt is not for this event
//
continue;
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
2020-06-13 03:12:44 -07:00
case HIDDEN_HOOK_READ_AND_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_EXECUTE:
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
2020-06-13 03:12:44 -07:00
case HIDDEN_HOOK_READ:
case HIDDEN_HOOK_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_EXECUTE:
2020-06-13 03:12:44 -07:00
//
2023-07-07 01:21:07 +09:00
// For hidden hook read/write/execute we check whether the address
2020-06-13 03:12:44 -07:00
// is in the range of what user specified or not, this is because
// we get the events for all hidden hooks in a page granularity
//
//
// Here the OriginalContext is used because the context
// might be changed but the OriginalContext is constant
//
EptContext = (PEPT_HOOKS_CONTEXT)OriginalContext;
2020-05-20 11:38:07 -07:00
//
// EPT context should be checked with hooking tag
// The hooking tag is same as the event tag if both
// of them match together
2020-05-20 11:38:07 -07:00
//
if (EptContext->HookingTag != CurrentEvent->Tag)
2023-03-22 17:45:52 +09:00
{
2020-05-20 11:38:07 -07:00
//
2024-03-17 18:17:38 +09:00
// The value is not within our expected range
2020-05-20 11:38:07 -07:00
//
continue;
2023-03-22 17:45:52 +09:00
}
else
{
//
// Fix the context to virtual address
//
2024-03-01 15:59:58 +09:00
Context = (PVOID)EptContext->VirtualAddress;
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
case HIDDEN_HOOK_EXEC_CC:
//
// Here we check if it's HIDDEN_HOOK_EXEC_CC then it means
// so we have to make sure to perform its actions only if
// the hook is triggered for the address described in
// event, note that address in event is a virtual address
//
2024-03-01 15:59:58 +09:00
if ((UINT64)Context != CurrentEvent->Options.OptionalParam1)
2023-03-22 17:45:52 +09:00
{
//
// Context is the virtual address
//
//
// The hook is not for this (virtual) address
//
continue;
}
break;
case HIDDEN_HOOK_EXEC_DETOURS:
//
// Here the OriginalContext is used because the context
// might be changed but the OriginalContext is constant
//
EptContext = (PEPT_HOOKS_CONTEXT)OriginalContext;
2020-06-13 03:12:44 -07:00
//
// Here we check if it's HIDDEN_HOOK_EXEC_DETOURS
// then it means that it's detours hidden hook exec so we have
// to make sure to perform its actions, only if the hook is triggered
// for the address described in event, note that address in event is
// a physical address and the address that the function that triggers
// these events and sent here as the context is also converted to its
// physical form
2020-06-13 03:12:44 -07:00
// This way we are sure that no one can bypass our hook by remapping
// address to another virtual address as everything is physical
//
if (EptContext->PhysicalAddress != CurrentEvent->Options.OptionalParam1)
2023-03-22 17:45:52 +09:00
{
2020-06-13 03:12:44 -07:00
//
// Context is the physical address
//
2020-06-02 07:20:06 -07:00
2020-06-13 03:12:44 -07:00
//
// The hook is not for this (physical) address
//
continue;
2023-03-22 17:45:52 +09:00
}
else
{
//
// Convert it to virtual address
//
Context = (PVOID)(EptContext->VirtualAddress);
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
2020-06-13 03:12:44 -07:00
case RDMSR_INSTRUCTION_EXECUTION:
case WRMSR_INSTRUCTION_EXECUTION:
2020-06-02 07:20:06 -07:00
//
2020-06-13 03:12:44 -07:00
// check if MSR exit is what we want or not
2020-06-02 07:20:06 -07:00
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != DEBUGGER_EVENT_MSR_READ_OR_WRITE_ALL_MSRS && CurrentEvent->Options.OptionalParam1 != (UINT64)Context)
2023-03-22 17:45:52 +09:00
{
//
2020-06-02 07:20:06 -07:00
// The msr is not what we want
//
continue;
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
2020-06-13 03:12:44 -07:00
case EXCEPTION_OCCURRED:
2020-06-13 03:12:44 -07:00
//
// check if exception is what we need or not
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != DEBUGGER_EVENT_EXCEPTIONS_ALL_FIRST_32_ENTRIES && CurrentEvent->Options.OptionalParam1 != (UINT64)Context)
2023-03-22 17:45:52 +09:00
{
2020-06-03 06:59:28 -07:00
//
// The exception is not what we want
//
continue;
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
2020-06-13 03:12:44 -07:00
case IN_INSTRUCTION_EXECUTION:
case OUT_INSTRUCTION_EXECUTION:
2020-06-13 03:12:44 -07:00
//
// check if I/O port is what we want or not
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != DEBUGGER_EVENT_ALL_IO_PORTS && CurrentEvent->Options.OptionalParam1 != (UINT64)Context)
2023-03-22 17:45:52 +09:00
{
2020-06-13 03:12:44 -07:00
//
// The port is not what we want
//
continue;
}
2020-06-13 03:12:44 -07:00
break;
2021-07-19 17:31:59 +04:30
2020-06-13 22:39:53 -07:00
case SYSCALL_HOOK_EFER_SYSCALL:
//
// case SYSCALL_HOOK_EFER_SYSRET:
//
// I don't know how to find syscall number when sysret is executed so
// that's why we don't support extra argument for sysret
//
2020-06-13 22:39:53 -07:00
//
// check syscall number
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != DEBUGGER_EVENT_SYSCALL_ALL_SYSRET_OR_SYSCALLS && CurrentEvent->Options.OptionalParam1 != (UINT64)Context)
2023-03-22 17:45:52 +09:00
{
2020-06-13 22:39:53 -07:00
//
// The syscall number is not what we want
//
continue;
}
2021-07-19 17:31:59 +04:30
2020-06-13 22:39:53 -07:00
break;
2021-07-19 17:31:59 +04:30
case CPUID_INSTRUCTION_EXECUTION:
//
// check if CPUID is what we want or not
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != (UINT64)NULL /*FALSE*/ && CurrentEvent->Options.OptionalParam2 != (UINT64)Context)
{
//
// The CPUID is not what we want (and the user didn't intend to get all CPUIDs)
//
continue;
}
break;
case CONTROL_REGISTER_MODIFIED:
//
// check if CR exit is what we want or not
//
2024-03-01 15:59:58 +09:00
if (CurrentEvent->Options.OptionalParam1 != (UINT64)Context)
2023-03-22 17:45:52 +09:00
{
//
// The CR is not what we want
//
continue;
}
break;
case TRAP_EXECUTION_MODE_CHANGED:
2023-09-18 19:47:13 +09:00
//
// check if the debugger needs user-to-kernel or kernel-to-user events
//
2023-10-14 21:28:08 +09:00
if (CurrentEvent->Options.OptionalParam1 != DEBUGGER_EVENT_MODE_TYPE_USER_MODE_AND_KERNEL_MODE)
2023-09-18 19:47:13 +09:00
{
2023-10-14 21:28:08 +09:00
if ((CurrentEvent->Options.OptionalParam1 == DEBUGGER_EVENT_MODE_TYPE_USER_MODE &&
2024-03-01 23:02:03 +09:00
Context == (PVOID)DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE) ||
2023-10-14 21:28:08 +09:00
(CurrentEvent->Options.OptionalParam1 == DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE &&
2024-03-01 23:02:03 +09:00
Context == (PVOID)DEBUGGER_EVENT_MODE_TYPE_USER_MODE))
2023-09-18 19:47:13 +09:00
{
continue;
}
}
break;
2025-08-21 00:17:26 +02:00
case XSETBV_INSTRUCTION_EXECUTION:
//
// check if XSETBV is what we want or not
//
if (CurrentEvent->Options.OptionalParam1 != (UINT64)NULL /*FALSE*/ && CurrentEvent->Options.OptionalParam2 != (UINT64)Context)
{
//
// The XCR is not what we want (and the user didn't intend to get all XSETBVs)
//
continue;
}
break;
default: // All other events that don't have conditions
2020-06-13 03:12:44 -07:00
break;
2020-06-03 06:59:28 -07:00
}
//
2023-07-30 22:43:51 +09:00
// Check the stage of calling (pre, all, or post event)
//
2023-07-30 22:43:51 +09:00
if (CallingStage == VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION &&
(CurrentEvent->EventMode == VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION ||
CurrentEvent->EventMode == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION))
2023-03-22 17:45:52 +09:00
{
//
2023-07-30 22:43:51 +09:00
// Here it means that the current event is a post, or all event event
// and the current stage of calling is for the pre-event events, thus
2024-03-17 01:01:22 +09:00
// this event is not supposed to be ran at the current stage.
// However, we'll set a flag so the caller will know that there is
// a valid post-event available for the parameters related to this
// event.
// This mechanism notifies the caller to trigger the event after
// emulation, we implement it in a way that the caller knows when
// to trigger a post-event thus it optimizes the number of times
// that the caller triggers the events and avoid unnecessary triggering
// of the event (for post-event) but at the same time we have the
// flexibility of having both pre-event and post-event concepts
//
*PostEventRequired = TRUE;
2023-07-30 22:43:51 +09:00
if (CurrentEvent->EventMode == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION)
{
//
// If it's not an 'all' event and it is only the 'post' event,
// then we ignore the trigger stage
//
continue;
}
}
2020-04-20 06:49:34 -07:00
//
2024-03-17 18:17:38 +09:00
// Check if condition is met or not , if the condition
2020-04-20 06:49:34 -07:00
// is not met then we have to avoid performing the actions
//
2023-03-22 17:45:52 +09:00
if (CurrentEvent->ConditionsBufferSize != 0)
{
2020-04-20 06:49:34 -07:00
//
// Means that there is some conditions
//
2024-03-01 22:27:09 +09:00
ConditionFunc = (DebuggerCheckForCondition *)CurrentEvent->ConditionBufferAddress;
2020-04-20 06:49:34 -07:00
//
// Run and check for results
//
// Because the user might change the nonvolatile registers, we save fastcall nonvolatile registers
//
if (AsmDebuggerConditionCodeHandler((UINT64)Regs, (UINT64)Context, (UINT64)ConditionFunc) == 0)
2023-03-22 17:45:52 +09:00
{
2020-04-20 06:49:34 -07:00
//
// The condition function returns null, mean that the
// condition didn't met, we can ignore this event
//
continue;
}
}
2022-06-15 12:55:44 +04:30
//
2023-07-13 16:05:42 +09:00
// Reset the event ignorance mechanism (apply 'sc on/off' to the events)
2022-06-15 12:55:44 +04:30
//
2023-06-07 19:24:47 +09:00
DbgState->ShortCircuitingEvent = CurrentEvent->EnableShortCircuiting;
2022-06-15 12:55:44 +04:30
2023-07-30 22:43:51 +09:00
//
// Setup event trigger detail
2023-07-30 22:43:51 +09:00
//
EventTriggerDetail.Context = Context;
EventTriggerDetail.Tag = CurrentEvent->Tag;
EventTriggerDetail.Stage = CallingStage;
2023-07-30 22:43:51 +09:00
2020-04-15 17:08:13 -07:00
//
2020-04-16 06:21:50 -07:00
// perform the actions
2020-04-15 17:08:13 -07:00
//
DebuggerPerformActions(DbgState, CurrentEvent, &EventTriggerDetail, Regs);
2020-04-15 17:08:13 -07:00
}
2022-06-15 12:55:44 +04:30
//
// Check if the event should be ignored or not
//
2023-03-22 17:45:52 +09:00
if (DbgState->ShortCircuitingEvent)
{
//
2023-07-13 16:05:42 +09:00
// Reset the event ignorance (short-circuit) mechanism
//
DbgState->ShortCircuitingEvent = FALSE;
2022-06-15 12:55:44 +04:30
//
// Event should be ignored
//
2023-01-29 04:06:01 +09:00
return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT;
2023-03-22 17:45:52 +09:00
}
else
{
2022-06-15 12:55:44 +04:30
//
// Event shouldn't be ignored
//
2023-01-29 04:06:01 +09:00
return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL;
2022-06-15 12:55:44 +04:30
}
2020-04-15 17:08:13 -07:00
}
2020-08-28 04:03:12 -07:00
/**
* @brief Run a special event's action(s)
2022-06-28 09:52:24 -07:00
*
2022-12-09 14:49:25 +09:00
* @param DbgState The state of the debugger on the current core
2020-08-28 04:03:12 -07:00
* @param Event Event Object
* @param EventTriggerDetail Event trigger details
* @param Regs Registers
*
2022-06-28 09:52:24 -07:00
* @return VOID
2020-08-28 04:03:12 -07:00
*/
2023-03-22 17:45:52 +09:00
VOID
DebuggerPerformActions(PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGER_EVENT * Event,
DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail,
GUEST_REGS * Regs)
2020-04-15 17:08:13 -07:00
{
2020-04-16 10:40:20 -07:00
PLIST_ENTRY TempList = 0;
//
// Find and run all the actions in this Event
//
TempList = &Event->ActionsListHead;
2023-03-22 17:45:52 +09:00
while (&Event->ActionsListHead != TempList->Flink)
{
TempList = TempList->Flink;
2020-04-16 10:40:20 -07:00
PDEBUGGER_EVENT_ACTION CurrentAction = CONTAINING_RECORD(TempList, DEBUGGER_EVENT_ACTION, ActionsList);
//
// Perform the action
//
2023-03-22 17:45:52 +09:00
switch (CurrentAction->ActionType)
{
2020-04-16 10:40:20 -07:00
case BREAK_TO_DEBUGGER:
DebuggerPerformBreakToDebugger(DbgState, CurrentAction, EventTriggerDetail, Regs);
2020-04-16 10:40:20 -07:00
break;
2020-10-08 01:16:51 -07:00
case RUN_SCRIPT:
DebuggerPerformRunScript(DbgState, CurrentAction, NULL, EventTriggerDetail, Regs);
2020-04-16 10:40:20 -07:00
break;
2020-04-16 10:40:20 -07:00
case RUN_CUSTOM_CODE:
DebuggerPerformRunTheCustomCode(DbgState, CurrentAction, EventTriggerDetail, Regs);
2020-04-16 10:40:20 -07:00
break;
2020-04-16 10:40:20 -07:00
default:
2022-04-24 20:57:08 +04:30
2020-04-16 10:40:20 -07:00
//
// Invalid action type
//
break;
}
}
2020-04-15 17:08:13 -07:00
}
2020-08-28 04:03:12 -07:00
/**
2020-10-08 01:16:51 -07:00
* @brief Managing run script action
2022-06-28 09:52:24 -07:00
*
2022-12-09 14:49:25 +09:00
* @param DbgState The state of the debugger on the current core
2020-08-28 04:03:12 -07:00
* @param Action Action object
* @param ScriptDetails Details of script
* @param EventTriggerDetail Event trigger detail
* @param Regs registers
*
2022-06-28 09:52:24 -07:00
* @return BOOLEAN
2020-08-28 04:03:12 -07:00
*/
2021-02-04 08:37:49 -08:00
BOOLEAN
DebuggerPerformRunScript(PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGER_EVENT_ACTION * Action,
DEBUGGEE_SCRIPT_PACKET * ScriptDetails,
DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail,
GUEST_REGS * Regs)
2020-04-16 11:17:42 -07:00
{
2024-07-24 21:25:55 +08:00
SYMBOL_BUFFER CodeBuffer = {0};
ACTION_BUFFER ActionBuffer = {0};
SYMBOL ErrorSymbol = {0};
SCRIPT_ENGINE_GENERAL_REGISTERS ScriptGeneralRegisters = {0};
2021-01-14 02:33:38 -08:00
2023-03-22 17:45:52 +09:00
if (Action != NULL)
{
//
// Fill the action buffer's calling stage
//
if (EventTriggerDetail->Stage == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION)
{
ActionBuffer.CallingStage = 1;
}
else
{
ActionBuffer.CallingStage = 0;
}
2021-02-04 08:37:49 -08:00
//
// Fill the action buffer
//
2024-03-01 21:02:52 +09:00
ActionBuffer.Context = (UINT64)EventTriggerDetail->Context;
ActionBuffer.Tag = EventTriggerDetail->Tag;
2021-02-04 08:37:49 -08:00
ActionBuffer.ImmediatelySendTheResults = Action->ImmediatelySendTheResults;
2024-03-01 21:02:52 +09:00
ActionBuffer.CurrentAction = (UINT64)Action;
2020-11-04 06:58:04 -08:00
2021-02-04 08:37:49 -08:00
//
// Context point to the registers
//
2024-03-01 21:02:52 +09:00
CodeBuffer.Head = (PSYMBOL)Action->ScriptConfiguration.ScriptBuffer;
2023-03-22 17:45:52 +09:00
CodeBuffer.Size = Action->ScriptConfiguration.ScriptLength;
2021-02-04 08:37:49 -08:00
CodeBuffer.Pointer = Action->ScriptConfiguration.ScriptPointer;
2023-03-22 17:45:52 +09:00
}
else if (ScriptDetails != NULL)
{
//
// Fill the action buffer's calling stage
//
if (EventTriggerDetail->Stage == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION)
{
ActionBuffer.CallingStage = 1;
}
else
{
ActionBuffer.CallingStage = 0;
}
2021-02-04 08:37:49 -08:00
//
// Fill the action buffer
//
2024-03-01 21:02:52 +09:00
ActionBuffer.Context = (UINT64)EventTriggerDetail->Context;
ActionBuffer.Tag = EventTriggerDetail->Tag;
2021-02-04 08:37:49 -08:00
ActionBuffer.ImmediatelySendTheResults = TRUE;
2024-03-01 21:02:52 +09:00
ActionBuffer.CurrentAction = (UINT64)NULL;
2021-02-04 08:37:49 -08:00
//
// Context point to the registers
//
2024-03-01 21:02:52 +09:00
CodeBuffer.Head = (SYMBOL *)((CHAR *)ScriptDetails + sizeof(DEBUGGEE_SCRIPT_PACKET));
2023-03-22 17:45:52 +09:00
CodeBuffer.Size = ScriptDetails->ScriptBufferSize;
2021-02-04 08:37:49 -08:00
CodeBuffer.Pointer = ScriptDetails->ScriptBufferPointer;
2023-03-22 17:45:52 +09:00
}
else
{
2021-02-04 08:37:49 -08:00
//
// The parameters are wrong !
//
return FALSE;
}
2020-10-25 10:09:52 -07:00
//
2024-07-24 21:25:55 +08:00
// Fill the stack buffer for this run
//
2024-07-24 21:25:55 +08:00
ScriptGeneralRegisters.StackBuffer = DbgState->ScriptEngineCoreSpecificStackBuffer;
ScriptGeneralRegisters.GlobalVariablesList = g_ScriptGlobalVariables;
RtlZeroMemory(ScriptGeneralRegisters.StackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
2024-06-15 02:10:03 +08:00
UINT64 EXECUTENUMBER = 0;
2024-06-15 02:10:03 +08:00
2024-03-01 21:02:52 +09:00
for (UINT64 i = 0; i < CodeBuffer.Pointer;)
2023-03-22 17:45:52 +09:00
{
//
// If has error, show error message and abort.
//
if (ScriptEngineExecute(Regs,
2023-03-22 17:45:52 +09:00
&ActionBuffer,
2024-07-24 21:25:55 +08:00
&ScriptGeneralRegisters,
2023-03-22 17:45:52 +09:00
&CodeBuffer,
&i,
2024-07-24 21:25:55 +08:00
&ErrorSymbol) == TRUE)
2023-03-22 17:45:52 +09:00
{
LogInfo("Err, ScriptEngineExecute, function = % s\n ",
FunctionNames[ErrorSymbol.Value]);
break;
}
2024-07-24 21:25:55 +08:00
else if (ScriptGeneralRegisters.StackIndx >= MAX_STACK_BUFFER_COUNT)
{
LogInfo("Err, stack buffer overflow (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n");
break;
}
else if (EXECUTENUMBER >= MAX_EXECUTION_COUNT)
{
LogInfo("Err, exceeding the max execution count (more information: https://docs.hyperdbg.org/tips-and-tricks/misc/customize-build/change-script-engine-limitations)\n");
break;
}
EXECUTENUMBER++;
2020-10-25 10:09:52 -07:00
}
2021-02-04 08:37:49 -08:00
return TRUE;
2020-04-16 11:17:42 -07:00
}
2020-04-16 10:40:20 -07:00
2020-08-28 04:03:12 -07:00
/**
* @brief Manage running the custom code action
2022-06-28 09:52:24 -07:00
*
2022-12-09 14:49:25 +09:00
* @param DbgState The state of the debugger on the current core
2020-08-28 04:03:12 -07:00
* @param Action Action object
* @param EventTriggerDetail Event trigger detail
* @param Reg Registers
*
2022-06-28 09:52:24 -07:00
* @return VOID
2020-08-28 04:03:12 -07:00
*/
2023-03-22 17:45:52 +09:00
VOID
DebuggerPerformRunTheCustomCode(PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGER_EVENT_ACTION * Action,
DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail,
GUEST_REGS * Regs)
2020-04-15 17:08:13 -07:00
{
UNREFERENCED_PARAMETER(DbgState);
2023-03-22 17:45:52 +09:00
if (Action->CustomCodeBufferSize == 0)
{
2020-04-19 11:53:03 -07:00
//
// Sth went wrong ! the buffer size for custom code shouldn't be zero
//
return;
}
2020-05-12 15:43:34 -07:00
//
// -----------------------------------------------------------------------------------------------------
2023-07-31 15:05:14 +09:00
// Test
2020-05-12 15:43:34 -07:00
//
2021-08-30 17:23:17 +04:30
// LogInfo("%X Called from : %llx", Tag, Context);
//
2021-02-04 08:37:49 -08:00
//
// LogInfo("Process Id : %x , Rax : %llx , R8 : %llx , Context : 0x%llx ", PsGetCurrentProcessId(), Regs->rax, Regs->r8, Context);
// return;
2020-05-12 15:43:34 -07:00
//
// -----------------------------------------------------------------------------------------------------
//
2020-04-19 11:53:03 -07:00
//
// Run the custom code
//
2023-03-22 17:45:52 +09:00
if (Action->RequestedBuffer.RequestBufferSize == 0)
{
2020-04-19 11:53:03 -07:00
//
// Because the user might change the nonvolatile registers, we save fastcall nonvolatile registers
2020-04-19 11:53:03 -07:00
//
2024-03-01 22:27:09 +09:00
AsmDebuggerCustomCodeHandler((UINT64)NULL,
(UINT64)Regs,
2024-03-01 22:27:09 +09:00
(UINT64)EventTriggerDetail->Context,
(UINT64)Action->CustomCodeBufferAddress);
2023-03-22 17:45:52 +09:00
}
else
{
2020-04-19 11:53:03 -07:00
//
// Because the user might change the nonvolatile registers, we save fastcall nonvolatile registers
2020-04-19 11:53:03 -07:00
//
2024-03-01 22:27:09 +09:00
AsmDebuggerCustomCodeHandler((UINT64)Action->RequestedBuffer.RequstBufferAddress,
(UINT64)Regs,
2024-03-01 22:27:09 +09:00
(UINT64)EventTriggerDetail->Context,
(UINT64)Action->CustomCodeBufferAddress);
2020-04-19 11:53:03 -07:00
}
2020-04-15 17:08:13 -07:00
}
2021-02-04 08:37:49 -08:00
/**
* @brief Manage breaking to the debugger action
2022-06-28 09:52:24 -07:00
*
2022-12-09 14:49:25 +09:00
* @param DbgState The state of the debugger on the current core
2021-02-04 08:37:49 -08:00
* @param Tag Tag of event
* @param Action Action object
* @param EventTriggerDetail Event trigger detail
* @param Regs Registers
2022-12-05 15:31:56 +09:00
*
2022-06-28 09:52:24 -07:00
* @return VOID
2021-02-04 08:37:49 -08:00
*/
2023-03-22 17:45:52 +09:00
VOID
DebuggerPerformBreakToDebugger(PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGER_EVENT_ACTION * Action,
DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail,
GUEST_REGS * Regs)
2021-02-04 08:37:49 -08:00
{
2024-03-01 18:11:24 +09:00
UNREFERENCED_PARAMETER(Action);
2023-03-22 17:45:52 +09:00
if (VmFuncVmxGetCurrentExecutionMode() == TRUE)
{
//
// The guest is already in vmx-root mode
// Halt other cores
//
KdHandleBreakpointAndDebugBreakpoints(
DbgState,
DEBUGGEE_PAUSING_REASON_DEBUGGEE_EVENT_TRIGGERED,
EventTriggerDetail);
2023-03-22 17:45:52 +09:00
}
else
{
//
// The guest is on vmx non-root mode and this is an event
//
2024-03-01 18:11:24 +09:00
VmFuncVmxVmcall(DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM_AS_A_RESULT_OF_TRIGGERING_EVENT,
(UINT64)EventTriggerDetail,
(UINT64)Regs,
2024-03-01 21:02:52 +09:00
(UINT64)NULL);
}
2021-02-04 08:37:49 -08:00
}
/**
* @brief Manage breaking to the debugger action by core id
*
* @param CoreId
* @param Tag Tag of event
* @param Action Action object
* @param EventTriggerDetail Event trigger detail
* @param Regs Registers
*
* @return VOID
*/
VOID
DebuggerPerformBreakToDebuggerByCoreId(UINT32 CoreId,
DEBUGGER_EVENT_ACTION * Action,
DEBUGGER_TRIGGERED_EVENT_DETAILS * EventTriggerDetail,
GUEST_REGS * Regs)
{
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
DebuggerPerformBreakToDebugger(DbgState, Action, EventTriggerDetail, Regs);
}
2020-08-28 04:03:12 -07:00
/**
* @brief Find event object by tag
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Tag of event
* @return PDEBUGGER_EVENT Returns null if not found and event object if found
*/
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT
DebuggerGetEventByTag(UINT64 Tag)
2020-04-15 17:08:13 -07:00
{
2023-03-22 17:45:52 +09:00
PLIST_ENTRY TempList = 0;
2020-05-14 08:28:28 -07:00
PLIST_ENTRY TempList2 = 0;
//
// We have to iterate through all events
//
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
2023-03-22 17:45:52 +09:00
{
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
TempList2 = TempList;
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
2020-05-14 08:28:28 -07:00
//
// Check if we find the event or not
//
2023-03-22 17:45:52 +09:00
if (CurrentEvent->Tag == Tag)
{
return CurrentEvent;
2020-05-14 08:28:28 -07:00
}
}
}
//
// We didn't find anything, so return null
//
return NULL;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Enable or disable all events from all the types
2022-06-28 09:52:24 -07:00
*
* @param IsEnable If you want to enable then true and if
2020-08-28 04:03:12 -07:00
* you want to disable then false
* @return BOOLEAN if at least one event enabled/disabled then
* it returns true, and otherwise false
*/
BOOLEAN
DebuggerEnableOrDisableAllEvents(BOOLEAN IsEnable)
{
2023-03-22 17:45:52 +09:00
BOOLEAN FindAtLeastOneEvent = FALSE;
PLIST_ENTRY TempList = 0;
PLIST_ENTRY TempList2 = 0;
2020-08-28 04:03:12 -07:00
//
// We have to iterate through all events
//
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
2023-03-22 17:45:52 +09:00
{
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
2020-08-28 04:03:12 -07:00
TempList2 = TempList;
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
2020-08-28 04:03:12 -07:00
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
//
// Check if we find at least one event or not
//
2023-03-22 17:45:52 +09:00
if (!FindAtLeastOneEvent)
{
2020-08-28 04:03:12 -07:00
FindAtLeastOneEvent = TRUE;
}
//
// Enable or disable event
2023-11-02 13:48:56 +09:00
// (We could directly modify the "enabled" flag here, however
// in the case of any possible callback for enabling/disabling let's
// modify the state of being enable all of them in a single place)
2020-08-28 04:03:12 -07:00
//
2023-11-02 13:48:56 +09:00
if (IsEnable)
{
DebuggerEnableEvent(CurrentEvent->Tag);
}
else
{
DebuggerDisableEvent(CurrentEvent->Tag);
}
2020-08-28 04:03:12 -07:00
}
}
return FindAtLeastOneEvent;
}
/**
* @brief Terminate effect and configuration to vmx-root
* and non-root for all the events
2022-06-28 09:52:24 -07:00
*
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN if at least one event terminated then
* it returns true, and otherwise false
*/
BOOLEAN
DebuggerTerminateAllEvents(BOOLEAN InputFromVmxRoot)
2020-08-28 04:03:12 -07:00
{
2023-03-22 17:45:52 +09:00
BOOLEAN FindAtLeastOneEvent = FALSE;
PLIST_ENTRY TempList = 0;
PLIST_ENTRY TempList2 = 0;
2020-08-28 04:03:12 -07:00
//
// We have to iterate through all events
//
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
2023-03-22 17:45:52 +09:00
{
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
2020-08-28 04:03:12 -07:00
TempList2 = TempList;
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
2020-08-28 04:03:12 -07:00
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
//
// Check if we find at least one event or not
//
2023-03-22 17:45:52 +09:00
if (!FindAtLeastOneEvent)
{
2020-08-28 04:03:12 -07:00
FindAtLeastOneEvent = TRUE;
}
//
// Terminate the current event
//
DebuggerTerminateEvent(CurrentEvent->Tag, InputFromVmxRoot);
2020-08-28 04:03:12 -07:00
}
}
return FindAtLeastOneEvent;
}
/**
* @brief Remove all the events from all the lists
* and also de-allocate their structures and actions
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @details should not be called from vmx-root mode, also
2022-06-28 09:52:24 -07:00
* it won't terminate their effects, so the events should
2020-08-28 04:03:12 -07:00
* be terminated first then we can remove them
2022-06-28 09:52:24 -07:00
*
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN if at least one event removed then
* it returns true, and otherwise false
*/
BOOLEAN
DebuggerRemoveAllEvents(BOOLEAN PoolManagerAllocatedMemory)
2020-08-28 04:03:12 -07:00
{
2023-03-22 17:45:52 +09:00
BOOLEAN FindAtLeastOneEvent = FALSE;
PLIST_ENTRY TempList = 0;
PLIST_ENTRY TempList2 = 0;
2020-08-28 04:03:12 -07:00
//
// We have to iterate through all events
//
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
2023-03-22 17:45:52 +09:00
{
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
2020-08-28 04:03:12 -07:00
TempList2 = TempList;
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
2020-08-28 04:03:12 -07:00
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
//
// Check if we find at least one event or not
//
2023-03-22 17:45:52 +09:00
if (!FindAtLeastOneEvent)
{
2020-08-28 04:03:12 -07:00
FindAtLeastOneEvent = TRUE;
}
//
// Remove the current event
//
DebuggerRemoveEvent(CurrentEvent->Tag, PoolManagerAllocatedMemory);
2020-08-28 04:03:12 -07:00
}
}
return FindAtLeastOneEvent;
}
/**
* @brief Count the list of events in a special list
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param TargetEventList target event list
* @return UINT32 count of events on the list
*/
UINT32
DebuggerEventListCount(PLIST_ENTRY TargetEventList)
{
PLIST_ENTRY TempList = 0;
2023-03-22 17:45:52 +09:00
UINT32 Counter = 0;
2020-08-28 04:03:12 -07:00
//
// We have to iterate through all events of this list
//
TempList = TargetEventList;
2023-03-22 17:45:52 +09:00
while (TargetEventList != TempList->Flink)
{
2024-03-01 18:11:24 +09:00
TempList = TempList->Flink;
/* PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList); */
2020-08-28 04:03:12 -07:00
//
// Increase the counter
//
Counter++;
}
return Counter;
}
/**
* @brief Get List of event based on event type
*
* @param EventType type of event
* @return PLIST_ENTRY
*/
PLIST_ENTRY
2023-01-29 04:06:01 +09:00
DebuggerGetEventListByEventType(VMM_EVENT_TYPE_ENUM EventType)
{
PLIST_ENTRY ResultList = NULL;
//
// Register the event
//
2023-03-22 17:45:52 +09:00
switch (EventType)
{
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
ResultList = &g_Events->HiddenHookReadAndWriteAndExecuteEventsHead;
break;
case HIDDEN_HOOK_READ_AND_WRITE:
ResultList = &g_Events->HiddenHookReadAndWriteEventsHead;
break;
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_EXECUTE:
ResultList = &g_Events->HiddenHookReadAndExecuteEventsHead;
break;
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
ResultList = &g_Events->HiddenHookWriteAndExecuteEventsHead;
break;
case HIDDEN_HOOK_READ:
ResultList = &g_Events->HiddenHookReadEventsHead;
break;
case HIDDEN_HOOK_WRITE:
ResultList = &g_Events->HiddenHookWriteEventsHead;
break;
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_EXECUTE:
ResultList = &g_Events->HiddenHookExecuteEventsHead;
break;
case HIDDEN_HOOK_EXEC_DETOURS:
ResultList = &g_Events->EptHook2sExecDetourEventsHead;
break;
case HIDDEN_HOOK_EXEC_CC:
ResultList = &g_Events->EptHookExecCcEventsHead;
break;
case SYSCALL_HOOK_EFER_SYSCALL:
ResultList = &g_Events->SyscallHooksEferSyscallEventsHead;
break;
case SYSCALL_HOOK_EFER_SYSRET:
ResultList = &g_Events->SyscallHooksEferSysretEventsHead;
break;
case CPUID_INSTRUCTION_EXECUTION:
ResultList = &g_Events->CpuidInstructionExecutionEventsHead;
break;
case RDMSR_INSTRUCTION_EXECUTION:
ResultList = &g_Events->RdmsrInstructionExecutionEventsHead;
break;
case WRMSR_INSTRUCTION_EXECUTION:
ResultList = &g_Events->WrmsrInstructionExecutionEventsHead;
break;
case EXCEPTION_OCCURRED:
ResultList = &g_Events->ExceptionOccurredEventsHead;
break;
case TSC_INSTRUCTION_EXECUTION:
ResultList = &g_Events->TscInstructionExecutionEventsHead;
break;
case PMC_INSTRUCTION_EXECUTION:
ResultList = &g_Events->PmcInstructionExecutionEventsHead;
break;
case IN_INSTRUCTION_EXECUTION:
ResultList = &g_Events->InInstructionExecutionEventsHead;
break;
case OUT_INSTRUCTION_EXECUTION:
ResultList = &g_Events->OutInstructionExecutionEventsHead;
break;
case DEBUG_REGISTERS_ACCESSED:
ResultList = &g_Events->DebugRegistersAccessedEventsHead;
break;
case EXTERNAL_INTERRUPT_OCCURRED:
ResultList = &g_Events->ExternalInterruptOccurredEventsHead;
break;
case VMCALL_INSTRUCTION_EXECUTION:
ResultList = &g_Events->VmcallInstructionExecutionEventsHead;
break;
case TRAP_EXECUTION_MODE_CHANGED:
ResultList = &g_Events->TrapExecutionModeChangedEventsHead;
break;
case TRAP_EXECUTION_INSTRUCTION_TRACE:
ResultList = &g_Events->TrapExecutionInstructionTraceEventsHead;
break;
case CONTROL_REGISTER_3_MODIFIED:
ResultList = &g_Events->ControlRegister3ModifiedEventsHead;
2023-09-13 19:59:55 +09:00
break;
case CONTROL_REGISTER_MODIFIED:
ResultList = &g_Events->ControlRegisterModifiedEventsHead;
break;
2025-08-21 00:17:26 +02:00
case XSETBV_INSTRUCTION_EXECUTION:
ResultList = &g_Events->XsetbvInstructionExecutionEventsHead;
break;
default:
//
// Wrong event type
//
LogError("Err, wrong event type is specified");
ResultList = NULL;
break;
}
return ResultList;
}
/**
* @brief Count the list of events in a special list that
* are activate on a target core
2022-06-28 09:52:24 -07:00
*
* @param TargetEventList target event list
* @param TargetCore target core
* @return UINT32 count of events on the list which is activated
* on the target core
*/
UINT32
DebuggerEventListCountByCore(PLIST_ENTRY TargetEventList, UINT32 TargetCore)
{
PLIST_ENTRY TempList = 0;
2023-03-22 17:45:52 +09:00
UINT32 Counter = 0;
//
// We have to iterate through all events of this list
//
TempList = TargetEventList;
2023-03-22 17:45:52 +09:00
while (TargetEventList != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
2023-03-22 17:45:52 +09:00
if (CurrentEvent->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES || CurrentEvent->CoreId == TargetCore)
{
//
// Increase the counter
//
Counter++;
}
}
return Counter;
}
/**
* @brief Count the list of events by a special event type that
* are activate on a target core
*
* @param EventType target event type
* @param TargetCore target core
*
* @return UINT32 count of events on the list which is activated
* on the target core
*/
UINT32
2023-01-29 04:06:01 +09:00
DebuggerEventListCountByEventType(VMM_EVENT_TYPE_ENUM EventType, UINT32 TargetCore)
{
PLIST_ENTRY TempList = 0;
2023-03-22 17:45:52 +09:00
UINT32 Counter = 0;
PLIST_ENTRY TargetEventList = DebuggerGetEventListByEventType(EventType);
//
// We have to iterate through all events of this list
//
TempList = TargetEventList;
2023-03-22 17:45:52 +09:00
while (TargetEventList != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
2023-03-22 17:45:52 +09:00
if (CurrentEvent->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES || CurrentEvent->CoreId == TargetCore)
{
//
// Increase the counter
//
Counter++;
}
}
return Counter;
}
/**
* @brief Get the mask related to the !exception command for the
* target core
2022-06-28 09:52:24 -07:00
*
* @param CoreIndex The index of core
2022-06-28 09:52:24 -07:00
*
* @return UINT32 Returns the current mask for the core
*/
UINT32
DebuggerExceptionEventBitmapMask(UINT32 CoreIndex)
{
2023-03-22 17:45:52 +09:00
PLIST_ENTRY TempList = 0;
UINT32 ExceptionMask = 0;
//
// We have to iterate through all events of this list
//
TempList = &g_Events->ExceptionOccurredEventsHead;
2023-03-22 17:45:52 +09:00
while (&g_Events->ExceptionOccurredEventsHead != TempList->Flink)
{
TempList = TempList->Flink;
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
2023-03-22 17:45:52 +09:00
if (CurrentEvent->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES || CurrentEvent->CoreId == CoreIndex)
{
2023-10-14 21:28:08 +09:00
ExceptionMask |= CurrentEvent->Options.OptionalParam1;
}
}
return ExceptionMask;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Enable an event by tag
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Tag of target event
2022-06-28 09:52:24 -07:00
* @return BOOLEAN TRUE if event enabled and FALSE if event not
2020-08-28 04:03:12 -07:00
* found
*/
BOOLEAN
2020-05-14 08:28:28 -07:00
DebuggerEnableEvent(UINT64 Tag)
{
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT Event;
//
// Search all the cores for enable this event
//
Event = DebuggerGetEventByTag(Tag);
//
2020-05-14 08:28:28 -07:00
// Check if tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
2020-05-14 08:28:28 -07:00
return FALSE;
}
//
// Enable the event
//
Event->Enabled = TRUE;
return TRUE;
}
2020-05-14 08:28:28 -07:00
/**
* @brief returns whether an event is enabled/disabled by tag
* @details this function won't check for Tag validity and if
* not found then returns false
2022-06-28 09:52:24 -07:00
*
* @param Tag Tag of target event
2022-06-28 09:52:24 -07:00
* @return BOOLEAN TRUE if event enabled and FALSE if event not
* found
*/
BOOLEAN
DebuggerQueryStateEvent(UINT64 Tag)
{
PDEBUGGER_EVENT Event;
//
// Search all the cores for enable this event
//
Event = DebuggerGetEventByTag(Tag);
//
// Check if tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
return FALSE;
}
return Event->Enabled;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Disable an event by tag
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Tag of target event
2022-06-28 09:52:24 -07:00
* @return BOOLEAN TRUE if event enabled and FALSE if event not
2020-08-28 04:03:12 -07:00
* found
*/
BOOLEAN
DebuggerDisableEvent(UINT64 Tag)
{
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT Event;
2020-08-28 04:03:12 -07:00
2020-05-14 08:28:28 -07:00
//
// Search all the cores for enable this event
//
Event = DebuggerGetEventByTag(Tag);
//
// Check if tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
2020-05-14 08:28:28 -07:00
return FALSE;
}
//
// Disable the event
//
Event->Enabled = FALSE;
return TRUE;
}
2023-10-22 01:14:36 +09:00
/**
* @brief Clear an event by tag
*
* @param Tag Tag of target event
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
2023-10-22 01:14:36 +09:00
*
* @return BOOLEAN
*
*/
BOOLEAN
DebuggerClearEvent(UINT64 Tag, BOOLEAN InputFromVmxRoot, BOOLEAN PoolManagerAllocatedMemory)
2023-10-22 01:14:36 +09:00
{
//
// Because we want to delete all the objects and buffers (pools)
// after we finished termination, the debugger might still use
// the buffers for events and action, for solving this problem
// we first disable the tag(s) and this way the debugger no longer
// use that event and this way we can safely remove and deallocate
// the buffers later after termination
//
//
// First, disable just one event
//
DebuggerDisableEvent(Tag);
//
// Second, terminate it
//
DebuggerTerminateEvent(Tag, InputFromVmxRoot);
//
// Third, remove it from the list
//
return DebuggerRemoveEvent(Tag, PoolManagerAllocatedMemory);
2023-10-22 01:14:36 +09:00
}
/**
* @brief Clear all events
*
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
2023-10-22 01:14:36 +09:00
*
* @return VOID
*/
VOID
DebuggerClearAllEvents(BOOLEAN InputFromVmxRoot, BOOLEAN PoolManagerAllocatedMemory)
2023-10-22 01:14:36 +09:00
{
//
// Because we want to delete all the objects and buffers (pools)
// after we finished termination, the debugger might still use
// the buffers for events and action, for solving this problem
// we first disable the tag(s) and this way the debugger no longer
// use that event and this way we can safely remove and deallocate
// the buffers later after termination
//
//
// First, disable all events
//
DebuggerEnableOrDisableAllEvents(FALSE);
//
// Second, terminate all events
//
DebuggerTerminateAllEvents(InputFromVmxRoot);
//
// Third, remove all events
//
DebuggerRemoveAllEvents(PoolManagerAllocatedMemory);
2023-10-22 01:14:36 +09:00
}
2020-08-28 04:03:12 -07:00
/**
* @brief Detect whether the tag exists or not
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Tag of target event
* @return BOOLEAN TRUE if event found and FALSE if event not found
*/
BOOLEAN
DebuggerIsTagValid(UINT64 Tag)
{
PDEBUGGER_EVENT Event;
//
// Search this event
//
Event = DebuggerGetEventByTag(Tag);
//
// Check if tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
2020-08-28 04:03:12 -07:00
return FALSE;
}
return TRUE;
}
/**
* @brief Detect whether the user or kernel debugger
* is active or not
*
* @return BOOLEAN TRUE if any of the are activated and FALSE if not
*/
BOOLEAN
DebuggerQueryDebuggerStatus()
{
2023-03-22 17:45:52 +09:00
if (g_KernelDebuggerState || g_UserDebuggerState)
{
return TRUE;
2023-03-22 17:45:52 +09:00
}
else
{
return FALSE;
}
}
2020-08-28 04:03:12 -07:00
/**
* @brief Remove the event from event list by its tag
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @details should not be called from vmx-root mode, also
2022-06-28 09:52:24 -07:00
* it won't terminate their effects, so the events should
2020-08-28 04:03:12 -07:00
* be terminated first then we can remove them
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Target events tag
* @return BOOLEAN If the event was removed then TRUE and FALSE
* if not found
*/
2020-05-14 08:28:28 -07:00
BOOLEAN
2020-05-15 10:45:22 -07:00
DebuggerRemoveEventFromEventList(UINT64 Tag)
2020-05-14 08:28:28 -07:00
{
2023-03-22 17:45:52 +09:00
PLIST_ENTRY TempList = 0;
2020-05-14 08:28:28 -07:00
PLIST_ENTRY TempList2 = 0;
//
// We have to iterate through all events
//
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
2023-03-22 17:45:52 +09:00
{
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
2020-05-14 08:28:28 -07:00
TempList2 = TempList;
2023-03-22 17:45:52 +09:00
while (TempList2 != TempList->Flink)
{
TempList = TempList->Flink;
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT CurrentEvent = CONTAINING_RECORD(TempList, DEBUGGER_EVENT, EventsOfSameTypeList);
//
// Check if we find the event or not
//
2023-03-22 17:45:52 +09:00
if (CurrentEvent->Tag == Tag)
{
2020-05-14 08:28:28 -07:00
//
// We have to remove the event from the list
//
2020-05-15 13:50:41 -07:00
RemoveEntryList(&CurrentEvent->EventsOfSameTypeList);
return TRUE;
2020-05-14 08:28:28 -07:00
}
}
}
//
2020-05-14 08:28:28 -07:00
// We didn't find anything, so return null
//
2020-05-14 08:28:28 -07:00
return FALSE;
}
2020-08-28 04:03:12 -07:00
/**
2022-06-28 09:52:24 -07:00
* @brief Remove the actions and de-allocate its buffer
*
2020-08-28 04:03:12 -07:00
* @details should not be called from vmx-root mode, also
2022-06-28 09:52:24 -07:00
* it won't terminate their effects, so the events should
* be terminated first then we can remove them *
*
2020-08-28 04:03:12 -07:00
* @param Event Event Object
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN TRUE if it was successful and FALSE if not successful
*/
BOOLEAN
DebuggerRemoveAllActionsFromEvent(PDEBUGGER_EVENT Event, BOOLEAN PoolManagerAllocatedMemory)
{
2023-03-22 17:45:52 +09:00
PLIST_ENTRY TempList = 0;
2020-05-14 08:28:28 -07:00
PLIST_ENTRY TempList2 = 0;
//
// Remove all actions
//
TempList = Event->ActionsListHead.Flink;
TempList2 = &Event->ActionsListHead;
2020-05-14 08:28:28 -07:00
while (TempList != TempList2)
2023-03-22 17:45:52 +09:00
{
PLIST_ENTRY NextList = TempList->Flink;
2020-05-14 08:28:28 -07:00
PDEBUGGER_EVENT_ACTION CurrentAction = CONTAINING_RECORD(TempList, DEBUGGER_EVENT_ACTION, ActionsList);
//
// Check if it has a OptionalRequestedBuffer probably for
// CustomCode
//
2024-03-01 15:59:58 +09:00
if (CurrentAction->RequestedBuffer.RequestBufferSize != 0 && CurrentAction->RequestedBuffer.RequstBufferAddress != (UINT64)NULL)
2023-03-22 17:45:52 +09:00
{
2020-05-14 08:28:28 -07:00
//
// There is a buffer
//
if (PoolManagerAllocatedMemory)
{
PoolManagerFreePool(CurrentAction->RequestedBuffer.RequstBufferAddress);
}
else
{
PlatformMemFreePool((PVOID)CurrentAction->RequestedBuffer.RequstBufferAddress);
}
2020-05-14 08:28:28 -07:00
}
//
// Remove the action and free the pool,
// if it's a custom buffer then the buffer
// is appended to the Action
//
RemoveEntryList(&CurrentAction->ActionsList);
if (PoolManagerAllocatedMemory)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)CurrentAction);
}
else
{
PlatformMemFreePool(CurrentAction);
}
TempList = NextList;
2020-05-14 08:28:28 -07:00
}
//
// Remember to free the pool
//
2020-05-14 08:28:28 -07:00
return TRUE;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Remove the event by its tags and also remove its actions
* and de-allocate their buffers
2022-06-28 09:52:24 -07:00
*
* @details it won't terminate their effects, so the events should
2020-08-28 04:03:12 -07:00
* be terminated first then we can remove them
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Target event tag
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN TRUE if it was successful and FALSE if not successful
*/
2020-05-14 08:28:28 -07:00
BOOLEAN
DebuggerRemoveEvent(UINT64 Tag, BOOLEAN PoolManagerAllocatedMemory)
2020-05-14 08:28:28 -07:00
{
PDEBUGGER_EVENT Event;
//
// First of all, we disable event
//
2023-03-22 17:45:52 +09:00
if (!DebuggerDisableEvent(Tag))
{
2020-05-14 08:28:28 -07:00
//
// Not found, tag is wrong !
//
return FALSE;
}
//
// When we're here, we are sure that the tag is valid
// because if it was not valid, then we have to return
// for the above function (DebuggerDisableEvent)
//
Event = DebuggerGetEventByTag(Tag);
//
2020-05-15 10:45:22 -07:00
// Now we get the PDEBUGGER_EVENT so we have to remove
// it from the event list
2020-05-14 08:28:28 -07:00
//
2023-03-22 17:45:52 +09:00
if (!DebuggerRemoveEventFromEventList(Tag))
{
2020-05-15 10:45:22 -07:00
return FALSE;
2020-05-14 08:28:28 -07:00
}
2020-05-15 13:50:41 -07:00
2020-05-14 08:28:28 -07:00
//
// Remove all of the actions and free its pools
//
DebuggerRemoveAllActionsFromEvent(Event, PoolManagerAllocatedMemory);
2020-05-14 08:28:28 -07:00
//
// Free the pools of Event, when we free the pool,
// ConditionsBufferAddress is also a part of the
// event pool (ConditionBufferAddress and event
// are both allocate in a same pool ) so both of
// them are freed
//
if (PoolManagerAllocatedMemory)
{
2024-03-01 18:11:24 +09:00
PoolManagerFreePool((UINT64)Event);
}
else
{
PlatformMemFreePool(Event);
}
2020-05-14 08:28:28 -07:00
return TRUE;
}
2020-04-16 10:40:20 -07:00
/**
* @brief validating events
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param EventDetails The structure that describes event that came
* from the user-mode or VMX-root mode
* @param ResultsToReturn Result buffer that should be returned to
2020-08-28 04:03:12 -07:00
* the user-mode
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
* @return BOOLEAN TRUE if the event was valid otherwise returns FALSE
*/
BOOLEAN
DebuggerValidateEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
2022-10-17 12:06:12 +09:00
//
// Check whether the event mode (calling stage) to see whether
// short-cicuiting event is used along with the post-event,
// it is because using the short-circuiting mechanism with
// post-events doesn't make sense; it's not supported!
//
2023-07-31 15:05:14 +09:00
if ((EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION ||
EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION) &&
2023-07-30 22:43:51 +09:00
EventDetails->EnableShortCircuiting == TRUE)
2023-03-22 17:45:52 +09:00
{
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_USING_SHORT_CIRCUITING_EVENT_WITH_POST_EVENT_MODE_IS_FORBIDDEDN;
2022-10-17 12:06:12 +09:00
return FALSE;
}
2020-06-01 14:17:32 -07:00
//
// Check whether the core Id is valid or not, we read cores count
// here because we use it in later parts
//
2023-03-22 17:45:52 +09:00
if (EventDetails->CoreId != DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
{
2020-06-01 14:17:32 -07:00
//
// Check if the core number is not invalid
//
if (!CommonValidateCoreNumber(EventDetails->CoreId))
2023-03-22 17:45:52 +09:00
{
2020-06-01 14:17:32 -07:00
//
// CoreId is invalid (Set the error)
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_CORE_ID;
2020-06-01 14:17:32 -07:00
return FALSE;
}
}
2021-11-04 12:47:18 +03:30
//
// Check if process id is valid or not, we won't touch process id here
// because some of the events use the exact value of DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES
//
2023-03-22 17:45:52 +09:00
if (EventDetails->ProcessId != DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES && EventDetails->ProcessId != 0)
{
2021-11-04 12:47:18 +03:30
//
// Here we prefer not to validate the process id, if it's applied from VMX-root mode
2021-11-04 12:47:18 +03:30
//
if (!InputFromVmxRoot)
2023-03-22 17:45:52 +09:00
{
//
// 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;
}
2021-11-04 12:47:18 +03:30
}
}
//
// *** Event specific validations ***
//
switch (EventDetails->EventType)
{
case EXCEPTION_OCCURRED:
2023-03-22 17:45:52 +09:00
{
2020-06-03 06:59:28 -07:00
//
// Check if exception parameters are valid
2020-06-03 06:59:28 -07:00
//
if (!ValidateEventException(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
2020-06-03 06:59:28 -07:00
//
// Event parameters are not valid, let break the further execution at this stage
2020-06-03 06:59:28 -07:00
//
return FALSE;
}
break;
2023-03-22 17:45:52 +09:00
}
case EXTERNAL_INTERRUPT_OCCURRED:
2023-03-22 17:45:52 +09:00
{
//
// Check if interrupt parameters are valid
//
if (!ValidateEventInterrupt(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
//
// Event parameters are not valid, let break the further execution at this stage
//
return FALSE;
}
break;
2023-03-22 17:45:52 +09:00
}
case TRAP_EXECUTION_MODE_CHANGED:
2023-09-18 19:47:13 +09:00
{
//
// Check if trap exec mode parameters are valid
2023-09-18 19:47:13 +09:00
//
if (!ValidateEventTrapExec(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-09-18 19:47:13 +09:00
{
//
// Event parameters are not valid, let break the further execution at this stage
2023-09-18 19:47:13 +09:00
//
return FALSE;
}
break;
2023-09-18 19:47:13 +09:00
}
case HIDDEN_HOOK_EXEC_DETOURS:
case HIDDEN_HOOK_EXEC_CC:
2023-03-22 17:45:52 +09:00
{
2020-05-21 22:52:23 -07:00
//
// Check if EPT hook exec (hidden breakpoint and inline hook) parameters are valid
//
if (!ValidateEventEptHookHiddenBreakpointAndInlineHooks(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
//
// Event parameters are not valid, let break the further execution at this stage
//
2020-05-21 22:52:23 -07:00
return FALSE;
}
break;
2023-03-22 17:45:52 +09:00
}
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
case HIDDEN_HOOK_READ_AND_WRITE:
case HIDDEN_HOOK_READ_AND_EXECUTE:
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
case HIDDEN_HOOK_READ:
case HIDDEN_HOOK_WRITE:
case HIDDEN_HOOK_EXECUTE:
2023-03-22 17:45:52 +09:00
{
2020-05-20 11:38:07 -07:00
//
// Check if EPT memory monitor hook parameters are valid
2020-05-20 11:38:07 -07:00
//
if (!ValidateEventMonitor(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
//
// Event parameters are not valid, let break the further execution at this stage
//
2020-05-20 11:38:07 -07:00
return FALSE;
}
break;
}
default:
2020-05-20 11:38:07 -07:00
//
// Other not specified events doesn't have any special validation
2020-05-20 11:38:07 -07:00
//
break;
2020-05-20 11:38:07 -07:00
}
//
// As we reached, all the checks are passed and it means the event is valid
//
return TRUE;
}
/**
* @brief Applying events
*
* @param Event The created event object
* @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_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
//
// Now we should configure the cpu to generate the events
//
switch (Event->EventType)
2023-03-22 17:45:52 +09:00
{
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
case HIDDEN_HOOK_READ_AND_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_EXECUTE:
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
case HIDDEN_HOOK_READ:
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_EXECUTE:
2023-03-22 17:45:52 +09:00
{
2021-08-27 14:59:08 +04:30
//
2023-10-15 15:23:15 +09:00
// Apply the monitor memory hook events
2020-05-20 11:38:07 -07:00
//
2023-10-15 15:23:15 +09:00
if (!ApplyEventMonitorEvent(Event, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
goto ClearTheEventAfterCreatingEvent;
}
break;
}
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_EXEC_CC:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the EPT hidden hook (hidden breakpoint) events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
if (!ApplyEventEptHookExecCcEvent(Event, ResultsToReturn, InputFromVmxRoot))
{
goto ClearTheEventAfterCreatingEvent;
}
break;
}
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_EXEC_DETOURS:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the EPT hook trampoline (inline hook) events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
if (!ApplyEventEpthookInlineEvent(Event, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
goto ClearTheEventAfterCreatingEvent;
}
break;
}
2023-03-22 17:45:52 +09:00
case RDMSR_INSTRUCTION_EXECUTION:
{
2020-06-01 14:17:32 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the RDMSR execution exiting events
2020-06-02 07:20:06 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventRdmsrExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-06-02 07:20:06 -07:00
}
2023-03-22 17:45:52 +09:00
case WRMSR_INSTRUCTION_EXECUTION:
{
2020-06-02 07:20:06 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the WRMSR execution exiting events
2020-06-02 07:20:06 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventWrmsrExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-06-01 14:17:32 -07:00
}
case IN_INSTRUCTION_EXECUTION:
2023-03-22 17:45:52 +09:00
case OUT_INSTRUCTION_EXECUTION:
{
2020-06-13 03:12:44 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the IN/OUT instructions execution exiting events
2020-06-13 03:12:44 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventInOutExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-06-13 03:12:44 -07:00
}
2023-03-22 17:45:52 +09:00
case TSC_INSTRUCTION_EXECUTION:
{
2020-06-02 11:41:37 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the RDTSC/RDTSCP instructions execution exiting events
2020-06-02 11:41:37 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventTscExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case PMC_INSTRUCTION_EXECUTION:
{
2020-06-02 15:17:03 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the RDPMC instruction execution exiting events
2020-06-02 15:17:03 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventRdpmcExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-06-02 15:17:03 -07:00
}
2023-03-22 17:45:52 +09:00
case DEBUG_REGISTERS_ACCESSED:
{
//
2023-10-15 15:23:15 +09:00
// Apply the mov 2 debug register exiting events
//
2023-10-15 15:23:15 +09:00
ApplyEventMov2DebugRegExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case CONTROL_REGISTER_MODIFIED:
{
//
2023-10-15 15:23:15 +09:00
// Apply the control register access exiting events
//
2023-10-15 15:23:15 +09:00
ApplyEventControlRegisterAccessedEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case EXCEPTION_OCCURRED:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the exception events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventExceptionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-06-03 06:59:28 -07:00
}
2023-03-22 17:45:52 +09:00
case EXTERNAL_INTERRUPT_OCCURRED:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the interrupt events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventInterruptEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case SYSCALL_HOOK_EFER_SYSCALL:
{
2020-06-13 22:39:53 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the EFER SYSCALL hook events
2020-06-13 22:39:53 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventEferSyscallHookEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case SYSCALL_HOOK_EFER_SYSRET:
{
2020-06-13 22:39:53 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the EFER SYSRET hook events
2020-06-13 22:39:53 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventEferSysretHookEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
case VMCALL_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the VMCALL instruction interception events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventVmcallExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-08-28 04:03:12 -07:00
}
case TRAP_EXECUTION_MODE_CHANGED:
2023-09-13 19:59:55 +09:00
{
2023-09-18 19:47:13 +09:00
//
2023-11-02 13:48:56 +09:00
// Apply the trap mode change and single instruction trace events
2023-09-13 19:59:55 +09:00
//
if (!ApplyEventTrapModeChangeEvent(Event, ResultsToReturn, InputFromVmxRoot))
{
goto ClearTheEventAfterCreatingEvent;
}
2023-09-14 21:17:44 +09:00
2023-09-13 19:59:55 +09:00
break;
}
2023-03-22 17:45:52 +09:00
case CPUID_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
// Apply the CPUID instruction execution events
2020-08-28 04:03:12 -07:00
//
2023-10-15 15:23:15 +09:00
ApplyEventCpuidExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
2020-08-28 04:03:12 -07:00
}
case TRAP_EXECUTION_INSTRUCTION_TRACE:
{
//
// Apply the tracing events
//
ApplyEventTracingEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2025-08-21 00:17:26 +02:00
case XSETBV_INSTRUCTION_EXECUTION:
{
//
// Apply the XSETBV instruction execution events
//
ApplyEventXsetbvExecutionEvent(Event, ResultsToReturn, InputFromVmxRoot);
break;
}
2023-03-22 17:45:52 +09:00
default:
{
//
// Set the error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
goto ClearTheEventAfterCreatingEvent;
break;
}
}
//
// Set the status
//
ResultsToReturn->IsSuccessful = TRUE;
ResultsToReturn->Error = 0;
//
// Event was applied successfully
//
return TRUE;
ClearTheEventAfterCreatingEvent:
return FALSE;
}
/**
* @brief Routine for parsing events
*
* @param EventDetails The structure that describes event that came
* from the user-mode
* @param ResultsToReturn Result buffer that should be returned to
* the user-mode
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2024-03-17 18:17:38 +09:00
* @return BOOLEAN TRUE if the event was valid and registered without error,
* otherwise returns FALSE
*/
BOOLEAN
DebuggerParseEvent(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
PDEBUGGER_EVENT Event;
//
// ----------------------------------------------------------------------------------
// *** Validating the Event's parameters ***
// ----------------------------------------------------------------------------------
//
//
// Validate the event parameters
//
2023-10-14 21:28:08 +09:00
if (!DebuggerValidateEvent(EventDetails, ResultsToReturn, InputFromVmxRoot))
2023-03-22 17:45:52 +09:00
{
//
// Input event is not valid
//
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,
2023-10-14 21:28:08 +09:00
&EventDetails->Options,
EventDetails->ConditionBufferSize,
2024-03-01 23:20:18 +09:00
(PVOID)((UINT64)EventDetails + sizeof(DEBUGGER_GENERAL_EVENT_DETAIL)),
ResultsToReturn,
InputFromVmxRoot);
}
else
{
//
// Unconditional Event
//
Event = DebuggerCreateEvent(FALSE,
EventDetails->CoreId,
EventDetails->ProcessId,
EventDetails->EventType,
EventDetails->Tag,
2023-10-14 21:28:08 +09:00
&EventDetails->Options,
0,
NULL,
ResultsToReturn,
InputFromVmxRoot);
}
if (Event == NULL)
{
//
// Error is already set in the creation function
//
return FALSE;
}
//
// Register the event
//
DebuggerRegisterEvent(Event);
//
// ----------------------------------------------------------------------------------
// *** Apply & Enable Event ***
// ----------------------------------------------------------------------------------
//
if (DebuggerApplyEvent(Event, ResultsToReturn, InputFromVmxRoot))
{
2023-10-14 21:28:08 +09:00
//
// *** Set the short-circuiting state ***
//
Event->EnableShortCircuiting = EventDetails->EnableShortCircuiting;
//
// Set the event stage (pre- post- event)
//
if (EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION)
{
Event->EventMode = VMM_CALLBACK_CALLING_STAGE_POST_EVENT_EMULATION;
}
else if (EventDetails->EventStage == VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION)
{
Event->EventMode = VMM_CALLBACK_CALLING_STAGE_ALL_EVENT_EMULATION;
}
else
{
//
// Any other value results to be pre-event
//
Event->EventMode = VMM_CALLBACK_CALLING_STAGE_PRE_EVENT_EMULATION;
}
return TRUE;
}
else
{
//
2024-03-17 18:17:38 +09:00
// Remove the event as it was not successful
// The same input as of input from VMX-root is
// selected here because we apply it directly in the
// above function and based on this input we can
// conclude whether the pool is allocated from the
// pool manager or not
//
if (Event != NULL)
{
DebuggerRemoveEvent(Event->Tag, InputFromVmxRoot);
}
return FALSE;
}
}
/**
* @brief Routine for validating and parsing actions that are coming from
2022-06-28 09:52:24 -07:00
* the user-mode
*
* @param ActionDetails Structure that describes the action that comes from the
2020-08-28 04:03:12 -07:00
* user-mode
* @param ResultsToReturn The buffer address that should be returned
2020-08-28 04:03:12 -07:00
* to the user-mode as the result
2023-10-14 21:28:08 +09:00
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN if action was parsed and added successfully, return TRUE
* otherwise, returns FALSE
*/
BOOLEAN
2023-10-17 18:20:21 +09:00
DebuggerParseAction(PDEBUGGER_GENERAL_ACTION ActionDetails,
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
BOOLEAN InputFromVmxRoot)
{
2023-10-17 18:20:21 +09:00
DEBUGGER_EVENT_ACTION * Action = NULL;
//
// Check if Tag is valid or not
//
2023-10-17 18:20:21 +09:00
PDEBUGGER_EVENT Event = DebuggerGetEventByTag(ActionDetails->EventTag);
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_TAG_NOT_EXISTS;
//
// Show that the
//
return FALSE;
}
2023-10-17 18:20:21 +09:00
if (ActionDetails->ActionType == RUN_CUSTOM_CODE)
2023-03-22 17:45:52 +09:00
{
//
// Check if buffer is not invalid
//
2023-10-17 18:20:21 +09:00
if (ActionDetails->CustomCodeBufferSize == 0)
2023-03-22 17:45:52 +09:00
{
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
//
// Show that the
//
return FALSE;
}
2020-10-22 08:14:59 -07:00
//
// Add action for RUN_CUSTOM_CODE
//
2023-03-22 17:45:52 +09:00
DEBUGGER_EVENT_REQUEST_CUSTOM_CODE CustomCode = {0};
2023-10-17 18:20:21 +09:00
CustomCode.CustomCodeBufferSize = ActionDetails->CustomCodeBufferSize;
2024-03-01 15:59:58 +09:00
CustomCode.CustomCodeBufferAddress = (PVOID)((UINT64)ActionDetails + sizeof(DEBUGGER_GENERAL_ACTION));
2023-10-17 18:20:21 +09:00
CustomCode.OptionalRequestedBufferSize = ActionDetails->PreAllocatedBuffer;
//
// Add action to event
//
2023-10-17 18:20:21 +09:00
Action = DebuggerAddActionToEvent(Event,
RUN_CUSTOM_CODE,
ActionDetails->ImmediateMessagePassing,
&CustomCode,
NULL,
ResultsToReturn,
InputFromVmxRoot);
2023-10-17 18:20:21 +09:00
if (!Action)
{
//
// Show that there was an error (error is set by the above function)
//
return FALSE;
}
2023-03-22 17:45:52 +09:00
}
2023-10-17 18:20:21 +09:00
else if (ActionDetails->ActionType == RUN_SCRIPT)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// Check if buffer is not invalid
//
2023-10-17 18:20:21 +09:00
if (ActionDetails->ScriptBufferSize == 0)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_ACTION_BUFFER_SIZE_IS_ZERO;
2020-10-22 08:14:59 -07:00
//
// Show that the
//
return FALSE;
}
//
// Add action for RUN_SCRIPT
//
2023-03-22 17:45:52 +09:00
DEBUGGER_EVENT_ACTION_RUN_SCRIPT_CONFIGURATION UserScriptConfig = {0};
2023-10-17 18:20:21 +09:00
UserScriptConfig.ScriptBuffer = (UINT64)ActionDetails + sizeof(DEBUGGER_GENERAL_ACTION);
UserScriptConfig.ScriptLength = ActionDetails->ScriptBufferSize;
UserScriptConfig.ScriptPointer = ActionDetails->ScriptBufferPointer;
UserScriptConfig.OptionalRequestedBufferSize = ActionDetails->PreAllocatedBuffer;
Action = DebuggerAddActionToEvent(Event,
RUN_SCRIPT,
ActionDetails->ImmediateMessagePassing,
NULL,
&UserScriptConfig,
ResultsToReturn,
InputFromVmxRoot);
if (!Action)
{
//
// Show that there was an error (error is set by the above function)
//
return FALSE;
}
2023-03-22 17:45:52 +09:00
}
2023-10-17 18:20:21 +09:00
else if (ActionDetails->ActionType == BREAK_TO_DEBUGGER)
2023-03-22 17:45:52 +09:00
{
2020-10-22 08:14:59 -07:00
//
// Add action BREAK_TO_DEBUGGER to event
//
2023-10-17 18:20:21 +09:00
Action = DebuggerAddActionToEvent(Event,
BREAK_TO_DEBUGGER,
ActionDetails->ImmediateMessagePassing,
NULL,
NULL,
ResultsToReturn,
InputFromVmxRoot);
2020-10-22 08:14:59 -07:00
2023-10-17 18:20:21 +09:00
if (!Action)
{
//
// Show that there was an error (error is set by the above function)
//
return FALSE;
}
2023-03-22 17:45:52 +09:00
}
else
{
//
// Set the appropriate error
//
ResultsToReturn->IsSuccessful = FALSE;
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ACTION_TYPE;
//
2023-10-17 18:20:21 +09:00
// Show that there was an error
//
return FALSE;
}
2023-10-17 18:20:21 +09:00
//
// Enable the event
//
DebuggerEnableEvent(Event->Tag);
ResultsToReturn->IsSuccessful = TRUE;
ResultsToReturn->Error = 0;
return TRUE;
}
2020-08-28 04:03:12 -07:00
/**
* @brief Terminate one event's effect by its tag
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @details This function won't remove the event from
* the lists of event or de-allocated them, this should
* be called BEFORE the removing function
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param Tag Target event's tag
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN if it was found and terminated without error
* then it returns TRUE, otherwise FALSE
*/
BOOLEAN
DebuggerTerminateEvent(UINT64 Tag, BOOLEAN InputFromVmxRoot)
2020-08-28 04:03:12 -07:00
{
PDEBUGGER_EVENT Event;
2024-03-01 23:20:18 +09:00
BOOLEAN Result = FALSE;
2020-08-28 04:03:12 -07:00
//
// Find the event by its tag
//
Event = DebuggerGetEventByTag(Tag);
2023-03-22 17:45:52 +09:00
if (Event == NULL)
{
2020-08-28 04:03:12 -07:00
//
// event, not found
//
return FALSE;
}
//
// Check the event type of our specific tag
//
2023-03-22 17:45:52 +09:00
switch (Event->EventType)
{
case EXTERNAL_INTERRUPT_OCCURRED:
{
2020-08-28 04:03:12 -07:00
//
// Call external interrupt terminator
//
TerminateExternalInterruptEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
2020-08-28 04:03:12 -07:00
case HIDDEN_HOOK_READ_AND_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_READ_AND_EXECUTE:
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
2020-08-28 04:03:12 -07:00
case HIDDEN_HOOK_READ:
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_WRITE:
2023-07-07 01:21:07 +09:00
case HIDDEN_HOOK_EXECUTE:
2023-03-22 17:45:52 +09:00
{
2020-08-28 04:03:12 -07:00
//
2023-07-07 01:21:07 +09:00
// Call read and write and execute ept hook terminator
2020-08-28 04:03:12 -07:00
//
TerminateHiddenHookReadAndWriteAndExecuteEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_EXEC_CC:
{
2020-08-28 04:03:12 -07:00
//
// Call ept hook (hidden breakpoint) terminator
//
TerminateHiddenHookExecCcEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case HIDDEN_HOOK_EXEC_DETOURS:
{
2020-08-28 04:03:12 -07:00
//
// Call ept hook (hidden inline hook) terminator
//
TerminateHiddenHookExecDetoursEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case RDMSR_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call rdmsr execution event terminator
//
TerminateRdmsrExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case WRMSR_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call wrmsr execution event terminator
//
TerminateWrmsrExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case EXCEPTION_OCCURRED:
{
2020-08-28 04:03:12 -07:00
//
// Call exception events terminator
//
TerminateExceptionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case IN_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call IN instruction execution event terminator
//
TerminateInInstructionExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case OUT_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call OUT instruction execution event terminator
//
TerminateOutInstructionExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case SYSCALL_HOOK_EFER_SYSCALL:
{
2020-08-28 04:03:12 -07:00
//
// Call syscall hook event terminator
//
TerminateSyscallHookEferEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case SYSCALL_HOOK_EFER_SYSRET:
{
2020-08-28 04:03:12 -07:00
//
// Call sysret hook event terminator
//
TerminateSysretHookEferEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case VMCALL_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call vmcall instruction execution event terminator
//
TerminateVmcallExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
case TRAP_EXECUTION_MODE_CHANGED:
2023-09-13 19:59:55 +09:00
{
//
2023-09-18 19:47:13 +09:00
// Call mode execution trap event terminator
2023-09-13 19:59:55 +09:00
//
TerminateExecTrapModeChangedEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2023-09-13 19:59:55 +09:00
break;
}
2023-03-22 17:45:52 +09:00
case TSC_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call rdtsc/rdtscp instruction execution event terminator
//
TerminateTscEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case PMC_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call rdtsc/rdtscp instructions execution event terminator
//
TerminatePmcEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case DEBUG_REGISTERS_ACCESSED:
{
2020-08-28 04:03:12 -07:00
//
// Call mov to debugger register event terminator
//
TerminateDebugRegistersEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case CPUID_INSTRUCTION_EXECUTION:
{
2020-08-28 04:03:12 -07:00
//
// Call cpuid instruction execution event terminator
//
TerminateCpuidExecutionEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
2020-08-28 04:03:12 -07:00
break;
}
2023-03-22 17:45:52 +09:00
case CONTROL_REGISTER_MODIFIED:
{
//
// Call mov to control register event terminator
//
TerminateControlRegistersEvent(Event, InputFromVmxRoot);
2024-03-01 23:20:18 +09:00
Result = TRUE;
break;
}
2025-08-21 00:17:26 +02:00
case XSETBV_INSTRUCTION_EXECUTION:
{
//
// Call XSETBV instruction execution event terminator
//
TerminateXsetbvExecutionEvent(Event, InputFromVmxRoot);
Result = TRUE;
break;
}
2020-08-28 04:03:12 -07:00
default:
2021-08-30 17:23:17 +04:30
LogError("Err, unknown event for termination");
2024-03-01 23:20:18 +09:00
Result = FALSE;
2020-08-28 04:03:12 -07:00
break;
}
2024-03-01 23:20:18 +09:00
//
// Return status
//
return Result;
2020-08-28 04:03:12 -07:00
}
/**
* @brief Parse and validate requests to enable/disable/clear
* from the user-mode
2022-06-28 09:52:24 -07:00
*
2020-08-28 04:03:12 -07:00
* @param DebuggerEventModificationRequest event modification request details
2023-10-14 21:28:08 +09:00
* @param InputFromVmxRoot Whether the input comes from VMX root-mode or IOCTL
* @param PoolManagerAllocatedMemory Whether the pools are allocated from the
* pool manager or original OS pools
2023-10-14 21:28:08 +09:00
*
2020-08-28 04:03:12 -07:00
* @return BOOLEAN returns TRUE if there was no error, and FALSE if there was
* an error
*/
BOOLEAN
2023-10-14 21:28:08 +09:00
DebuggerParseEventsModification(PDEBUGGER_MODIFY_EVENTS DebuggerEventModificationRequest,
BOOLEAN InputFromVmxRoot,
BOOLEAN PoolManagerAllocatedMemory)
2020-08-28 04:03:12 -07:00
{
BOOLEAN IsForAllEvents = FALSE;
//
// Check if the tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (DebuggerEventModificationRequest->Tag == DEBUGGER_MODIFY_EVENTS_APPLY_TO_ALL_TAG)
{
2020-08-28 04:03:12 -07:00
IsForAllEvents = TRUE;
2023-03-22 17:45:52 +09:00
}
else if (!DebuggerIsTagValid(DebuggerEventModificationRequest->Tag))
{
2020-08-28 04:03:12 -07:00
//
// Tag is invalid
//
2020-09-08 13:53:27 -07:00
DebuggerEventModificationRequest->KernelStatus = DEBUGGER_ERROR_MODIFY_EVENTS_INVALID_TAG;
2020-08-28 04:03:12 -07:00
return FALSE;
}
//
// ***************************************************************************
//
//
// Check if it's a ENABLE, DISABLE or CLEAR
//
2023-03-22 17:45:52 +09:00
if (DebuggerEventModificationRequest->TypeOfAction == DEBUGGER_MODIFY_EVENTS_ENABLE)
{
if (IsForAllEvents)
{
2020-08-28 04:03:12 -07:00
//
// Enable all events
//
DebuggerEnableOrDisableAllEvents(TRUE);
2023-03-22 17:45:52 +09:00
}
else
{
2020-08-28 04:03:12 -07:00
//
// Enable just one event
//
DebuggerEnableEvent(DebuggerEventModificationRequest->Tag);
}
2023-03-22 17:45:52 +09:00
}
else if (DebuggerEventModificationRequest->TypeOfAction == DEBUGGER_MODIFY_EVENTS_DISABLE)
{
if (IsForAllEvents)
{
2020-08-28 04:03:12 -07:00
//
// Disable all events
//
DebuggerEnableOrDisableAllEvents(FALSE);
2023-03-22 17:45:52 +09:00
}
else
{
2020-08-28 04:03:12 -07:00
//
// Disable just one event
//
DebuggerDisableEvent(DebuggerEventModificationRequest->Tag);
}
2023-03-22 17:45:52 +09:00
}
else if (DebuggerEventModificationRequest->TypeOfAction == DEBUGGER_MODIFY_EVENTS_CLEAR)
{
if (IsForAllEvents)
{
2020-08-28 04:03:12 -07:00
//
// Clear all events
//
DebuggerClearAllEvents(InputFromVmxRoot, PoolManagerAllocatedMemory);
2023-03-22 17:45:52 +09:00
}
else
{
2020-08-28 04:03:12 -07:00
//
// Clear just one event
//
DebuggerClearEvent(DebuggerEventModificationRequest->Tag, InputFromVmxRoot, PoolManagerAllocatedMemory);
2020-08-28 04:03:12 -07:00
}
2023-03-22 17:45:52 +09:00
}
else if (DebuggerEventModificationRequest->TypeOfAction == DEBUGGER_MODIFY_EVENTS_QUERY_STATE)
{
2021-02-22 12:57:09 -08:00
//
// check if tag is valid or not
//
2023-03-22 17:45:52 +09:00
if (!DebuggerIsTagValid(DebuggerEventModificationRequest->Tag))
{
DebuggerEventModificationRequest->KernelStatus = DEBUGGER_ERROR_TAG_NOT_EXISTS;
2021-02-22 12:57:09 -08:00
return FALSE;
}
//
// Set event state
//
2023-03-22 17:45:52 +09:00
if (DebuggerQueryStateEvent(DebuggerEventModificationRequest->Tag))
{
2021-02-22 12:57:09 -08:00
DebuggerEventModificationRequest->IsEnabled = TRUE;
2023-03-22 17:45:52 +09:00
}
else
{
2021-02-22 12:57:09 -08:00
DebuggerEventModificationRequest->IsEnabled = FALSE;
}
2023-03-22 17:45:52 +09:00
}
else
{
2020-08-28 04:03:12 -07:00
//
2024-03-17 18:17:38 +09:00
// Invalid parameter specified in TypeOfAction
2020-08-28 04:03:12 -07:00
//
2020-09-08 13:53:27 -07:00
DebuggerEventModificationRequest->KernelStatus = DEBUGGER_ERROR_MODIFY_EVENTS_INVALID_TYPE_OF_ACTION;
2020-08-28 04:03:12 -07:00
return FALSE;
}
//
// The function was successful
//
2022-10-06 17:45:07 +09:00
DebuggerEventModificationRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
2020-08-28 04:03:12 -07:00
return TRUE;
}