add pre and post event concepts for cpuid, rdtsc and rdtscp, syscall, and sysret commnads

This commit is contained in:
unknown 2022-09-22 13:19:37 +09:00
parent b8a2aa5ccc
commit afb16b55a8
14 changed files with 497 additions and 221 deletions

View file

@ -10,6 +10,7 @@ The second (2nd) of the HyperDbg Debugger.
### Added
- HyperDbg Software Development Kit (DK) is now available
- **flush()** function in script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/events/flush))
- **memcpy()** function in script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/memory/memcpy))
- **!crwrite** - Control Register Modification Event ([link](https://docs.hyperdbg.org/commands/extension-commands/crwrite))
### Changed

View file

@ -701,13 +701,20 @@ DebuggerRegisterEvent(PDEBUGGER_EVENT Event)
* @brief Trigger events of a special type to be managed by debugger
*
* @param EventType Type of events
* @param CallingStage Stage of calling (pre-event or post-event)
* @param Regs Guest registers
* @param Context An optional parameter (different in each event)
* @param PostEventRequired Whether the caller is requested to
* trigger a post-event event
* @return DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE returns the staus
* of handling events
*/
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE
DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOID Context)
DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType,
DEBUGGER_EVENT_CALLING_STAGE_TYPE CallingStage,
PGUEST_REGS Regs,
PVOID Context,
BOOLEAN * PostEventRequired)
{
DebuggerCheckForCondition * ConditionFunc;
PLIST_ENTRY TempList = 0;
@ -831,7 +838,7 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
{
TempList = &g_Events->ControlRegisterModifiedEventsHead;
TempList2 = TempList;
break;
break;
}
case EXTERNAL_INTERRUPT_OCCURRED:
{
@ -895,6 +902,7 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
switch (CurrentEvent->EventType)
{
case EXTERNAL_INTERRUPT_OCCURRED:
//
// For external interrupt exiting events we check whether the
// vector match the event's vector or not
@ -908,11 +916,13 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
//
continue;
}
break;
case HIDDEN_HOOK_READ_AND_WRITE:
case HIDDEN_HOOK_READ:
case HIDDEN_HOOK_WRITE:
//
// For hidden hook read/writes we check whether the address
// is in the range of what user specified or not, this is because
@ -998,6 +1008,7 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
case RDMSR_INSTRUCTION_EXECUTION:
case WRMSR_INSTRUCTION_EXECUTION:
//
// check if MSR exit is what we want or not
//
@ -1008,9 +1019,11 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
//
continue;
}
break;
case EXCEPTION_OCCURRED:
//
// check if exception is what we need or not
//
@ -1021,10 +1034,12 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
//
continue;
}
break;
case IN_INSTRUCTION_EXECUTION:
case OUT_INSTRUCTION_EXECUTION:
//
// check if I/O port is what we want or not
//
@ -1035,6 +1050,7 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
//
continue;
}
break;
case SYSCALL_HOOK_EFER_SYSCALL:
@ -1044,6 +1060,7 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
//
// 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
//
//
// check syscall number
@ -1059,27 +1076,53 @@ DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOI
break;
case CONTROL_REGISTER_MODIFIED:
//
//
// check if CR exit is what we want or not
//
if (CurrentEvent->OptionalParam1 != Context)
{
//
//
// The CR is not what we want
//
continue;
}
break;
default:
break;
}
//
// Check the stage of calling (pre and post event)
//
if (CallingStage == DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION &&
CurrentEvent->CallingStage == DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION)
{
//
// Here it means that the current event is a post-event event and
// the current stage of calling is for the pre-event events, thus
// this event is not supposed to be runned 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;
continue;
}
//
// Check if condtion is met or not , if the condition
// is not met then we have to avoid performing the actions
//
if (CurrentEvent->ConditionsBufferSize != 0)
{
//
@ -2506,11 +2549,11 @@ DebuggerParseEventFromUsermode(PDEBUGGER_GENERAL_EVENT_DETAIL EventDetails, UINT
//
//
// Setting an indicator to CR
//
// Setting an indicator to CR
//
Event->OptionalParam1 = EventDetails->OptionalParam1;
Event->OptionalParam2 = EventDetails->OptionalParam2;
//
// Let's see if it is for all cores or just one core
//

View file

@ -0,0 +1,236 @@
/**
* @file Dispatch.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Implementation of debugger functions for dispatching, triggering and
* emulating events
* @details
*
* @version 0.1
* @date 2022-09-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
/**
* @brief Handling debugger functions related to SYSRET events
*
* @param CoreIndex Current core's index
* @param Regs Guest's gp register
* @param Context Context of triggering the event
* @return VOID
*/
VOID
DispatchEventEferSysret(UINT32 CoreIndex, PGUEST_REGS Regs, PVOID Context)
{
BOOLEAN PostEventTriggerReq = FALSE;
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult;
VIRTUAL_MACHINE_STATE * CurrentVmState = &g_GuestState[CoreIndex];
//
// We should trigger the event of SYSRET here
//
EventTriggerResult = DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSRET,
DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION,
Regs,
Context,
&PostEventTriggerReq);
//
// Check whether we need to ignore event emulation or not
//
if (EventTriggerResult != DEBUGGER_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT)
{
SyscallHookEmulateSYSRET(Regs);
CurrentVmState->IncrementRip = FALSE;
}
//
// Check for the post-event triggering needs
//
if (PostEventTriggerReq)
{
DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSRET,
DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION,
Regs,
Context,
NULL);
}
}
/**
* @brief Handling debugger functions related to SYSCALL events
*
* @param CoreIndex Current core's index
* @param Regs Guest's gp register
* @param Context Context of triggering the event
* @return VOID
*/
VOID
DispatchEventEferSyscall(UINT32 CoreIndex, PGUEST_REGS Regs, PVOID Context)
{
BOOLEAN PostEventTriggerReq = FALSE;
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult;
VIRTUAL_MACHINE_STATE * CurrentVmState = &g_GuestState[CoreIndex];
//
// We should trigger the event of SYSCALL here, we send the
// syscall number in rax
//
EventTriggerResult = DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSCALL,
DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION,
Regs,
Regs->rax,
&PostEventTriggerReq);
//
// Check whether we need to ignore event emulation or not
//
if (EventTriggerResult != DEBUGGER_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT)
{
SyscallHookEmulateSYSCALL(Regs);
CurrentVmState->IncrementRip = FALSE;
}
//
// Check for the post-event triggering needs
//
if (PostEventTriggerReq)
{
DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSCALL,
DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION,
Regs,
Regs->rax,
NULL);
}
}
/**
* @brief Handling debugger functions related to CPUID events
*
* @param Regs Guest's gp register
* @return VOID
*/
VOID
DispatchEventCpuid(PGUEST_REGS Regs)
{
UINT64 Context;
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult;
BOOLEAN PostEventTriggerReq = FALSE;
//
// Check if attaching is for command dispatching in user debugger
// or a regular CPUID
//
if (g_UserDebuggerState && UdCheckForCommand())
{
//
// It's a thread command for user debugger, no need to run the
// actual CPUID instruction and change the registers
//
return;
}
//
// As the context to event trigger, we send the eax before the cpuid
// so that the debugger can both read the eax as it's now changed by
// the cpuid instruction and also can modify the results
//
if (g_TriggerEventForCpuids)
{
//
// Adjusting the core context (save eax for the debugger)
//
Context = Regs->rax;
//
// Triggering the pre-event
//
EventTriggerResult = DebuggerTriggerEvents(CPUID_INSTRUCTION_EXECUTION,
DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION,
Regs,
Context,
&PostEventTriggerReq);
//
// Check whether we need to ignore event emulation or not
//
if (EventTriggerResult != DEBUGGER_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT)
{
//
// Handle the CPUID event in the case of triggering event
//
HvHandleCpuid(Regs);
}
//
// Check for the post-event triggering needs
//
if (PostEventTriggerReq)
{
DebuggerTriggerEvents(CPUID_INSTRUCTION_EXECUTION,
DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION,
Regs,
Context,
NULL);
}
}
else
{
//
// Otherwise and if there is no event, we should handle the CPUID
// normally
//
HvHandleCpuid(Regs);
}
}
/**
* @brief Handling debugger functions related to RDTSC/RDTSCP events
*
* @param Regs Guest's gp register
* @param ShouldEmulateTsc Whether or not the debugger is allowed to
* emulate RDTSC/RDTSCP
* @return VOID
*/
VOID
DispatchEventTsc(PGUEST_REGS Regs, BOOLEAN IsRdtscp)
{
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE EventTriggerResult;
BOOLEAN PostEventTriggerReq = FALSE;
//
// As the context to event trigger, we send the false which means
// it's an rdtsc (for rdtscp we set Context to true)
// Note : Using !tsc command in transparent-mode is not allowed
//
EventTriggerResult = DebuggerTriggerEvents(TSC_INSTRUCTION_EXECUTION,
DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION,
Regs,
IsRdtscp,
&PostEventTriggerReq);
//
// Check whether we need to ignore event emulation or not
//
if (EventTriggerResult != DEBUGGER_TRIGGERING_EVENT_STATUS_SUCCESSFUL_IGNORE_EVENT)
{
//
// Handle rdtsc (emulate rdtsc/p)
//
CounterEmulateRdtsc(Regs);
}
//
// Check for the post-event triggering needs
//
if (PostEventTriggerReq)
{
DebuggerTriggerEvents(TSC_INSTRUCTION_EXECUTION,
DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION,
Regs,
IsRdtscp,
NULL);
}
}

