mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
315 lines
9.8 KiB
C
315 lines
9.8 KiB
C
/**
|
|
* @file ValidateEvents.c
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Implementation of debugger functions for validating events
|
|
* @details
|
|
*
|
|
* @version 0.7
|
|
* @date 2023-10-15
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief Validating 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
|
|
ValidateEventMonitor(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UINT32 TempPid;
|
|
|
|
//
|
|
// First check if the address are valid
|
|
//
|
|
TempPid = EventDetails->ProcessId;
|
|
if (TempPid == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES)
|
|
{
|
|
TempPid = HANDLE_TO_UINT32(PsGetCurrentProcessId());
|
|
}
|
|
|
|
//
|
|
// Check if input is coming from VMX-root or not
|
|
// If it's coming from VMX-root, then as switching
|
|
// to another process is not possible, we'll return
|
|
// an error
|
|
//
|
|
if (InputFromVmxRoot && TempPid != HANDLE_TO_UINT32(PsGetCurrentProcessId()))
|
|
{
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check whether address is valid or not based on whether the event needs
|
|
// to be applied directly from VMX-root mode or not
|
|
//
|
|
if ((DEBUGGER_HOOK_MEMORY_TYPE)EventDetails->Options.OptionalParam3 == DEBUGGER_MEMORY_HOOK_PHYSICAL_ADDRESS)
|
|
{
|
|
//
|
|
// Validation of a physical address
|
|
//
|
|
if (CheckAddressPhysical(EventDetails->Options.OptionalParam1) == FALSE ||
|
|
CheckAddressPhysical(EventDetails->Options.OptionalParam2) == FALSE)
|
|
{
|
|
//
|
|
// Physical address is invalid (Set the error)
|
|
//
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Validation of a virtual address
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
if (VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam1) == (UINT64)NULL ||
|
|
VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam2) == (UINT64)NULL)
|
|
{
|
|
//
|
|
// Virtual address is invalid (Set the error)
|
|
//
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam1, TempPid) == (UINT64)NULL ||
|
|
VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam2, TempPid) == (UINT64)NULL)
|
|
{
|
|
//
|
|
// Address is invalid (Set the error)
|
|
//
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if the 'to' is greater that 'from'
|
|
//
|
|
if (EventDetails->Options.OptionalParam1 >= EventDetails->Options.OptionalParam2)
|
|
{
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The event parameters are valid at this stage
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Validating 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 BOOLEAN
|
|
*/
|
|
BOOLEAN
|
|
ValidateEventException(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Check if the exception entry doesn't exceed the first 32 entry (start from zero)
|
|
//
|
|
if (EventDetails->Options.OptionalParam1 != DEBUGGER_EVENT_EXCEPTIONS_ALL_FIRST_32_ENTRIES && EventDetails->Options.OptionalParam1 >= 31)
|
|
{
|
|
//
|
|
// We don't support entries other than first 32 IDT indexes,
|
|
// it is because we use exception bitmaps and in order to support
|
|
// more than 32 indexes we should use pin-based external interrupt
|
|
// exiting which is completely different
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_EXCEPTION_INDEX_EXCEED_FIRST_32_ENTRIES;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The event parameters are valid at this stage
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Validating interrupt 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
|
|
ValidateEventInterrupt(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Check if the exception entry is between 32 to 255
|
|
//
|
|
if (!(EventDetails->Options.OptionalParam1 >= 32 && EventDetails->Options.OptionalParam1 <= 0xff))
|
|
{
|
|
//
|
|
// The IDT Entry is either invalid or is not in the range
|
|
// of the pin-based external interrupt exiting controls
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INTERRUPT_INDEX_IS_NOT_VALID;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The event parameters are valid at this stage
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Validating trap exec 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
|
|
ValidateEventTrapExec(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UNREFERENCED_PARAMETER(InputFromVmxRoot);
|
|
|
|
//
|
|
// Check if the execution mode is valid or not
|
|
//
|
|
if (EventDetails->Options.OptionalParam1 != DEBUGGER_EVENT_MODE_TYPE_USER_MODE &&
|
|
EventDetails->Options.OptionalParam1 != DEBUGGER_EVENT_MODE_TYPE_KERNEL_MODE &&
|
|
EventDetails->Options.OptionalParam1 != DEBUGGER_EVENT_MODE_TYPE_USER_MODE_AND_KERNEL_MODE)
|
|
{
|
|
//
|
|
// The execution mode is not correctly applied
|
|
//
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_MODE_EXECUTION_IS_INVALID;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The event parameters are valid at this stage
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Validating EPT hook exec (hidden breakpoint and 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
|
|
ValidateEventEptHookHiddenBreakpointAndInlineHooks(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails,
|
|
PDEBUGGER_EVENT_AND_ACTION_RESULT ResultsToReturn,
|
|
BOOLEAN InputFromVmxRoot)
|
|
{
|
|
UINT32 TempPid;
|
|
|
|
//
|
|
// First check if the address are valid
|
|
//
|
|
TempPid = EventDetails->ProcessId;
|
|
|
|
if (TempPid == DEBUGGER_EVENT_APPLY_TO_ALL_PROCESSES)
|
|
{
|
|
TempPid = HANDLE_TO_UINT32(PsGetCurrentProcessId());
|
|
}
|
|
|
|
//
|
|
// Check if input is coming from VMX-root or not
|
|
// If it's coming from VMX-root, then as switching
|
|
// to another process is not possible, we'll return
|
|
// an error
|
|
//
|
|
if (InputFromVmxRoot && TempPid != HANDLE_TO_UINT32(PsGetCurrentProcessId()))
|
|
{
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_PROCESS_ID_CANNOT_BE_SPECIFIED_WHILE_APPLYING_EVENT_FROM_VMX_ROOT_MODE;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check whether address is valid or not based on whether the event needs
|
|
// to be applied directly from VMX-root mode or not
|
|
//
|
|
if (InputFromVmxRoot)
|
|
{
|
|
if (VirtualAddressToPhysicalAddressOnTargetProcess((PVOID)EventDetails->Options.OptionalParam1) == (UINT64)NULL)
|
|
{
|
|
//
|
|
// Address is invalid (Set the error)
|
|
//
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (VirtualAddressToPhysicalAddressByProcessId((PVOID)EventDetails->Options.OptionalParam1, TempPid) == (UINT64)NULL)
|
|
{
|
|
//
|
|
// Address is invalid (Set the error)
|
|
//
|
|
|
|
ResultsToReturn->IsSuccessful = FALSE;
|
|
ResultsToReturn->Error = DEBUGGER_ERROR_INVALID_ADDRESS;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The event parameters are valid at this stage
|
|
//
|
|
return TRUE;
|
|
}
|