mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-13 19:19:38 +00:00
1339 lines
39 KiB
C
1339 lines
39 KiB
C
/**
|
|
* @file ApplyEvents.c
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Implementation of debugger functions for applying events
|
|
* @details
|
|
*
|
|
* @version 0.7
|
|
* @date 2023-10-15
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief Applying monitor memory hook 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
|
|
*/
|
|
BOOLEAN
|
|
ApplyEventMonitorEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UINT32 TempProcessId;
|
|
BOOLEAN ResultOfApplyingEvent = FALSE;
|
|
UINT64 RemainingSize;
|
|
UINT64 PagesBytes;
|
|
UINT64 ConstEndAddress;
|
|
UINT64 TempStartAddress;
|
|
UINT64 TempEndAddress;
|
|
UINT64 TempNextPageAddr;
|
|
EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR HookingAddresses = {0};
|
|
|
|
if (InputFromVmxRoot)
|
|
{
|
|
TempProcessId = NULL_ZERO; // Process Id does not make sense in the Debugger Mode
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check if process id is equal to DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES
|
|
// or if process id is 0 then we use the cr3 of current process
|
|
//
|
|
if (Event->ProcessId == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES || Event->ProcessId == 0)
|
|
{
|
|
TempProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
|
|
}
|
|
else
|
|
{
|
|
TempProcessId = Event->ProcessId;
|
|
}
|
|
}
|
|
//
|
|
// In all the cases we should set both read/write, even if it's only
|
|
// read we should set the write too!
|
|
// Also execute bit has the same conditions here, because if write is set
|
|
// read should be also set
|
|
//
|
|
switch (Event->EventType)
|
|
{
|
|
case HIDDEN_HOOK_READ_AND_WRITE_AND_EXECUTE:
|
|
case HIDDEN_HOOK_READ_AND_EXECUTE:
|
|
|
|
HookingAddresses.SetHookForRead = TRUE;
|
|
HookingAddresses.SetHookForWrite = TRUE;
|
|
HookingAddresses.SetHookForExec = TRUE;
|
|
|
|
break;
|
|
|
|
case HIDDEN_HOOK_WRITE_AND_EXECUTE:
|
|
|
|
HookingAddresses.SetHookForRead = FALSE;
|
|
HookingAddresses.SetHookForWrite = TRUE;
|
|
HookingAddresses.SetHookForExec = FALSE;
|
|
|
|
break;
|
|
|
|
case HIDDEN_HOOK_READ_AND_WRITE:
|
|
case HIDDEN_HOOK_READ:
|
|
|
|
HookingAddresses.SetHookForRead = TRUE;
|
|
HookingAddresses.SetHookForWrite = TRUE;
|
|
HookingAddresses.SetHookForExec = FALSE;
|
|
|
|
break;
|
|
|
|
case HIDDEN_HOOK_WRITE:
|
|
|
|
HookingAddresses.SetHookForRead = FALSE;
|
|
HookingAddresses.SetHookForWrite = TRUE;
|
|
HookingAddresses.SetHookForExec = FALSE;
|
|
|
|
break;
|
|
|
|
case HIDDEN_HOOK_EXECUTE:
|
|
|
|
HookingAddresses.SetHookForRead = FALSE;
|
|
HookingAddresses.SetHookForWrite = FALSE;
|
|
HookingAddresses.SetHookForExec = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
LogError("Err, Invalid monitor hook type");
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_EVENT_TYPE_IS_INVALID;
|
|
|
|
goto EventNotApplied;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the tag
|
|
//
|
|
HookingAddresses.Tag = Event->Tag;
|
|
|
|
TempStartAddress = Event->InitOptions.OptionalParam1;
|
|
TempEndAddress = Event->InitOptions.OptionalParam2;
|
|
ConstEndAddress = TempEndAddress;
|
|
|
|
PagesBytes = (UINT64)PAGE_ALIGN(TempStartAddress);
|
|
PagesBytes = TempEndAddress - PagesBytes;
|
|
PagesBytes = PagesBytes / PAGE_SIZE;
|
|
|
|
RemainingSize = TempEndAddress - TempStartAddress;
|
|
|
|
// LogInfo("Start address: %llx, end address: %llx", TempStartAddress, TempEndAddress, RemainingSize);
|
|
|
|
for (SIZE_T i = 0; i <= PagesBytes; i++)
|
|
{
|
|
if (RemainingSize >= PAGE_SIZE)
|
|
{
|
|
TempEndAddress = (TempStartAddress + ((UINT64)PAGE_ALIGN(TempStartAddress + PAGE_SIZE) - TempStartAddress)) - 1;
|
|
RemainingSize = ConstEndAddress - TempEndAddress - 1;
|
|
}
|
|
else
|
|
{
|
|
TempNextPageAddr = (UINT64)PAGE_ALIGN(TempStartAddress + RemainingSize);
|
|
|
|
//
|
|
// Check if by adding the remaining size, we'll go to the next
|
|
// page boundary or not
|
|
//
|
|
if (TempNextPageAddr > ((UINT64)PAGE_ALIGN(TempStartAddress)))
|
|
{
|
|
//
|
|
// It goes to the next page boundary
|
|
//
|
|
TempEndAddress = TempNextPageAddr - 1;
|
|
RemainingSize = RemainingSize - (TempEndAddress - TempStartAddress) - 1;
|
|
}
|
|
else
|
|
{
|
|
TempEndAddress = TempStartAddress + RemainingSize;
|
|
RemainingSize = 0;
|
|
}
|
|
}
|
|
|
|
// LogInfo("Start address: %llx, end address: %llx, remaining size: %llx",
|
|
// TempStartAddress,
|
|
// TempEndAddress,
|
|
// RemainingSize);
|
|
|
|
//
|
|
// Setup hooking addresses
|
|
//
|
|
HookingAddresses.StartAddress = TempStartAddress;
|
|
HookingAddresses.EndAddress = TempEndAddress;
|
|
|
|
if ((DEBUGGER_HOOK_MEMORY_TYPE)Event->InitOptions.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS)
|
|
{
|
|
HookingAddresses.MemoryType = DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS;
|
|
}
|
|
else
|
|
{
|
|
HookingAddresses.MemoryType = DEBUGGER_MEMORY_HOOK_VIRTUAL_ADDRESS;
|
|
}
|
|
|
|
//
|
|
// Apply the hook
|
|
//
|
|
ResultOfApplyingEvent = DebuggerEventEnableMonitorReadWriteExec(&HookingAddresses,
|
|
TempProcessId,
|
|
InputFromVmxRoot);
|
|
|
|
if (!ResultOfApplyingEvent)
|
|
{
|
|
//
|
|
// The event is not applied, won't apply other EPT modifications
|
|
// as we want to remove this event
|
|
//
|
|
|
|
//
|
|
// Now we should restore the previously applied events (if any)
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
//
|
|
// EPT hooking tag is same as event tag, so we can use it to unhook
|
|
//
|
|
TerminateEptHookUnHookAllHooksByHookingTagFromVmxRootAndApplyInvalidation(Event->Tag);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// EPT hooking tag is same as event tag, so we can use it to unhook
|
|
//
|
|
ConfigureEptHookUnHookAllByHookingTag(Event->Tag);
|
|
}
|
|
|
|
//
|
|
// Break from the loop
|
|
//
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We applied the hook and the pre-allocated buffers are used
|
|
// for this hook, as here is a safe PASSIVE_LEVEL we can force
|
|
// the Windows to reallocate some pools for us, thus, if this
|
|
// hook is continued to other pages, we still have pre-allocated
|
|
// buffers ready for our future hooks
|
|
//
|
|
if (!InputFromVmxRoot)
|
|
{
|
|
PoolManagerCheckAndPerformAllocationAndDeallocation();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Swap the temporary start address and temporary end address
|
|
//
|
|
TempStartAddress = TempEndAddress + 1;
|
|
}
|
|
|
|
//
|
|
// If applied directly from VMX root-mode,
|
|
// As the call to hook adjuster was successful, we have to
|
|
// invalidate the TLB of EPT caches for all cores here
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastInvalidateSingleContextAllCores();
|
|
}
|
|
|
|
//
|
|
// Check if address is virtual or physical
|
|
//
|
|
if ((DEBUGGER_HOOK_MEMORY_TYPE)Event->Options.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS)
|
|
{
|
|
//
|
|
// It's a physical address so we just save the addresses without conversion
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam2 = Event->InitOptions.OptionalParam2;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// It's a virtual address, we convert the Event's optional parameters physical address
|
|
// because vm-exit occurs and we have the physical address to compare in the case of
|
|
// hidden hook rw events
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam1);
|
|
Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam2);
|
|
}
|
|
else
|
|
{
|
|
Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam1, TempProcessId);
|
|
Event->Options.OptionalParam2 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam2, TempProcessId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// The initial options are also recorded
|
|
//
|
|
Event->Options.OptionalParam3 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam4 = Event->InitOptions.OptionalParam2;
|
|
Event->Options.OptionalParam5 = Event->InitOptions.OptionalParam3; // This parameter shows whether the address is physical or virtual
|
|
|
|
//
|
|
// Check if we should restore the event if it was not successful
|
|
//
|
|
if (!ResultOfApplyingEvent)
|
|
{
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DebuggerGetLastError();
|
|
|
|
goto EventNotApplied;
|
|
}
|
|
|
|
//
|
|
// Applying event was successful
|
|
//
|
|
return TRUE;
|
|
|
|
EventNotApplied:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying EPT hook execution (hidden breakpoints) 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
|
|
*/
|
|
BOOLEAN
|
|
ApplyEventEptHookExecCcEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UINT32 TempProcessId;
|
|
|
|
if (InputFromVmxRoot)
|
|
{
|
|
//
|
|
// *** apply the hook directly from VMX root-mode ***
|
|
//
|
|
|
|
//
|
|
// First, breakpoints have to be intercepted as the caller to the
|
|
// direct hook function have to broadcast it by its own
|
|
//
|
|
HaltedBroadcastSetExceptionBitmapAllCores(EXCEPTION_VECTOR_BREAKPOINT);
|
|
|
|
//
|
|
// Invoke the hooker
|
|
//
|
|
if (!ConfigureEptHookFromVmxRoot((PVOID)Event->InitOptions.OptionalParam1))
|
|
{
|
|
//
|
|
// There was an error applying this event, so we're setting
|
|
// the event
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DebuggerGetLastError();
|
|
goto EventNotApplied;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// As the call to hook adjuster was successful, we have to
|
|
// invalidate the TLB of EPT caches for all cores here
|
|
//
|
|
HaltedBroadcastInvalidateSingleContextAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// *** apply the hook from VMX non root-mode ***
|
|
//
|
|
|
|
//
|
|
// Check if process id is equal to DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES
|
|
// or if process id is 0 then we use the cr3 of current process
|
|
//
|
|
if (Event->ProcessId == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES || Event->ProcessId == 0)
|
|
{
|
|
TempProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
|
|
}
|
|
else
|
|
{
|
|
TempProcessId = Event->ProcessId;
|
|
}
|
|
|
|
//
|
|
// Invoke the hooker
|
|
//
|
|
if (!ConfigureEptHook((PVOID)Event->InitOptions.OptionalParam1, TempProcessId))
|
|
{
|
|
//
|
|
// There was an error applying this event, so we're setting
|
|
// the event
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DebuggerGetLastError();
|
|
goto EventNotApplied;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We set events OptionalParam1 here to make sure that our event is
|
|
// executed not for all hooks but for this special hook
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
|
|
//
|
|
// Applying event was successful
|
|
//
|
|
return TRUE;
|
|
|
|
EventNotApplied:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying EPT hook trampoline (inline hook) 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
|
|
*/
|
|
BOOLEAN
|
|
ApplyEventEpthookInlineEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UINT32 TempProcessId;
|
|
|
|
if (InputFromVmxRoot)
|
|
{
|
|
//
|
|
// *** apply the hook directly from VMX root-mode ***
|
|
//
|
|
|
|
//
|
|
// We set events OptionalParam1 here to make sure that our event is
|
|
// executed not for all hooks but for this special hook
|
|
// Also, we are sure that this is not null because we checked it before
|
|
//
|
|
Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)Event->InitOptions.OptionalParam1);
|
|
|
|
//
|
|
// Invoke the hooker
|
|
//
|
|
if (!ConfigureEptHook2FromVmxRoot(KeGetCurrentProcessorNumberEx(NULL),
|
|
(PVOID)Event->InitOptions.OptionalParam1,
|
|
NULL))
|
|
{
|
|
//
|
|
// There was an error applying this event, so we're setting
|
|
// the event
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DebuggerGetLastError();
|
|
goto EventNotApplied;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// As the call to hook adjuster was successful, we have to
|
|
// invalidate the TLB of EPT caches for all cores here
|
|
//
|
|
HaltedBroadcastInvalidateSingleContextAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// *** apply the hook from VMX non root-mode ***
|
|
//
|
|
|
|
//
|
|
// Check if process id is equal to DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES
|
|
// or if process id is 0 then we use the cr3 of current process
|
|
//
|
|
if (Event->ProcessId == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES || Event->ProcessId == 0)
|
|
{
|
|
TempProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
|
|
}
|
|
else
|
|
{
|
|
TempProcessId = Event->ProcessId;
|
|
}
|
|
|
|
//
|
|
// We set events OptionalParam1 here to make sure that our event is
|
|
// executed not for all hooks but for this special hook
|
|
// Also, we are sure that this is not null because we checked it before
|
|
//
|
|
Event->Options.OptionalParam1 = VirtualAddressToPhysicalAddressByProcessId((PVOID)Event->InitOptions.OptionalParam1, TempProcessId);
|
|
|
|
//
|
|
// Invoke the hooker
|
|
//
|
|
if (!ConfigureEptHook2(KeGetCurrentProcessorNumberEx(NULL),
|
|
(PVOID)Event->InitOptions.OptionalParam1,
|
|
NULL,
|
|
TempProcessId))
|
|
{
|
|
//
|
|
// There was an error applying this event, so we're setting
|
|
// the event
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DebuggerGetLastError();
|
|
goto EventNotApplied;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Applying event was successful
|
|
//
|
|
return TRUE;
|
|
|
|
EventNotApplied:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying RDMSR execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventRdmsrExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastChangeAllMsrBitmapReadAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandChangeAllMsrBitmapReadAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineChangeAllMsrBitmapReadOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ConfigureChangeMsrBitmapReadOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setting an indicator to MSR
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying WRMSR execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventWrmsrExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastChangeAllMsrBitmapWriteAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandChangeAllMsrBitmapWriteAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineChangeAllMsrBitmapWriteOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ConfigureChangeMsrBitmapWriteOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setting an indicator to MSR
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying IN/OUT instructions execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventInOutExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastChangeAllIoBitmapAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandIoBitmapChangeAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineChangeIoBitmapOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ConfigureChangeIoBitmapOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Setting an indicator to MSR
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying RDTSC/RDTSCP instructions execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventTscExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableRdtscExitingAllCores();
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandEnableRdtscExitingAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableRdtscExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableRdtscExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Applying RDPMC instruction execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventRdpmcExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableRdpmcExitingAllCores();
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandEnableRdpmcExitingAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableRdpmcExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableRdpmcExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Applying mov 2 debug registers 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventMov2DebugRegExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (ResultsToReturn)
|
|
{
|
|
HaltedBroadcastEnableMov2DebugRegsExitingAllCores();
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandEnableMovDebugRegistersExitingAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (ResultsToReturn)
|
|
{
|
|
HaltedRoutineEnableMov2DebugRegsExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableMovToDebugRegistersExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Applying control registers accessed 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventControlRegisterAccessedEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Setting an indicator to CR
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam2 = Event->InitOptions.OptionalParam2;
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableMovToCrExitingAllCores(&Event->Options);
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandEnableMovControlRegisterExitingAllCores(Event);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableMovToCrExitingOnSingleCore(Event->CoreId, &Event->Options);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableMovToControlRegisterExitingOnSingleCore(Event->CoreId, &Event->Options);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Applying exception 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventExceptionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastSetExceptionBitmapAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandSetExceptionBitmapAllCores(Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineSetExceptionBitmapOnSingleCore(Event->CoreId, Event->InitOptions.OptionalParam1);
|
|
}
|
|
else
|
|
{
|
|
ConfigureSetExceptionBitmapOnSingleCore(Event->CoreId, (UINT32)Event->InitOptions.OptionalParam1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the event's target exception
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying interrupt interception 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventInterruptEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableExternalInterruptExitingAllCores();
|
|
}
|
|
else
|
|
{
|
|
ExtensionCommandSetExternalInterruptExitingAllCores();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableExternalInterruptExiting(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureSetExternalInterruptExitingOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the event's target interrupt
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying EFER SYSCALL hook 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventEferSyscallHookEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
DEBUGGER_EVENT_SYSCALL_SYSRET_TYPE SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY;
|
|
|
|
//
|
|
// whether it's a !syscall2 or !sysret2
|
|
//
|
|
if (Event->InitOptions.OptionalParam2 == DEBUGGER_EVENT_SYSCALL_SYSRET_HANDLE_ALL_UD)
|
|
{
|
|
SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_HANDLE_ALL_UD;
|
|
}
|
|
else if (Event->InitOptions.OptionalParam2 == DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY)
|
|
{
|
|
SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Set hook type
|
|
//
|
|
ConfigureSetEferSyscallOrSysretHookType(SyscallHookType);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableEferSyscallHookAllCores();
|
|
}
|
|
else
|
|
{
|
|
DebuggerEventEnableEferOnAllProcessors();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableEferSyscallHookOnSingleCore(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableEferSyscallHookOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the event's target syscall number and save the approach
|
|
// of handling event details
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam2 = SyscallHookType;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying EFER SYSRET hook 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventEferSysretHookEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
|
|
DEBUGGER_EVENT_SYSCALL_SYSRET_TYPE SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY;
|
|
|
|
//
|
|
// whether it's a !syscall2 or !sysret2
|
|
//
|
|
if (Event->InitOptions.OptionalParam2 == DEBUGGER_EVENT_SYSCALL_SYSRET_HANDLE_ALL_UD)
|
|
{
|
|
SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_HANDLE_ALL_UD;
|
|
}
|
|
else if (Event->InitOptions.OptionalParam2 == DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY)
|
|
{
|
|
SyscallHookType = DEBUGGER_EVENT_SYSCALL_SYSRET_SAFE_ACCESS_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Set hook type
|
|
//
|
|
ConfigureSetEferSyscallOrSysretHookType(SyscallHookType);
|
|
|
|
//
|
|
// Let's see if it is for all cores or just one core
|
|
//
|
|
if (Event->CoreId == DEBUGGER_EVENT_APPLY_TO_ALL_CORES)
|
|
{
|
|
//
|
|
// All cores
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedBroadcastEnableEferSyscallHookAllCores();
|
|
}
|
|
else
|
|
{
|
|
DebuggerEventEnableEferOnAllProcessors();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just one core
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
HaltedRoutineEnableEferSyscallHookOnSingleCore(Event->CoreId);
|
|
}
|
|
else
|
|
{
|
|
ConfigureEnableEferSyscallHookOnSingleCore(Event->CoreId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the event's target syscall number and save the approach
|
|
// of handling event details
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam2 = SyscallHookType;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying VMCALL instruction execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventVmcallExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(Event);
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Enable triggering events for VMCALLs. This event doesn't support custom optional
|
|
// parameter(s) because it's unconditional users can use condition(s) to check for
|
|
// their custom optional parameters
|
|
//
|
|
VmFuncSetTriggerEventForVmcalls(TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Applying trap mode change 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
|
|
*/
|
|
BOOLEAN
|
|
ApplyEventTrapModeChangeEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
//
|
|
// Set the event's mode of execution
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
|
|
if (InputFromVmxRoot)
|
|
{
|
|
//
|
|
// The event registration is coming from VMX root-mode, we
|
|
// cannot initialize this event in VMX-root mode, so we need
|
|
// to check whether it's already activated (using the 'preactivate' command)
|
|
// or not and if it's activated then we can just add the current process
|
|
// to the watchlist, otherwise the user needs to preactivate this event
|
|
//
|
|
if (VmFuncQueryModeExecTrap())
|
|
{
|
|
//
|
|
// Add the process to the watching list
|
|
//
|
|
ConfigureExecTrapAddProcessToWatchingList(Event->ProcessId);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The mode exec trap is not initialized
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_THE_MODE_EXEC_TRAP_IS_NOT_INITIALIZED;
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The event registration is coming from VMX non-root mode so we
|
|
// can initialize this mechanism if it's not already initialized
|
|
//
|
|
|
|
//
|
|
// Add the process to the watching list
|
|
//
|
|
ConfigureExecTrapAddProcessToWatchingList(Event->ProcessId);
|
|
|
|
//
|
|
// Enable triggering events for user-mode execution traps. This event doesn't
|
|
// support custom optional parameter(s) because it's unconditional users can
|
|
// use condition(s) to check for their custom optional parameters
|
|
//
|
|
ConfigureInitializeExecTrapOnAllProcessors();
|
|
}
|
|
|
|
//
|
|
// It was successfully applied
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying CPUID instruction execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventCpuidExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(Event);
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Enable triggering events for CPUIDs. This event doesn't support custom optional
|
|
// parameter(s) because it's unconditional users can use condition(s) to check for
|
|
// their custom optional parameters
|
|
//
|
|
VmFuncSetTriggerEventForCpuids(TRUE);
|
|
|
|
//
|
|
// Setting an indicator to CPUID EAX index (if any)
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
Event->Options.OptionalParam2 = Event->InitOptions.OptionalParam2;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying trace 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventTracingEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// This is a dependent-event thus, it will be activated later by
|
|
// another event and nothing needs to be initiated at this stage
|
|
//
|
|
|
|
//
|
|
// Save the type of the trace
|
|
//
|
|
Event->Options.OptionalParam1 = Event->InitOptions.OptionalParam1;
|
|
}
|
|
|
|
/**
|
|
* @brief Applying XSETBV instruction execution 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 VOID
|
|
*/
|
|
VOID
|
|
ApplyEventXsetbvExecutionEvent(PDEBUGGER_EVENT Event,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(Event);
|
|
UNREFERENCED_PARAMETER(ResultsToReturn);
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Enable triggering events for XSETBVs. This event doesn't support custom optional
|
|
// parameter(s) because it's unconditional. Users can use condition(s) to check for
|
|
// their custom optional parameters
|
|
//
|
|
VmFuncSetTriggerEventForXsetbvs(TRUE);
|
|
}
|