View file

@ -1,22 +1,22 @@
/**
* @file Termination.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Implementation of Debugger functions for terminating events
* @brief Implementation of debugger functions for terminating events
* @details
*
*
* @version 0.1
* @date 2020-08-16
*
*
* @copyright This project is released under the GNU Public License v3.
*
*
*/
#include "pch.h"
/**
* @brief Termination function for external-interrupts
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateExternalInterruptEvent(PDEBUGGER_EVENT Event)
@ -93,9 +93,9 @@ TerminateExternalInterruptEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for hidden hook read/write
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateHiddenHookReadAndWriteEvent(PDEBUGGER_EVENT Event)
@ -126,9 +126,9 @@ TerminateHiddenHookReadAndWriteEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for hidden hook (hidden breakpoints)
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateHiddenHookExecCcEvent(PDEBUGGER_EVENT Event)
@ -152,9 +152,9 @@ TerminateHiddenHookExecCcEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for hidden hook (detours)
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateHiddenHookExecDetoursEvent(PDEBUGGER_EVENT Event)
@ -180,9 +180,9 @@ TerminateHiddenHookExecDetoursEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for msr read events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateRdmsrExecutionEvent(PDEBUGGER_EVENT Event)
@ -259,9 +259,9 @@ TerminateRdmsrExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for msr write events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateWrmsrExecutionEvent(PDEBUGGER_EVENT Event)
@ -338,9 +338,9 @@ TerminateWrmsrExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for exception events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateExceptionEvent(PDEBUGGER_EVENT Event)
@ -418,9 +418,9 @@ TerminateExceptionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for IN instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateInInstructionExecutionEvent(PDEBUGGER_EVENT Event)
@ -504,9 +504,9 @@ TerminateInInstructionExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for OUT Instructions events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateOutInstructionExecutionEvent(PDEBUGGER_EVENT Event)
@ -590,9 +590,9 @@ TerminateOutInstructionExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for VMCALL Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateVmcallExecutionEvent(PDEBUGGER_EVENT Event)
@ -628,9 +628,9 @@ TerminateVmcallExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for CPUID Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateCpuidExecutionEvent(PDEBUGGER_EVENT Event)
@ -666,9 +666,9 @@ TerminateCpuidExecutionEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for RDTSC/RDTSCP Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateTscEvent(PDEBUGGER_EVENT Event)
@ -745,9 +745,9 @@ TerminateTscEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for RDPMC Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminatePmcEvent(PDEBUGGER_EVENT Event)
@ -903,9 +903,9 @@ TerminateControlRegistersEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for MOV to debug registers events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateDebugRegistersEvent(PDEBUGGER_EVENT Event)
@ -982,9 +982,9 @@ TerminateDebugRegistersEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for SYSCALL Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateSyscallHookEferEvent(PDEBUGGER_EVENT Event)
@ -1068,9 +1068,9 @@ TerminateSyscallHookEferEvent(PDEBUGGER_EVENT Event)
/**
* @brief Termination function for SYSRET Instruction events
*
*
* @param Event Target Event Object
* @return VOID
* @return VOID
*/
VOID
TerminateSysretHookEferEvent(PDEBUGGER_EVENT Event)

