HyperDbg/hyperdbg/hyperhv/code/interface/Callback.c
2026-06-09 15:04:20 +02:00

409 lines
9.5 KiB
C

/**
* @file Callback.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief VMM callback interface routines
* @details
*
* @version 0.2
* @date 2023-01-29
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief routines callback to trigger events
* @param EventType
* @param CallingStage
* @param Context
* @param PostEventRequired
* @param Regs
*
* @return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE
*/
VMM_CALLBACK_TRIGGERING_EVENT_STATUS_TYPE
VmmCallbackTriggerEvents(VMM_EVENT_TYPE_ENUM EventType,
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE CallingStage,
PVOID Context,
BOOLEAN * PostEventRequired,
GUEST_REGS * Regs)
{
if (g_Callbacks.VmmCallbackTriggerEvents == NULL)
{
return VMM_CALLBACK_TRIGGERING_EVENT_STATUS_SUCCESSFUL_NO_INITIALIZED;
}
return g_Callbacks.VmmCallbackTriggerEvents(EventType, CallingStage, Context, PostEventRequired, Regs);
}
/**
* @brief routine callback to set last error
* @param LastError
*
* @return VOID
*/
VOID
VmmCallbackSetLastError(UINT32 LastError)
{
if (g_Callbacks.VmmCallbackSetLastError == NULL)
{
//
// Ignore setting the last error
//
return;
}
g_Callbacks.VmmCallbackSetLastError(LastError);
}
/**
* @brief routine callback to handle external VMCALLs
*
* @param CoreId
* @param VmcallNumber
* @param OptionalParam1
* @param OptionalParam2
* @param OptionalParam3
*
* @return BOOLEAN
*/
BOOLEAN
VmmCallbackVmcallHandler(UINT32 CoreId,
UINT64 VmcallNumber,
UINT64 OptionalParam1,
UINT64 OptionalParam2,
UINT64 OptionalParam3)
{
if (g_Callbacks.VmmCallbackVmcallHandler == NULL)
{
//
// Ignore handling external VMCALLs
//
return FALSE;
}
return g_Callbacks.VmmCallbackVmcallHandler(CoreId, VmcallNumber, OptionalParam1, OptionalParam2, OptionalParam3);
}
/**
* @brief routine callback to handle NMI requests
*
* @param CoreId
* @param IsOnVmxNmiHandler
*
* @return VOID
*/
VOID
VmmCallbackNmiBroadcastRequestHandler(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler)
{
if (g_Callbacks.VmmCallbackNmiBroadcastRequestHandler == NULL)
{
//
// ignore it
//
return;
}
g_Callbacks.VmmCallbackNmiBroadcastRequestHandler(CoreId, IsOnVmxNmiHandler);
}
/**
* @brief routine callback to query for termination of protected resources
*
* @param CoreId
* @param ResourceType
* @param Context
* @param PassOver
*
* @return BOOLEAN
*/
BOOLEAN
VmmCallbackQueryTerminateProtectedResource(UINT32 CoreId,
PROTECTED_HV_RESOURCES_TYPE ResourceType,
PVOID Context,
PROTECTED_HV_RESOURCES_PASSING_OVERS PassOver)
{
if (g_Callbacks.VmmCallbackQueryTerminateProtectedResource == NULL)
{
//
// ignore it
//
return FALSE;
}
return g_Callbacks.VmmCallbackQueryTerminateProtectedResource(CoreId, ResourceType, Context, PassOver);
}
/**
* @brief routine callback to restore EPT state
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
VmmCallbackRestoreEptState(UINT32 CoreId)
{
if (g_Callbacks.VmmCallbackRestoreEptState == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.VmmCallbackRestoreEptState(CoreId);
}
/**
* @brief routine callback to handle unhandled EPT violations
* @param CoreId
* @param ViolationQualification
* @param GuestPhysicalAddr
*
* @return BOOLEAN
*/
BOOLEAN
VmmCallbackUnhandledEptViolation(UINT32 CoreId,
UINT64 ViolationQualification,
UINT64 GuestPhysicalAddr)
{
if (g_Callbacks.VmmCallbackCheckUnhandledEptViolations == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.VmmCallbackCheckUnhandledEptViolations(CoreId, ViolationQualification, GuestPhysicalAddr);
}
/**
* @brief routine callback to handle MTF callback
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
VmmCallbackHandleMtfCallback(UINT32 CoreId)
{
if (g_Callbacks.VmmCallbackHandleMtfCallback == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.VmmCallbackHandleMtfCallback(CoreId);
}
/**
* @brief routine callback to check if LBR is supported and get the LBR capacity if supported
*
* @param Capacity
* @param IsArchLbr
*
* @return BOOLEAN
*/
BOOLEAN
HyperTraceCallbackLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr)
{
if (g_Callbacks.HyperTraceCallbackLbrIsSupported == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.HyperTraceCallbackLbrIsSupported(Capacity, IsArchLbr);
}
/**
* @brief routine callback to handle breakpoint exception
*
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
DebuggingCallbackHandleBreakpointException(UINT32 CoreId)
{
if (g_Callbacks.DebuggingCallbackHandleBreakpointException == NULL)
{
//
// re-inject it to not disrupt system normal execution
//
return FALSE;
}
return g_Callbacks.DebuggingCallbackHandleBreakpointException(CoreId);
}
/**
* @brief routine callback to handle debug breakpoint exception
*
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
DebuggingCallbackHandleDebugBreakpointException(UINT32 CoreId)
{
if (g_Callbacks.DebuggingCallbackHandleDebugBreakpointException == NULL)
{
//
// re-inject it to not disrupt system normal execution
//
return FALSE;
}
return g_Callbacks.DebuggingCallbackHandleDebugBreakpointException(CoreId);
}
/**
* @brief routine callback to handle thread interception
*
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
DebuggingCallbackCheckThreadInterception(UINT32 CoreId)
{
if (g_Callbacks.DebuggingCallbackCheckThreadInterception == NULL)
{
//
// not handled by user debugger
//
return FALSE;
}
return g_Callbacks.DebuggingCallbackCheckThreadInterception(CoreId);
}
/**
* @brief routine callback to trigger on clock and IPI events for checking process or thread change
*
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
DebuggingCallbackTriggerOnClockAndIpiEvents(UINT32 CoreId)
{
if (g_Callbacks.DebuggingCallbackTriggerOnClockAndIpiEvents == NULL)
{
//
// not handled by user debugger
//
return FALSE;
}
return g_Callbacks.DebuggingCallbackTriggerOnClockAndIpiEvents(CoreId);
}
/**
* @brief routine callback to ignore handling mov 2 debug registers
* @param CoreId
*
* @return BOOLEAN
*/
BOOLEAN
DebuggingCallbackIgnoreHandlingMov2DebugRegs(UINT32 CoreId)
{
if (g_Callbacks.DebuggingCallbackIgnoreHandlingMov2DebugRegs == NULL)
{
//
// not handled by user debugger
//
return FALSE;
}
return g_Callbacks.DebuggingCallbackIgnoreHandlingMov2DebugRegs(CoreId);
}
/**
* @brief routine callback to request pool allocation
*
* @param Size
* @param Count
* @param Intention The intention of the buffer (buffer tag)
*
* @return BOOLEAN
*/
BOOLEAN
PoolManagerCallbackRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
{
if (g_Callbacks.PoolManagerCallbackRequestAllocation == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.PoolManagerCallbackRequestAllocation(Size, Count, Intention);
}
/**
* @brief routine callback to request pool
*
* @param Intention The intention why we need this pool for (buffer tag)
* @param RequestNewPool Create a request to allocate a new pool with the same size, next time
* that it's safe to allocate (this way we never ran out of pools for this "Intention")
* @param Size If the RequestNewPool is true the we should specify a size for the new pool
*
* @return UINT64 Returns a pool address or returns null if there was an error
*/
UINT64
PoolManagerCallbackRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size)
{
if (g_Callbacks.PoolManagerCallbackRequestPool == NULL)
{
//
// ignore it as it's not handled
//
return 0;
}
return g_Callbacks.PoolManagerCallbackRequestPool(Intention, RequestNewPool, Size);
}
/**
* @brief routine callback to free pool
*
* @param AddressToFree
*
* @return BOOLEAN
*/
BOOLEAN
PoolManagerCallbackFreePool(UINT64 AddressToFree)
{
if (g_Callbacks.PoolManagerCallbackFreePool == NULL)
{
//
// ignore it as it's not handled
//
return FALSE;
}
return g_Callbacks.PoolManagerCallbackFreePool(AddressToFree);
}
/**
* @brief routine callback to handle cr3 process change
*
* @param CoreId
*
* @return VOID
*/
VOID
InterceptionCallbackTriggerCr3ProcessChange(UINT32 CoreId)
{
if (g_Callbacks.InterceptionCallbackTriggerCr3ProcessChange == NULL)
{
//
// ignore it
//
return;
}
g_Callbacks.InterceptionCallbackTriggerCr3ProcessChange(CoreId);
}