View file

@ -4,27 +4,27 @@
* @brief Implenetation of the fucntions related to the EFER Syscall Hook
* @details This is derived by the method demonstrated at
* - https://revers.engineering/syscall-hooking-via-extended-feature-enable-register-efer/
*
*
* also some of the functions derived from hvpp
* - https://github.com/wbenny/hvpp
*
*
* @version 0.1
* @date 2020-04-10
*
*
* @copyright This project is released under the GNU Public License v3.
*
*
*/
#include "pch.h"
/**
* @brief This function enables or disables EFER syscall hoo
* @details This function should be called for the first time
* that we want to enable EFER hook because after calling this
* that we want to enable EFER hook because after calling this
* function EFER MSR is loaded from GUEST_EFER instead of loading
* from the regular EFER MSR.
*
*
* @param EnableEFERSyscallHook Determines whether we want to enable syscall hook or disable syscall hook
* @return VOID
* @return VOID
*/
VOID
SyscallHookConfigureEFER(BOOLEAN EnableEFERSyscallHook)
@ -104,8 +104,8 @@ SyscallHookConfigureEFER(BOOLEAN EnableEFERSyscallHook)
}
/**
* @brief This function emulates the SYSCALL execution
*
* @brief This function emulates the SYSCALL execution
*
* @param Regs Guest registers
* @return BOOLEAN
*/
@ -171,8 +171,8 @@ SyscallHookEmulateSYSCALL(PGUEST_REGS Regs)
}
/**
* @brief This function emulates the SYSRET execution
*
* @brief This function emulates the SYSRET execution
*
* @param Regs Guest registers
* @return BOOLEAN
*/
@ -218,7 +218,7 @@ SyscallHookEmulateSYSRET(PGUEST_REGS Regs)
/**
* @brief Detect whether the #UD was because of Syscall or Sysret or not
*
*
* @param Regs Guest register
* @param CoreIndex Logical core index
* @return BOOLEAN Shows whther the caller should inject #UD on the guest or not
@ -230,7 +230,6 @@ SyscallHookHandleUD(PGUEST_REGS Regs, UINT32 CoreIndex)
CR3_TYPE GuestCr3;
UINT64 OriginalCr3;
UINT64 Rip;
BOOLEAN Result;
VIRTUAL_MACHINE_STATE * CurrentVmState = &g_GuestState[CoreIndex];
//
@ -339,6 +338,7 @@ SyscallHookHandleUD(PGUEST_REGS Regs, UINT32 CoreIndex)
// Emulate SYSRET instruction
//
EmulateSYSRET:
//
// Test
//
@ -346,13 +346,11 @@ EmulateSYSRET:
//
//
// We should trigger the event of SYSRET here
// Perform the dispatching and the emulation of the SYSRET event
//
DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSRET, Regs, Rip);
DispatchEventEferSysret(CoreIndex, Regs, Rip);
Result = SyscallHookEmulateSYSRET(Regs);
CurrentVmState->IncrementRip = FALSE;
return Result;
return TRUE;
//
// Emulate SYSCALL instruction
@ -367,13 +365,9 @@ EmulateSYSCALL:
//
//
// We should trigger the event of SYSCALL here, we send the
// syscall number in rax
// Perform the dispatching and the emulation of the SYSCAKK event
//
DebuggerTriggerEvents(SYSCALL_HOOK_EFER_SYSCALL, Regs, Regs->rax);
DispatchEventEferSyscall(CoreIndex, Regs, Rip);
Result = SyscallHookEmulateSYSCALL(Regs);
CurrentVmState->IncrementRip = FALSE;
return Result;
return TRUE;
}

View file

@ -5,17 +5,17 @@
* @details vmx related routines
* @version 0.1
* @date 2020-04-11
*
*
* @copyright This project is released under the GNU Public License v3.
*
*
*/
#include "pch.h"
/**
* @brief Adjust controls for VMCS based on processor capability
*
* @param Ctl
* @param Msr
*
* @param Ctl
* @param Msr
* @return ULONG Returns the Cpu Based and Secondary Processor Based Controls
* and other controls based on hardware support
*/
@ -32,11 +32,11 @@ HvAdjustControls(ULONG Ctl, ULONG Msr)
/**
* @brief Set guest's selector registers
*
* @param GdtBase
* @param SegmentRegister
* @param Selector
* @return BOOLEAN
*
* @param GdtBase
* @param SegmentRegister
* @param Selector
* @return BOOLEAN
*/
BOOLEAN
HvSetGuestSelector(PVOID GdtBase, ULONG SegmentRegister, UINT16 Selector)
@ -59,34 +59,15 @@ HvSetGuestSelector(PVOID GdtBase, ULONG SegmentRegister, UINT16 Selector)
/**
* @brief Handle Cpuid Vmexits
*
*
* @param RegistersState Guest's gp registers
* @return VOID
* @return VOID
*/
VOID
HvHandleCpuid(PGUEST_REGS RegistersState)
{
INT32 CpuInfo[4];
ULONG Mode = 0;
UINT64 Context = 0;
//
// Check if attaching is for command dispatching in user debugger
// or a regular CPUID
//
if (g_UserDebuggerState && UdCheckForCommand())
{
//
// It's a thread command for user debugger, no need to run the
// actual CPUID instruction and change the registers
//
return;
}
//
// Set the context (save eax for the debugger)
//
Context = RegistersState->rax;
INT32 CpuInfo[4];
ULONG Mode = 0;
//
// Otherwise, issue the CPUID to the logical processor based on the indexes
@ -112,7 +93,6 @@ HvHandleCpuid(PGUEST_REGS RegistersState)
//
CpuInfo[2] |= HYPERV_HYPERVISOR_PRESENT_BIT;
}
/*
else if (RegistersState->rax == CPUID_HV_VENDOR_AND_MAX_FUNCTIONS)
{
//
@ -135,7 +115,6 @@ HvHandleCpuid(PGUEST_REGS RegistersState)
CpuInfo[0] = '0#vH'; // Hv#0
CpuInfo[1] = CpuInfo[2] = CpuInfo[3] = 0;
}
*/
}
//
@ -145,24 +124,14 @@ HvHandleCpuid(PGUEST_REGS RegistersState)
RegistersState->rbx = CpuInfo[1];
RegistersState->rcx = CpuInfo[2];
RegistersState->rdx = CpuInfo[3];
//
// As the context to event trigger, we send the eax before the cpuid
// so that the debugger can both read the eax as it's now changed by
// the cpuid instruction and also can modify the results
//
if (g_TriggerEventForCpuids)
{
DebuggerTriggerEvents(CPUID_INSTRUCTION_EXECUTION, RegistersState, Context);
}
}
/**
* @brief Handles Guest Access to control registers
*
*
* @param GuestState Guest's gp registers
* @param ProcessorIndex Index of processor
* @return VOID
* @return VOID
*/
VOID
HvHandleControlRegisterAccess(PGUEST_REGS GuestState, UINT32 ProcessorIndex)
@ -189,7 +158,7 @@ HvHandleControlRegisterAccess(PGUEST_REGS GuestState, UINT32 ProcessorIndex)
// We handled it in vm-exit handler, commented
//
/*
/*
if (CrExitQualification->Fields.Register == 4)
{
__vmx_vmread(VMCS_GUEST_RSP, &GuestRsp);
@ -204,9 +173,12 @@ HvHandleControlRegisterAccess(PGUEST_REGS GuestState, UINT32 ProcessorIndex)
switch (CrExitQualification->ControlRegister)
{
case VMX_EXIT_QUALIFICATION_REGISTER_CR0:
__vmx_vmwrite(VMCS_GUEST_CR0, *RegPtr);
__vmx_vmwrite(VMCS_CTRL_CR0_READ_SHADOW, *RegPtr);
DebuggerTriggerEvents(CONTROL_REGISTER_MODIFIED, GuestState, VMX_EXIT_QUALIFICATION_REGISTER_CR0);
break;
case VMX_EXIT_QUALIFICATION_REGISTER_CR3:
@ -243,9 +215,12 @@ HvHandleControlRegisterAccess(PGUEST_REGS GuestState, UINT32 ProcessorIndex)
break;
case VMX_EXIT_QUALIFICATION_REGISTER_CR4:
__vmx_vmwrite(VMCS_GUEST_CR4, *RegPtr);
__vmx_vmwrite(VMCS_CTRL_CR4_READ_SHADOW, *RegPtr);
DebuggerTriggerEvents(CONTROL_REGISTER_MODIFIED, GuestState, VMX_EXIT_QUALIFICATION_REGISTER_CR4);
break;
default:
LogWarning("Unsupported register 0x%x in handling control registers access",
@ -285,11 +260,11 @@ HvHandleControlRegisterAccess(PGUEST_REGS GuestState, UINT32 ProcessorIndex)
/**
* @brief Fill the guest's selector data
*
* @param GdtBase
* @param SegmentRegister
* @param Selector
* @return VOID
*
* @param GdtBase
* @param SegmentRegister
* @param Selector
* @return VOID
*/
VOID
HvFillGuestSelectorData(PVOID GdtBase, ULONG SegmentRegister, UINT16 Selector)
@ -314,8 +289,8 @@ HvFillGuestSelectorData(PVOID GdtBase, ULONG SegmentRegister, UINT16 Selector)
/**
* @brief Add the current instruction length to guest rip to resume to next instruction
*
* @return VOID
*
* @return VOID
*/
VOID
HvResumeToNextInstruction()
@ -334,9 +309,9 @@ HvResumeToNextInstruction()
/**
* @brief Set the monitor trap flag
*
*
* @param Set Set or unset the MTFs
* @return VOID
* @return VOID
*/
VOID
HvSetMonitorTrapFlag(BOOLEAN Set)
@ -365,9 +340,9 @@ HvSetMonitorTrapFlag(BOOLEAN Set)
/**
* @brief Set LOAD DEBUG CONTROLS on Vm-entry controls
*
* @param Set Set or unset
* @return VOID
*
* @param Set Set or unset
* @return VOID
*/
VOID
HvSetLoadDebugControls(BOOLEAN Set)
@ -396,9 +371,9 @@ HvSetLoadDebugControls(BOOLEAN Set)
/**
* @brief Set SAVE DEBUG CONTROLS on Vm-exit controls
*
* @param Set Set or unset
* @return VOID
*
* @param Set Set or unset
* @return VOID
*/
VOID
HvSetSaveDebugControls(BOOLEAN Set)
@ -427,8 +402,8 @@ HvSetSaveDebugControls(BOOLEAN Set)
/**
* @brief Reset GDTR/IDTR and other old when you do vmxoff as the patchguard will detect them left modified
*
* @return VOID
*
* @return VOID
*/
VOID
HvRestoreRegisters()
@ -470,11 +445,11 @@ HvRestoreRegisters()
}
/**
* @brief Set vm-exit for rdpmc instructions
* @brief Set vm-exit for rdpmc instructions
* @details Should be called in vmx-root
*
*
* @param Set Set or unset the vm-exits
* @return VOID
* @return VOID
*/
VOID
HvSetPmcVmexit(BOOLEAN Set)
@ -517,11 +492,11 @@ HvSetMovControlRegsExiting(BOOLEAN Set, UINT64 ControlRegister, UINT64 MaskRegis
}
/**
* @brief Set vm-exit for mov-to-cr3
* @brief Set vm-exit for mov-to-cr3
* @details Should be called in vmx-root
*
*
* @param Set Set or unset the vm-exits
* @return VOID
* @return VOID
*/
VOID
HvSetMovToCr3Vmexit(BOOLEAN Set)
@ -530,12 +505,12 @@ HvSetMovToCr3Vmexit(BOOLEAN Set)
}
/**
* @brief Write on exception bitmap in VMCS
* @brief Write on exception bitmap in VMCS
* DO NOT CALL IT DIRECTLY, instead use HvSetExceptionBitmap
* @details Should be called in vmx-root
*
* @param BitmapMask The content to write on exception bitmap
* @return VOID
*
* @param BitmapMask The content to write on exception bitmap
* @return VOID
*/
VOID
HvWriteExceptionBitmap(UINT32 BitmapMask)
@ -547,10 +522,10 @@ HvWriteExceptionBitmap(UINT32 BitmapMask)
}
/**
* @brief Read exception bitmap in VMCS
* @brief Read exception bitmap in VMCS
* @details Should be called in vmx-root
*
* @return UINT32
*
* @return UINT32
*/
UINT32
HvReadExceptionBitmap()
@ -567,9 +542,9 @@ HvReadExceptionBitmap()
/**
* @brief Set Interrupt-window exiting
*
*
* @param Set Set or unset the Interrupt-window exiting
* @return VOID
* @return VOID
*/
VOID
HvSetInterruptWindowExiting(BOOLEAN Set)
@ -601,9 +576,9 @@ HvSetInterruptWindowExiting(BOOLEAN Set)
/**
* @brief Set NMI-window exiting
*
*
* @param Set Set or unset the NMI-window exiting
* @return VOID
* @return VOID
*/
VOID
HvSetNmiWindowExiting(BOOLEAN Set)
@ -635,10 +610,10 @@ HvSetNmiWindowExiting(BOOLEAN Set)
/**
* @brief Handle Mov to Debug Registers Exitings
*
*
* @param ProcessorIndex Index of processor
* @param Regs Registers of guest
* @return VOID
* @return VOID
*/
VOID
HvHandleMovDebugRegister(UINT32 ProcessorIndex, PGUEST_REGS Regs)
@ -843,9 +818,9 @@ HvHandleMovDebugRegister(UINT32 ProcessorIndex, PGUEST_REGS Regs)
/**
* @brief Set the NMI Exiting
*
*
* @param Set Set or unset the NMI Exiting
* @return VOID
* @return VOID
*/
VOID
HvSetNmiExiting(BOOLEAN Set)
@ -879,9 +854,9 @@ HvSetNmiExiting(BOOLEAN Set)
/**
* @brief Set the VMX preemption timer
*
*
* @param Set Set or unset the VMX preemption timer
* @return VOID
* @return VOID
*/
VOID
HvSetVmxPreemptionTimerExiting(BOOLEAN Set)
@ -909,11 +884,11 @@ HvSetVmxPreemptionTimerExiting(BOOLEAN Set)
}
/**
* @brief Set exception bitmap in VMCS
* @brief Set exception bitmap in VMCS
* @details Should be called in vmx-root
*
* @param IdtIndex Interrupt Descriptor Table index of exception
* @return VOID
*
* @param IdtIndex Interrupt Descriptor Table index of exception
* @return VOID
*/
VOID
HvSetExceptionBitmap(UINT32 IdtIndex)
@ -925,11 +900,11 @@ HvSetExceptionBitmap(UINT32 IdtIndex)
}
/**
* @brief Unset exception bitmap in VMCS
* @brief Unset exception bitmap in VMCS
* @details Should be called in vmx-root
*
* @param IdtIndex Interrupt Descriptor Table index of exception
* @return VOID
*
* @param IdtIndex Interrupt Descriptor Table index of exception
* @return VOID
*/
VOID
HvUnsetExceptionBitmap(UINT32 IdtIndex)
@ -942,9 +917,9 @@ HvUnsetExceptionBitmap(UINT32 IdtIndex)
/**
* @brief Set the External Interrupt Exiting
*
*
* @param Set Set or unset the External Interrupt Exiting
* @return VOID
* @return VOID
*/
VOID
HvSetExternalInterruptExiting(BOOLEAN Set)
@ -957,9 +932,9 @@ HvSetExternalInterruptExiting(BOOLEAN Set)
/**
* @brief Set the RDTSC/P Exiting
*
*
* @param Set Set or unset the RDTSC/P Exiting
* @return VOID
* @return VOID
*/
VOID
HvSetRdtscExiting(BOOLEAN Set)
@ -969,9 +944,9 @@ HvSetRdtscExiting(BOOLEAN Set)
/**
* @brief Set or unset the Mov to Debug Registers Exiting
*
*
* @param Set Set or unset the Mov to Debug Registers Exiting
* @return VOID
* @return VOID
*/
VOID
HvSetMovDebugRegsExiting(BOOLEAN Set)

View file

@ -1,19 +1,19 @@
/**
* @file Vmexit.c
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief The functions for VM-Exit handler for different exit reasons
* @brief The functions for VM-Exit handler for different exit reasons
* @details
* @version 0.1
* @date 2020-04-11
*
*
* @copyright This project is released under the GNU Public License v3.
*
*
*/
#include "pch.h"
/**
* @brief VM-Exit handler for different exit reasons
*
*
* @param GuestRegs Registers that are automatically saved by AsmVmexitHandler (HOST_RIP)
* @return BOOLEAN Return True if VMXOFF executed (not in vmx anymore),
* or return false if we are still in vmx (so we should use vm resume)
@ -184,7 +184,7 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs)
}
case VMX_EXIT_REASON_EXECUTE_CPUID:
{
HvHandleCpuid(GuestRegs);
DispatchEventCpuid(CurrentProcessorIndex, GuestRegs);
break;
}
@ -318,45 +318,17 @@ VmxVmexitHandler(_Inout_ PGUEST_REGS GuestRegs)
break;
}
case VMX_EXIT_REASON_EXECUTE_RDTSC:
{
//
// Check whether we are allowed to change
// the registers and emulate rdtsc or not
//
if (ShouldEmulateRdtscp)
{
//
// handle rdtsc (emulate rdtsc)
//
CounterEmulateRdtsc(GuestRegs);
//
// As the context to event trigger, we send the false which means
// it's an rdtsc (for rdtscp we set Context to true)
// Note : Using !tsc command in transparent-mode is not allowed
//
DebuggerTriggerEvents(TSC_INSTRUCTION_EXECUTION, GuestRegs, FALSE);
}
break;
}
case VMX_EXIT_REASON_EXECUTE_RDTSCP:
{
//
// Check whether we are allowed to change
// the registers and emulate rdtscp or not
// Check whether we are allowed to change the registers
// and emulate rdtsc or not
// Note : Using !tsc command in transparent-mode is not allowed
//
if (ShouldEmulateRdtscp)
{
//
// handle rdtscp (emulate rdtscp)
//
CounterEmulateRdtscp(GuestRegs);
//
// As the context to event trigger, we send the false which means
// it's an rdtsc (for rdtscp we set Context to true)
// Note : Using !tsc command in transparent-mode is not allowed
//
DebuggerTriggerEvents(TSC_INSTRUCTION_EXECUTION, GuestRegs, TRUE);
DispatchEventTsc(GuestRegs, ExitReason == VMX_EXIT_REASON_EXECUTE_RDTSCP ? TRUE : FALSE);
}
break;

View file

@ -83,7 +83,7 @@ typedef struct _DEBUGGER_CORE_EVENTS
LIST_ENTRY DebugRegistersAccessedEventsHead; // DEBUG_REGISTERS_ACCESSED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY ExternalInterruptOccurredEventsHead; // EXTERNAL_INTERRUPT_OCCURRED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY VmcallInstructionExecutionEventsHead; // VMCALL_INSTRUCTION_EXECUTION [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY ControlRegisterModifiedEventsHead; // CONTROL_REGISTER_MODIFIED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
LIST_ENTRY ControlRegisterModifiedEventsHead; // CONTROL_REGISTER_MODIFIED [WARNING : MAKE SURE TO INITIALIZE LIST HEAD , Add it to DebuggerRegisterEvent, Add it to DebuggerTriggerEvents, Add termination to DebuggerTerminateEvent ]
} DEBUGGER_CORE_EVENTS, *PDEBUGGER_CORE_EVENTS;
@ -218,6 +218,8 @@ typedef struct _DEBUGGER_EVENT
LIST_ENTRY ActionsListHead; // Each entry is in DEBUGGER_EVENT_ACTION struct
UINT32 CountOfActions; // The total count of actions
DEBUGGER_EVENT_CALLING_STAGE_TYPE CallingStage; // The stage that a event is supposed to be called
UINT64 OptionalParam1; // Optional parameter to be used differently by events
UINT64 OptionalParam2; // Optional parameter to be used differently by events
UINT64 OptionalParam3; // Optional parameter to be used differently by events
@ -320,7 +322,11 @@ BOOLEAN
DebuggerRegisterEvent(PDEBUGGER_EVENT Event);
DEBUGGER_TRIGGERING_EVENT_STATUS_TYPE
DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType, PGUEST_REGS Regs, PVOID Context);
DebuggerTriggerEvents(DEBUGGER_EVENT_TYPE_ENUM EventType,
DEBUGGER_EVENT_CALLING_STAGE_TYPE CallingStage,
PGUEST_REGS Regs,
PVOID Context,
BOOLEAN * PostEventRequired);
PDEBUGGER_EVENT
DebuggerGetEventByTag(UINT64 Tag);

View file

@ -0,0 +1,29 @@
/**
* @file Dispatch.h
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Headers of debugger functions for dispatching, triggering and
* emulating events
*
* @version 0.1
* @date 2022-09-21
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#pragma once
//////////////////////////////////////////////////
// Functions //
//////////////////////////////////////////////////
VOID
DispatchEventEferSysret(UINT32 CoreIndex, PGUEST_REGS Regs, PVOID Context);
VOID
DispatchEventEferSyscall(UINT32 CoreIndex, PGUEST_REGS Regs, PVOID Context);
VOID
DispatchEventCpuid(PGUEST_REGS Regs);
VOID
DispatchEventTsc(PGUEST_REGS Regs, BOOLEAN IsRdtscp);

View file

@ -1,14 +1,14 @@
/**
* @file Termination.h
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief Headers of Debugger functions for terminating events
* @brief Headers of debugger functions for terminating events
* @details
*
*
* @version 0.1
* @date 2020-08-16
*
*
* @copyright This project is released under the GNU Public License v3.
*
*
*/
#pragma once
@ -65,4 +65,4 @@ VOID
TerminateCpuidExecutionEvent(PDEBUGGER_EVENT Event);
VOID
TerminateControlRegistersEvent(PDEBUGGER_EVENT Event);
TerminateControlRegistersEvent(PDEBUGGER_EVENT Event);

View file

@ -127,6 +127,7 @@
<ClCompile Include="code\debugger\communication\SerialConnection.c" />
<ClCompile Include="code\debugger\core\Debugger.c" />
<ClCompile Include="code\debugger\core\DebuggerEvents.c" />
<ClCompile Include="code\debugger\core\Dispatch.c" />
<ClCompile Include="code\debugger\core\Termination.c" />
<ClCompile Include="code\debugger\features\hooks\ept-hook\EptHook.c" />
<ClCompile Include="code\debugger\features\hooks\syscall-hook\EferHook.c" />
@ -200,6 +201,7 @@
<ClInclude Include="header\debugger\communication\SerialConnection.h" />
<ClInclude Include="header\debugger\core\Debugger.h" />
<ClInclude Include="header\debugger\core\DebuggerEvents.h" />
<ClInclude Include="header\debugger\core\Dispatch.h" />
<ClInclude Include="header\debugger\core\Termination.h" />
<ClInclude Include="header\debugger\features\Hooks.h" />
<ClInclude Include="header\debugger\kernel-level\Kd.h" />

View file

@ -153,15 +153,15 @@
<Filter Include="code\globals">
<UniqueIdentifier>{a7f11b36-d144-4970-826a-a1e54e72e556}</UniqueIdentifier>
</Filter>
<Filter Include="header\globals">
<UniqueIdentifier>{740e29a4-86cf-41c1-b6d0-6e182ab55823}</UniqueIdentifier>
</Filter>
<Filter Include="header\debugger\script-engine">
<UniqueIdentifier>{5b6684f0-db1b-4920-987c-d5dfd8cdc0c1}</UniqueIdentifier>
</Filter>
<Filter Include="code\script-eval">
<UniqueIdentifier>{59005a75-5137-42a4-867a-ccf06fae2f9f}</UniqueIdentifier>
</Filter>
<Filter Include="header\devices\globals">
<UniqueIdentifier>{740e29a4-86cf-41c1-b6d0-6e182ab55823}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="code\common\Common.c">
@ -344,6 +344,9 @@
<ClCompile Include="..\script-eval\code\Regs.c">
<Filter>code\script-eval</Filter>
</ClCompile>
<ClCompile Include="code\debugger\core\Dispatch.c">
<Filter>code\debugger\core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@ -497,10 +500,10 @@
<Filter>header\debugger\commands</Filter>
</ClInclude>
<ClInclude Include="header\globals\GlobalVariableManagement.h">
<Filter>header\globals</Filter>
<Filter>header\devices\globals</Filter>
</ClInclude>
<ClInclude Include="header\globals\GlobalVariables.h">
<Filter>header\globals</Filter>
<Filter>header\devices\globals</Filter>
</ClInclude>
<ClInclude Include="header\platform\MetaMacros.h">
<Filter>header\platform</Filter>
@ -508,6 +511,9 @@
<ClInclude Include="header\debugger\script-engine\ScriptEngine.h">
<Filter>header\debugger\script-engine</Filter>
</ClInclude>
<ClInclude Include="header\debugger\core\Dispatch.h">
<Filter>header\debugger\core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="code\assembly\AsmCommon.asm">

View file

@ -71,6 +71,7 @@
#include "..\hprdbghv\header\debugger\user-level\Ud.h"
#include "..\hprdbghv\header\vmm\vmx\Mtf.h"
#include "..\hprdbghv\header\debugger\core\DebuggerEvents.h"
#include "..\hprdbghv\header\debugger\core\Dispatch.h"
#include "..\hprdbghv\header\debugger\features\Hooks.h"
#include "..\hprdbghv\header\vmm\vmx\Counters.h"
#include "..\hprdbghv\header\debugger\transparency\Transparency.h"

View file

@ -66,6 +66,17 @@ typedef enum _DEBUGGER_EVENT_ACTION_TYPE_ENUM
} DEBUGGER_EVENT_ACTION_TYPE_ENUM;
/**
* @brief Type of calling the event
*
*/
typedef enum _DEBUGGER_EVENT_CALLING_STAGE_TYPE
{
DEBUGGER_CALLING_STAGE_PRE_EVENT_EMULATION,
DEBUGGER_CALLING_STAGE_POST_EVENT_EMULATION,
} DEBUGGER_EVENT_CALLING_STAGE_TYPE;
/**
* @brief Type of handling !syscall or !sysret
*