HyperDbg Debugger
Loading...
Searching...
No Matches
Kd.h File Reference

Header for routines related to kernel mode debugging. More...

Go to the source code of this file.

Classes

struct  _DEBUGGEE_REQUEST_TO_CHANGE_PROCESS
 request to change the process More...
struct  _DEBUGGEE_REQUEST_TO_CHANGE_THREAD
 request to change the thread More...
struct  _DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT
 request to pause and halt the system More...
struct  _HARDWARE_DEBUG_REGISTER_DETAILS
 store the details of a hardware debug register to ignore any trigger for other threads More...

Typedefs

typedef struct _DEBUGGEE_REQUEST_TO_CHANGE_PROCESS DEBUGGEE_REQUEST_TO_CHANGE_PROCESS
 request to change the process
typedef struct _DEBUGGEE_REQUEST_TO_CHANGE_PROCESSPDEBUGGEE_REQUEST_TO_CHANGE_PROCESS
typedef struct _DEBUGGEE_REQUEST_TO_CHANGE_THREAD DEBUGGEE_REQUEST_TO_CHANGE_THREAD
 request to change the thread
typedef struct _DEBUGGEE_REQUEST_TO_CHANGE_THREADPDEBUGGEE_REQUEST_TO_CHANGE_THREAD
typedef struct _DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT
 request to pause and halt the system
typedef struct _DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENTPDEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT
typedef struct _HARDWARE_DEBUG_REGISTER_DETAILS HARDWARE_DEBUG_REGISTER_DETAILS
 store the details of a hardware debug register to ignore any trigger for other threads
typedef struct _HARDWARE_DEBUG_REGISTER_DETAILSPHARDWARE_DEBUG_REGISTER_DETAILS

Functions

VOID KdHaltSystem (PDEBUGGER_PAUSE_PACKET_RECEIVED PausePacket)
 Halt the system.
VOID KdHandleDebugEventsWhenKernelDebuggerIsAttached (PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN TrapSetByDebugger)
 Handles debug events when kernel-debugger is attached.
VOID KdManageSystemHaltOnVmxRoot (PROCESSOR_DEBUGGING_STATE *DbgState, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
 manage system halt on vmx-root mode
VOID KdHandleNmi (_Inout_ PROCESSOR_DEBUGGING_STATE *DbgState)
VOID KdInitializeKernelDebugger ()
 initialize kernel debugger
VOID KdUninitializeKernelDebugger ()
 uninitialize kernel debugger
VOID KdInitializeInstantEventPools ()
 Initialize the required pools for instant events.
VOID KdSendFormatsFunctionResult (UINT64 Value)
 Send the result of formats command to the kernel debugger.
VOID KdSendCommandFinishedSignal (UINT32 CoreId)
 Notify debugger that the execution of command finished.
VOID KdHandleBreakpointAndDebugBreakpointsCallback (_In_ UINT32 CoreId, _In_ DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
VOID KdHandleBreakpointAndDebugBreakpoints (_Inout_ PROCESSOR_DEBUGGING_STATE *DbgState, _In_ DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
VOID KdHandleHaltsWhenNmiReceivedFromVmxRoot (_Inout_ PROCESSOR_DEBUGGING_STATE *DbgState)
BOOLEAN KdHandleMtfCallback (UINT32 CoreId)
 Handle Monitor Trap Flag (MTF) callback for kernel debugger.
BOOLEAN KdCheckImmediateMessagingMechanism (UINT32 OperationCode)
 Checks whether the immediate messaging mechism is needed or not.
BOOLEAN KdResponsePacketToDebugger (_In_ _Strict_type_match_ DEBUGGER_REMOTE_PACKET_TYPE PacketType, _In_ _Strict_type_match_ DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION Response, _In_reads_bytes_opt_(OptionalBufferLength) CHAR *OptionalBuffer, _In_ UINT32 OptionalBufferLength)
BOOLEAN KdLoggingResponsePacketToDebugger (_In_reads_bytes_(OptionalBufferLength) CHAR *OptionalBuffer, _In_ UINT32 OptionalBufferLength, _In_ UINT32 OperationCode)
BOOLEAN KdCheckGuestOperatingModeChanges (UINT16 PreviousCsSelector, UINT16 CurrentCsSelector)
 Check if the execution mode (kernel-mode to user-mode or user-mode to kernel-mode) changed.
BOOLEAN KdIsGuestOnUsermode32Bit ()
 determines if the guest was in 32-bit user-mode or 64-bit (long mode)
VOID KdHandleNmiBroadcastDebugBreaks (UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler)
 Handle broadcast NMIs for halting cores in vmx-root mode.
VOID KdUnlockTheHaltedCore (PROCESSOR_DEBUGGING_STATE *DbgState)
 unlock the target core
BOOLEAN KdCheckTheHaltedCore (PROCESSOR_DEBUGGING_STATE *DbgState)
 check the lock state of the target core
BOOLEAN KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId (UINT32 CoreId, DEBUGGER_THREAD_PROCESS_TRACING TracingType)
 Query for process/thread interception status.
BOOLEAN KdQueryIgnoreHandlingMov2DebugRegs (UINT32 CoreId)
 Query to ignore handling mov 2 debug regs exiting.

Variables

volatile LONG DebuggerResponseLock
 Vmx-root lock for sending response of debugger.
volatile LONG DebuggerHandleBreakpointLock
 Vmx-root lock for handling breaks to debugger.

Detailed Description

Header for routines related to kernel mode debugging.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2020-12-20

Typedef Documentation

◆ DEBUGGEE_REQUEST_TO_CHANGE_PROCESS

request to change the process

◆ DEBUGGEE_REQUEST_TO_CHANGE_THREAD

request to change the thread

◆ DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT

◆ HARDWARE_DEBUG_REGISTER_DETAILS

store the details of a hardware debug register to ignore any trigger for other threads

◆ PDEBUGGEE_REQUEST_TO_CHANGE_PROCESS

◆ PDEBUGGEE_REQUEST_TO_CHANGE_THREAD

◆ PDEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT

◆ PHARDWARE_DEBUG_REGISTER_DETAILS

Function Documentation

◆ KdCheckGuestOperatingModeChanges()

BOOLEAN KdCheckGuestOperatingModeChanges ( UINT16 PreviousCsSelector,
UINT16 CurrentCsSelector )

Check if the execution mode (kernel-mode to user-mode or user-mode to kernel-mode) changed.

Parameters
PreviousCsSelector
CurrentCsSelector
Returns
BOOLEAN
1488{
1489 PreviousCsSelector = PreviousCsSelector & ~3;
1490 CurrentCsSelector = CurrentCsSelector & ~3;
1491
1492 //
1493 // Check if the execution modes are the same or not
1494 //
1495 if (PreviousCsSelector == CurrentCsSelector)
1496 {
1497 //
1498 // Execution modes are not changed
1499 //
1500 return FALSE;
1501 }
1502
1503 if ((PreviousCsSelector == KGDT64_R3_CODE || PreviousCsSelector == KGDT64_R3_CMCODE) && CurrentCsSelector == KGDT64_R0_CODE)
1504 {
1505 //
1506 // User-mode -> Kernel-mode
1507 //
1508 LogInfo("User-mode -> Kernel-mode\n");
1509 }
1510 else if ((CurrentCsSelector == KGDT64_R3_CODE || CurrentCsSelector == KGDT64_R3_CMCODE) && PreviousCsSelector == KGDT64_R0_CODE)
1511 {
1512 //
1513 // Kernel-mode to user-mode
1514 //
1515 LogInfo("Kernel-mode -> User-mode\n");
1516 }
1517 else if (CurrentCsSelector == KGDT64_R3_CODE && PreviousCsSelector == KGDT64_R3_CMCODE)
1518 {
1519 //
1520 // A heaven's gate (User-mode 32-bit code -> User-mode 64-bit code)
1521 //
1522 LogInfo("32-bit User-mode -> 64-bit User-mode (Heaven's gate)\n");
1523 }
1524 else if (PreviousCsSelector == KGDT64_R3_CODE && CurrentCsSelector == KGDT64_R3_CMCODE)
1525 {
1526 //
1527 // A heaven's gate (User-mode 64-bit code -> User-mode 32-bit code)
1528 //
1529 LogInfo("64-bit User-mode -> 32-bit User-mode (Return from Heaven's gate)\n");
1530 }
1531 else
1532 {
1533 LogError("Err, unknown changes in cs selector during the instrumentation step-in\n");
1534 }
1535
1536 //
1537 // Execution modes are changed
1538 //
1539 return TRUE;
1540}
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
#define KGDT64_R3_CODE
Definition Constants.h:659
#define KGDT64_R0_CODE
Definition Constants.h:655
#define KGDT64_R3_CMCODE
Definition Constants.h:657
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71

◆ KdCheckImmediateMessagingMechanism()

BOOLEAN KdCheckImmediateMessagingMechanism ( UINT32 OperationCode)

Checks whether the immediate messaging mechism is needed or not.

Parameters
OperationCode
Returns
BOOLEAN
108{
109 return (g_KernelDebuggerState && !(OperationCode & OPERATION_MANDATORY_DEBUGGEE_BIT));
110}
#define OPERATION_MANDATORY_DEBUGGEE_BIT
If a operation use this bit in its Operation code, then it means that the operation should be perform...
Definition Constants.h:367
BOOLEAN g_KernelDebuggerState
shows whether the kernel debugger is enabled or disabled
Definition Global.h:151

◆ KdCheckTheHaltedCore()

BOOLEAN KdCheckTheHaltedCore ( PROCESSOR_DEBUGGING_STATE * DbgState)

check the lock state of the target core

Parameters
DbgStateThe state of the debugger on the target core
Returns
BOOLEAN
1792{
1793 return SpinlockCheckLock(&DbgState->Lock);
1794}
BOOLEAN SpinlockCheckLock(volatile LONG *Lock)
Check the lock without changing the state.
Definition Spinlock.c:174
volatile LONG Lock
Definition State.h:165

◆ KdHaltSystem()

VOID KdHaltSystem ( PDEBUGGER_PAUSE_PACKET_RECEIVED PausePacket)

Halt the system.

Parameters
PausePacket
Returns
VOID
3490{
3491 //
3492 // Broadcast to halt everything
3493 // Instead of broadcasting we will just send one vmcall and
3494 // from that point, we halt all the other cores by NMIs, this
3495 // way we are sure that we get all the other cores at the middle
3496 // of their execution codes and not on HyperDbg routines
3497 //
3498 // KdBroadcastHaltOnAllCores();
3499 //
3500
3501 //
3502 // vm-exit and halt current core
3503 //
3505
3506 //
3507 // Set the status
3508 //
3510}
#define DEBUGGER_VMCALL_VM_EXIT_HALT_SYSTEM
VMCALL to cause vm-exit and halt the system.
Definition DebuggerVmcalls.h:22
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
IMPORT_EXPORT_VMM NTSTATUS VmFuncVmxVmcall(UINT64 VmcallNumber, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3)
Export for running VMX VMCALLs.
Definition Export.c:957
UINT32 Result
Definition DataTypes.h:212

◆ KdHandleBreakpointAndDebugBreakpoints()

VOID KdHandleBreakpointAndDebugBreakpoints ( _Inout_ PROCESSOR_DEBUGGING_STATE * DbgState,
_In_ DEBUGGEE_PAUSING_REASON Reason,
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails )

◆ KdHandleBreakpointAndDebugBreakpointsCallback()

VOID KdHandleBreakpointAndDebugBreakpointsCallback ( _In_ UINT32 CoreId,
_In_ DEBUGGEE_PAUSING_REASON Reason,
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails )

◆ KdHandleDebugEventsWhenKernelDebuggerIsAttached()

VOID KdHandleDebugEventsWhenKernelDebuggerIsAttached ( PROCESSOR_DEBUGGING_STATE * DbgState,
BOOLEAN TrapSetByDebugger )

Handles debug events when kernel-debugger is attached.

Parameters
DbgStateThe state of the debugger on the current core
TrapSetByDebuggerShows whether a trap set by debugger or not
Returns
VOID
488{
489 DEBUGGER_TRIGGERED_EVENT_DETAILS TargetContext = {0};
490 BOOLEAN IgnoreDebugEvent = FALSE;
491 UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(DbgState->CoreId);
492
493 //
494 // It's a breakpoint and should be handled by the kernel debugger
495 //
496 TargetContext.Context = (PVOID)LastVmexitRip;
497
498 if (TrapSetByDebugger)
499 {
500 //
501 // *** Handle a regular trap flag (most of the times as a result of stepping) set by the debugger ***
502 //
503
504 //
505 // Check and handle if there is a software defined breakpoint
506 //
508 LastVmexitRip,
510 FALSE))
511 {
512 if (g_HardwareDebugRegisterDetailsForStepOver.Address != (UINT64)NULL)
513 {
514 //
515 // Check if it's caused by a step-over hardware debug breakpoint or not
516 //
517 if (LastVmexitRip == g_HardwareDebugRegisterDetailsForStepOver.Address)
518 {
519 if (g_HardwareDebugRegisterDetailsForStepOver.ProcessId == HANDLE_TO_UINT32(PsGetCurrentProcessId()) &&
520 g_HardwareDebugRegisterDetailsForStepOver.ThreadId == HANDLE_TO_UINT32(PsGetCurrentThreadId()))
521 {
522 //
523 // It's a step caused by a debug register breakpoint step-over
524 //
526 }
527 else
528 {
529 //
530 // Should be ignored because it's a hardware debug register that is
531 // likely triggered by other thread
532 //
533 IgnoreDebugEvent = TRUE;
534
535 //
536 // Also, we should re-apply the hardware debug breakpoint on this thread
537 //
540 FALSE,
542 }
543 }
544 }
545
546 if (!IgnoreDebugEvent)
547 {
548 //
549 // Handle a regular step
550 //
553 &TargetContext);
554 }
555 }
556 }
557 else
558 {
559 //
560 // It's a regular debug break event
561 //
564 &TargetContext);
565 }
566}
BOOLEAN BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE *DbgState, UINT64 GuestRip, DEBUGGEE_PAUSING_REASON Reason, BOOLEAN ChangeMtfState)
Check if the breakpoint vm-exit relates to 'bp' command or not.
Definition BreakpointCommands.c:478
_Use_decl_annotations_ VOID KdHandleBreakpointAndDebugBreakpoints(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle DBs and BPs for kernel debugger.
Definition Kd.c:1291
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
UCHAR BOOLEAN
Definition BasicTypes.h:35
void * PVOID
Definition BasicTypes.h:56
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_STEPPED
Definition Connection.h:27
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_HARDWARE_DEBUG_REGISTER_HIT
Definition Connection.h:30
struct _DEBUGGER_TRIGGERED_EVENT_DETAILS DEBUGGER_TRIGGERED_EVENT_DETAILS
The structure of detail of a triggered event in HyperDbg.
@ BREAK_ON_INSTRUCTION_FETCH
Definition DataTypes.h:103
IMPORT_EXPORT_VMM BOOLEAN SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN ApplyToVmcs, UINT64 TargetAddress)
Configure hardware debug register for access, write and fetch breakpoints.
Definition DebugRegisters.c:37
IMPORT_EXPORT_VMM UINT64 VmFuncGetLastVmexitRip(UINT32 CoreId)
get the last vm-exit RIP
Definition Export.c:363
HARDWARE_DEBUG_REGISTER_DETAILS g_HardwareDebugRegisterDetailsForStepOver
Holds the state of hardware debug register for step-over.
Definition Global.h:103
#define DEBUGGER_DEBUG_REGISTER_FOR_STEP_OVER
debug register for step-over
Definition Debugger.h:21
struct _HARDWARE_DEBUG_REGISTER_DETAILS HARDWARE_DEBUG_REGISTER_DETAILS
store the details of a hardware debug register to ignore any trigger for other threads
PVOID Context
Definition DataTypes.h:227
UINT32 CoreId
Definition State.h:168

◆ KdHandleHaltsWhenNmiReceivedFromVmxRoot()

VOID KdHandleHaltsWhenNmiReceivedFromVmxRoot ( _Inout_ PROCESSOR_DEBUGGING_STATE * DbgState)

◆ KdHandleMtfCallback()

BOOLEAN KdHandleMtfCallback ( UINT32 CoreId)

Handle Monitor Trap Flag (MTF) callback for kernel debugger.

This function will be called from vmx-root mode

Parameters
CoreId
Returns
BOOLEAN
1213{
1214 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
1215 BOOLEAN IsMtfHandled = FALSE;
1216
1217 //
1218 // *** Check if we need to re-apply a breakpoint or not
1219 // We check it separately because the guest might step
1220 // instructions on an MTF so we want to check for the step too ***
1221 //
1223 {
1224 //
1225 // Check for re-enabling external interrupts
1226 //
1228
1229 //
1230 // MTF is handled
1231 //
1232 IsMtfHandled = TRUE;
1233 }
1234
1235 //
1236 // *** Check for instrumentation step-in ***
1237 //
1239 {
1240 //
1241 // Unset the MTF instrumentation state (might be changed in the caller)
1242 //
1244
1245 //
1246 // Handle MTF in the debugger
1247 //
1249
1250 //
1251 // MTF is handled
1252 //
1253 IsMtfHandled = TRUE;
1254 }
1255
1256 //
1257 // check the condition of passing the execution to NMIs
1258 //
1259 // This one wastes one week of my life!
1260 // During the testing we realized the !epthook command in Debugger Mode
1261 // is not working. After some tests, it's because if in the middle of a
1262 // command in vmx-root and NMI is sent and the debugger waits for another
1263 // MTF, we'll ignore that MTF and a new MTF is not set again.
1264 // That's why we moved this check here so every command that needs a task
1265 // from MTF is doing its tasks and when we reached here, the check for halting
1266 // the debuggee in MTF is performed
1267 //
1268 else if (KdCheckAndHandleNmiStateForMtf(DbgState))
1269 {
1270 //
1271 // MTF is handled
1272 //
1273 IsMtfHandled = TRUE;
1274 }
1275
1276 return IsMtfHandled;
1277}
BOOLEAN BreakpointCheckAndHandleReApplyingBreakpoint(PROCESSOR_DEBUGGING_STATE *DbgState)
Check and reapply breakpoint.
Definition BreakpointCommands.c:440
BOOLEAN KdCheckAndHandleNmiStateForMtf(PROCESSOR_DEBUGGING_STATE *DbgState)
Handle NMI state for MTF.
Definition Kd.c:1104
VOID KdHandleInstrumentationStepIn(PROCESSOR_DEBUGGING_STATE *DbgState)
Handle instrumentation step-in for kernel debugger.
Definition Kd.c:1146
IMPORT_EXPORT_VMM VOID VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId)
Checks to enable and reinject previous interrupts.
Definition Export.c:1086
IMPORT_EXPORT_VMM VOID VmFuncUnsetInstrumentationStepInState(UINT32 CoreId)
Unset instrumentation step in MTF (used for single stepping with MTF).
Definition Export.c:86
IMPORT_EXPORT_VMM BOOLEAN VmFuncQueryInstrumentationStepInState(UINT32 CoreId)
Query instrumentation step in MTF state.
Definition Export.c:99
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
struct _PROCESSOR_DEBUGGING_STATE PROCESSOR_DEBUGGING_STATE
Saves the debugger state.

◆ KdHandleNmi()

VOID KdHandleNmi ( _Inout_ PROCESSOR_DEBUGGING_STATE * DbgState)

◆ KdHandleNmiBroadcastDebugBreaks()

VOID KdHandleNmiBroadcastDebugBreaks ( UINT32 CoreId,
BOOLEAN IsOnVmxNmiHandler )

Handle broadcast NMIs for halting cores in vmx-root mode.

Parameters
CoreId
IsOnVmxNmiHandler
Returns
VOID
1026{
1027 //
1028 // Get the current debugging state
1029 //
1030 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
1031
1032 //
1033 // We use it as a global flag (for both vmx-root and vmx non-root), because
1034 // generally it doesn't have any use case in vmx-root (IsOnVmxNmiHandler == FALSE)
1035 // but in some cases, we might set the MTF but another vm-exit receives before
1036 // MTF and in that place if it tries to trigger and event, then the MTF is not
1037 // handled and the core is not locked properly, just waits to get the handle
1038 // of the "DebuggerHandleBreakpointLock", so we check this flag there
1039 //
1040 DbgState->NmiState.WaitingToBeLocked = TRUE;
1041
1042 if (IsOnVmxNmiHandler)
1043 {
1044 //
1045 // Indicate that it's called from NMI handle, and it relates to
1046 // halting the debuggee
1047 //
1049
1050 //
1051 // If the core was in the middle of spinning on the spinlock
1052 // of getting the debug lock, this mechanism is not needed,
1053 // but if the core is not spinning there or the core is processing
1054 // a random vm-exit, then we inject an immediate vm-exit after vm-entry
1055 // or inject a DPC
1056 // this is used for two reasons.
1057 //
1058 // 1. first, we will get the registers (context) to halt the core
1059 // 2. second, it guarantees that if the NMI arrives within any
1060 // instruction in vmx-root mode, then we injected an immediate
1061 // vm-exit and we won't miss any cpu cycle in the guest
1062 //
1063 // KdFireDpc(KdHaltCoreInTheCaseOfHaltedFromNmiInVmxRoot, NULL);
1065 }
1066 else
1067 {
1068 //
1069 // Handle core break
1070 //
1071 KdHandleNmi(DbgState);
1072 }
1073}
_Use_decl_annotations_ VOID KdHandleNmi(PROCESSOR_DEBUGGING_STATE *DbgState)
Handle NMI Vm-exits.
Definition Kd.c:1399
IMPORT_EXPORT_VMM VOID VmFuncSetMonitorTrapFlag(BOOLEAN Set)
Set the monitor trap flag.
Definition Export.c:111
volatile BOOLEAN WaitingToBeLocked
Definition State.h:96
volatile BOOLEAN NmiCalledInVmxRootRelatedToHaltDebuggee
Definition State.h:95
KD_NMI_STATE NmiState
Definition State.h:180

◆ KdInitializeInstantEventPools()

VOID KdInitializeInstantEventPools ( )

Initialize the required pools for instant events.

Returns
VOID
119{
120 //
121 // Request pages to be allocated for regular instant events
122 //
124
125 //
126 // Request pages to be allocated for regular instant events's actions
127 //
129
130#if MAXIMUM_BIG_INSTANT_EVENTS >= 1
131
132 //
133 // Request pages to be allocated for big instant events
134 //
136
137 //
138 // Request pages to be allocated for big instant events's actions
139 //
141
142#endif // MAXIMUM_BIG_INSTANT_EVENTS
143
144 //
145 // Pre-allocate pools for possible EPT hooks
146 // Because there are possible init EPT hook structures, we only allocate the
147 // maximum number of regular instant event subtracted from the initial pages
148 //
150
152 {
153 LogWarning("Warning, cannot allocate the pre-allocated pools for EPT hooks");
154
155 //
156 // BTW, won't fail the starting phase because of this
157 //
158 }
159}
BOOLEAN PoolManagerCheckAndPerformAllocationAndDeallocation()
This function performs allocations from VMX non-root based on g_RequestNewAllocation.
Definition PoolManager.c:320
BOOLEAN PoolManagerRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
Request to allocate new buffers.
Definition PoolManager.c:436
#define MAXIMUM_NUMBER_OF_INITIAL_PREALLOCATED_EPT_HOOKS
Maximum number of initial pre-allocated EPT hooks.
Definition Constants.h:268
#define BIG_INSTANT_EVENT_ACTION_BUFFER
Pre-allocated size for a big action + custom code or script buffer.
Definition Constants.h:308
#define REGULAR_INSTANT_EVENT_ACTION_BUFFER
Pre-allocated size for a regular action + custom code or script buffer.
Definition Constants.h:302
#define MAXIMUM_BIG_INSTANT_EVENTS
Maximum number of (big) instant events that are pre-allocated.
Definition Constants.h:284
#define MAXIMUM_REGULAR_INSTANT_EVENTS
Maximum number of (regular) instant events that are pre-allocated.
Definition Constants.h:278
#define REGULAR_INSTANT_EVENT_CONDITIONAL_BUFFER
Pre-allocated size for a regular event + conditions buffer.
Definition Constants.h:290
#define BIG_INSTANT_EVENT_CONDITIONAL_BUFFER
Pre-allocated size for a big event + conditions buffer.
Definition Constants.h:296
@ INSTANT_BIG_EVENT_BUFFER
Definition DataTypes.h:85
@ INSTANT_BIG_EVENT_ACTION_BUFFER
Definition DataTypes.h:87
@ INSTANT_REGULAR_EVENT_ACTION_BUFFER
Definition DataTypes.h:86
@ INSTANT_REGULAR_EVENT_BUFFER
Definition DataTypes.h:84
#define LogWarning(format,...)
Log in the case of warning.
Definition HyperDbgHyperLogIntrinsics.h:99
IMPORT_EXPORT_VMM VOID ConfigureEptHookReservePreallocatedPoolsForEptHooks(UINT32 Count)
Allocate (reserve) pages for storing EPT hooks page hooks.
Definition Configuration.c:241

◆ KdInitializeKernelDebugger()

VOID KdInitializeKernelDebugger ( )

initialize kernel debugger

this function should be called on vmx non-root

Returns
VOID
23{
24 //
25 // Allocate DPC routine
26 //
27 // for (SIZE_T i = 0; i < CoreCount; i++)
28 // {
29 // g_DbgState[i].KdDpcObject = PlatformMemAllocateNonPagedPool(sizeof(KDPC));
30 //
31 // if (g_DbgState[i].KdDpcObject == NULL)
32 // {
33 // LogError("Err, allocating dpc holder for debuggee");
34 // return;
35 // }
36 // }
37
38 //
39 // Enable vm-exit on Hardware debug exceptions and breakpoints
40 // so, intercept #DBs and #BP by changing exception bitmap (one core)
41 //
43
44 //
45 // Reset pause break requests
46 //
48
49 //
50 // Initial the needed pools for instant events
51 //
53
54 //
55 // Indicate that the kernel debugger is active
56 //
58}
VOID KdInitializeInstantEventPools()
Initialize the required pools for instant events.
Definition Kd.c:118
IMPORT_EXPORT_VMM VOID BroadcastEnableDbAndBpExitingAllCores()
routines to set vm-exit on all DBs and BP on all cores
Definition Broadcast.c:35
DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT g_IgnoreBreaksToDebugger
Holds the requests to pause the break of debuggee until a special event happens.
Definition Global.h:97
struct _DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT DEBUGGEE_REQUEST_TO_IGNORE_BREAKS_UNTIL_AN_EVENT
request to pause and halt the system

◆ KdIsGuestOnUsermode32Bit()

BOOLEAN KdIsGuestOnUsermode32Bit ( )

determines if the guest was in 32-bit user-mode or 64-bit (long mode)

this function should be called from vmx-root

Returns
BOOLEAN
3221{
3222 //
3223 // Only 16 bit is needed however, vmwrite might write on other bits
3224 // and corrupt other variables, that's why we get 64bit
3225 //
3226 UINT64 CsSel = (UINT64)NULL;
3227
3228 //
3229 // Read guest's cs selector
3230 //
3231 CsSel = VmFuncGetCsSelector();
3232
3233 if (CsSel == KGDT64_R0_CODE)
3234 {
3235 //
3236 // 64-bit kernel-mode
3237 //
3238 return FALSE;
3239 }
3240 else if ((CsSel & ~3) == KGDT64_R3_CODE)
3241 {
3242 //
3243 // 64-bit user-mode
3244 //
3245 return FALSE;
3246 }
3247 else if ((CsSel & ~3) == KGDT64_R3_CMCODE)
3248 {
3249 //
3250 // 32-bit user-mode
3251 //
3252 return TRUE;
3253 }
3254 else
3255 {
3256 LogError("Err, unknown value for cs, cannot determine wow64 mode");
3257 }
3258
3259 //
3260 // By default, 64-bit
3261 //
3262 return FALSE;
3263}
IMPORT_EXPORT_VMM UINT16 VmFuncGetCsSelector()
Read CS selector.
Definition Export.c:386

◆ KdLoggingResponsePacketToDebugger()

BOOLEAN KdLoggingResponsePacketToDebugger ( _In_reads_bytes_(OptionalBufferLength) CHAR * OptionalBuffer,
_In_ UINT32 OptionalBufferLength,
_In_ UINT32 OperationCode )

◆ KdManageSystemHaltOnVmxRoot()

VOID KdManageSystemHaltOnVmxRoot ( PROCESSOR_DEBUGGING_STATE * DbgState,
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails )

manage system halt on vmx-root mode

This function should only be called from KdHandleBreakpointAndDebugBreakpoints

Parameters
DbgStateThe state of the debugger on the current core
EventDetails
MainCorethe core that triggered the event
Returns
VOID
3277{
3278 DEBUGGEE_KD_PAUSED_PACKET PausePacket;
3279 ULONG ExitInstructionLength = 0;
3280 RFLAGS Rflags = {0};
3281 UINT64 LastVmexitRip = 0;
3282
3283 //
3284 // Perform Pre-halt tasks
3285 //
3286 KdApplyTasksPreHaltCore(DbgState);
3287
3288StartAgain:
3289
3290 //
3291 // We check for receiving buffer (unhalting) only on the
3292 // first core and not on every cores
3293 //
3294 if (DbgState->MainDebuggingCore)
3295 {
3296 //
3297 // *** Current Operating Core ***
3298 //
3299 RtlZeroMemory(&PausePacket, sizeof(DEBUGGEE_KD_PAUSED_PACKET));
3300
3301 //
3302 // Get the last RIP for vm-exit handler
3303 //
3304 LastVmexitRip = VmFuncGetRip();
3305
3306 //
3307 // Set the halt reason
3308 //
3309 PausePacket.PausingReason = g_DebuggeeHaltReason;
3310
3311 //
3312 // Set the current core
3313 //
3314 PausePacket.CurrentCore = DbgState->CoreId;
3315
3316 //
3317 // Set the RIP and mode of execution
3318 //
3319 PausePacket.Rip = LastVmexitRip;
3321
3322 //
3323 // Set disassembly state
3324 //
3325 PausePacket.IgnoreDisassembling = DbgState->IgnoreDisasmInNextPacket;
3326 DbgState->IgnoreDisasmInNextPacket = FALSE;
3327
3328 //
3329 // Set rflags for finding the results of conditional jumps
3330 //
3331 Rflags.AsUInt = VmFuncGetRflags();
3332 PausePacket.Rflags = Rflags.AsUInt;
3333
3334 //
3335 // Set the event tag (if it's an event)
3336 //
3337 if (EventDetails != NULL)
3338 {
3339 PausePacket.EventTag = EventDetails->Tag;
3340 PausePacket.EventCallingStage = EventDetails->Stage;
3341 }
3342
3343 //
3344 // Read the instruction len hint
3345 //
3346 if (DbgState->InstructionLengthHint != 0)
3347 {
3348 ExitInstructionLength = DbgState->InstructionLengthHint;
3349 }
3350 else
3351 {
3352 //
3353 // Reading instruction length (VMCS_VMEXIT_INSTRUCTION_LENGTH) won't work for anything that is not instruction exiting,
3354 // so we won't use it anymore
3355 //
3356
3357 //
3358 // Set the length to notify debuggee
3359 //
3360 ExitInstructionLength = CheckAddressMaximumInstructionLength((PVOID)LastVmexitRip);
3361 }
3362
3363 //
3364 // Set the reading length of bytes (for instruction disassembling)
3365 //
3366 PausePacket.ReadInstructionLen = (UINT16)ExitInstructionLength;
3367
3368 //
3369 // Find the current instruction
3370 //
3372 &PausePacket.InstructionBytesOnRip,
3373 ExitInstructionLength);
3374
3375 //
3376 // Send the pause packet, along with RIP and an indication
3377 // to pause to the debugger
3378 //
3381 (CHAR *)&PausePacket,
3383
3384 //
3385 // Perform Commands from the debugger
3386 //
3388
3389 //
3390 // Check if it's a change core event or not, otherwise finish the execution
3391 // and continue debuggee
3392 //
3393 if (!DbgState->MainDebuggingCore)
3394 {
3395 //
3396 // It's a core switch, start again
3397 //
3398 goto StartAgain;
3399 }
3400 }
3401 else
3402 {
3403 //
3404 // All cores except operating core
3405 //
3406
3407 //
3408 // Lock and unlock the lock so all core can get the lock
3409 // and continue their normal execution
3410 //
3411 DbgState->NmiState.WaitingToBeLocked = FALSE;
3412
3414 DbgState->Lock,
3415
3416 //
3417 // Check if it's a change core event or not
3418 //
3419 if (DbgState->MainDebuggingCore) {
3420 //
3421 // It's a core change event
3422 //
3423 g_DebuggeeHaltReason = DEBUGGEE_PAUSING_REASON_DEBUGGEE_CORE_SWITCHED;
3424
3425 goto StartAgain;
3426 }
3427
3428 );
3429
3430 //
3431 // Check if any task needs to be executed on this core or not
3432 //
3433 if (DbgState->HaltedCoreTask.PerformHaltedTask)
3434 {
3435 //
3436 // Indicate that the halted core is no longer needed to execute a task
3437 // as the current task is executed once
3438 //
3440
3441 //
3442 // Perform the target task
3443 //
3445 DbgState->HaltedCoreTask.TargetTask,
3446 DbgState->HaltedCoreTask.Context);
3447
3448 //
3449 // Check if the core needs to be locked again
3450 //
3451 if (DbgState->HaltedCoreTask.LockAgainAfterTask)
3452 {
3453 //
3454 // Lock again
3455 //
3456 SpinlockLock(&DbgState->Lock);
3457
3458 goto StartAgain;
3459 }
3460 }
3461 }
3462
3463 //
3464 // Apply the basic task for the core before continue
3465 //
3467}
VOID HaltedCorePerformTargetTask(PROCESSOR_DEBUGGING_STATE *DbgState, UINT64 TargetTask, PVOID Context)
Perform the task on halted core.
Definition HaltedCore.c:45
VOID KdApplyTasksPreHaltCore(PROCESSOR_DEBUGGING_STATE *DbgState)
before halting any core, all the tasks will be applied to all cores including the main core
Definition Kd.c:578
BOOLEAN KdIsGuestOnUsermode32Bit()
determines if the guest was in 32-bit user-mode or 64-bit (long mode)
Definition Kd.c:3220
VOID KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE *DbgState)
This function applies commands from the debugger to the debuggee.
Definition Kd.c:2258
VOID KdApplyTasksPostContinueCore(PROCESSOR_DEBUGGING_STATE *DbgState)
before continue any core, all the tasks will be applied to all cores including the main core
Definition Kd.c:617
_Use_decl_annotations_ BOOLEAN KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE PacketType, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION Response, CHAR *OptionalBuffer, UINT32 OptionalBufferLength)
Sends a HyperDbg response packet to the debugger.
Definition Kd.c:299
VOID SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:53
#define ScopedSpinlock(LockObject, CodeToRun)
Definition Spinlock.h:39
unsigned short UINT16
Definition BasicTypes.h:53
char CHAR
Definition BasicTypes.h:33
unsigned long ULONG
Definition BasicTypes.h:31
@ DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER
Definition Connection.h:178
@ DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_PAUSED_AND_CURRENT_INSTRUCTION
Definition Connection.h:113
struct _DEBUGGEE_KD_PAUSED_PACKET DEBUGGEE_KD_PAUSED_PACKET
The structure of pausing packet in kHyperDbg.
IMPORT_EXPORT_VMM UINT32 CheckAddressMaximumInstructionLength(PVOID Address)
This function returns the maximum instruction length that can be read from this address.
Definition AddressCheck.c:345
IMPORT_EXPORT_VMM UINT64 VmFuncGetRflags()
Read guest's RFLAGS.
Definition Export.c:397
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafeOnTargetProcess(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead)
IMPORT_EXPORT_VMM UINT64 VmFuncGetRip()
Read guest's RIP.
Definition Export.c:420
DEBUGGEE_PAUSING_REASON g_DebuggeeHaltReason
Reason that the debuggee is halted.
Definition Global.h:175
if(.test_var==4)
Definition script_conditional_statement_global_var.hds.hex.txt:6
BOOLEAN LockAgainAfterTask
Definition State.h:138
PVOID Context
Definition State.h:140
BOOLEAN PerformHaltedTask
Definition State.h:137
UINT64 TargetTask
Definition State.h:139
UINT16 ReadInstructionLen
Definition DataTypes.h:250
UINT64 Rip
Definition DataTypes.h:241
UINT64 Rflags
Definition DataTypes.h:248
BOOLEAN IsProcessorOn32BitMode
Definition DataTypes.h:242
DEBUGGEE_PAUSING_REASON PausingReason
Definition DataTypes.h:244
UINT64 EventTag
Definition DataTypes.h:246
ULONG CurrentCore
Definition DataTypes.h:245
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition DataTypes.h:249
BOOLEAN IgnoreDisassembling
Definition DataTypes.h:243
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE EventCallingStage
Definition DataTypes.h:247
UINT64 Tag
Definition DataTypes.h:226
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE Stage
Definition DataTypes.h:228
BOOLEAN IgnoreDisasmInNextPacket
Definition State.h:170
volatile BOOLEAN MainDebuggingCore
Definition State.h:166
UINT16 InstructionLengthHint
Definition State.h:182
DEBUGGEE_HALTED_CORE_TASK HaltedCoreTask
Definition State.h:181

◆ KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId()

BOOLEAN KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId ( UINT32 CoreId,
DEBUGGER_THREAD_PROCESS_TRACING TracingType )

Query for process/thread interception status.

Parameters
CoreId
TracingType
Returns
BOOLEAN whether it's activated or not
208{
209 BOOLEAN Result = FALSE;
210 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
211
212 switch (TracingType)
213 {
215
217
218 break;
219
221
223
224 break;
225
227
229
230 break;
231
233
235
236 break;
237
238 default:
239
240 LogError("Err, debugger encountered an unknown query type for querying process or thread interception details");
241
242 break;
243 }
244
245 return Result;
246}
@ DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_INTERRUPTS_FOR_THREAD_CHANGE
Definition DataTypes.h:139
@ DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_INTERRUPTS_FOR_PROCESS_CHANGE
Definition DataTypes.h:140
@ DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_DEBUG_REGISTER_INTERCEPTION
Definition DataTypes.h:141
@ DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_WAITING_FOR_MOV_CR3_VM_EXITS
Definition DataTypes.h:142
BOOLEAN InterceptClockInterruptsForProcessChange
Definition State.h:63
BOOLEAN DebugRegisterInterceptionState
Definition State.h:56
BOOLEAN IsWatingForMovCr3VmExits
Definition State.h:62
BOOLEAN InterceptClockInterruptsForThreadChange
Definition State.h:57
DEBUGGEE_PROCESS_OR_THREAD_TRACING_DETAILS ThreadOrProcessTracingDetails
Definition State.h:179

◆ KdQueryIgnoreHandlingMov2DebugRegs()

BOOLEAN KdQueryIgnoreHandlingMov2DebugRegs ( UINT32 CoreId)

Query to ignore handling mov 2 debug regs exiting.

Parameters
CoreId
Returns
BOOLEAN whether it's activated or not
256{
257 //
258 // Handle access to debug registers, if we should not ignore it, it is
259 // because on detecting thread scheduling we ignore the hardware debug
260 // registers modifications
261 //
264}
BOOLEAN KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32 CoreId, DEBUGGER_THREAD_PROCESS_TRACING TracingType)
Query for process/thread interception status.
Definition Kd.c:206

◆ KdResponsePacketToDebugger()

BOOLEAN KdResponsePacketToDebugger ( _In_ _Strict_type_match_ DEBUGGER_REMOTE_PACKET_TYPE PacketType,
_In_ _Strict_type_match_ DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION Response,
_In_reads_bytes_opt_(OptionalBufferLength) CHAR * OptionalBuffer,
_In_ UINT32 OptionalBufferLength )

◆ KdSendCommandFinishedSignal()

VOID KdSendCommandFinishedSignal ( UINT32 CoreId)

Notify debugger that the execution of command finished.

Parameters
CoreId
Returns
VOID
888{
889 //
890 // Halt other cores again
891 //
894 NULL);
895}
_Use_decl_annotations_ VOID KdHandleBreakpointAndDebugBreakpointsCallback(UINT32 CoreId, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle DBs and BPs for kernel debugger.
Definition Kd.c:1087
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_COMMAND_EXECUTION_FINISHED
Definition Connection.h:34

◆ KdSendFormatsFunctionResult()

VOID KdSendFormatsFunctionResult ( UINT64 Value)

Send the result of formats command to the kernel debugger.

Parameters
Value
Returns
VOID
864{
865 DEBUGGEE_FORMATS_PACKET FormatsPacket = {0};
866
868 FormatsPacket.Value = Value;
869
870 //
871 // Kernel debugger is active, we should send the bytes over serial
872 //
876 (CHAR *)&FormatsPacket,
878}
@ DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_FORMATS
Definition Connection.h:118
struct _DEBUGGEE_FORMATS_PACKET DEBUGGEE_FORMATS_PACKET
check so the INTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS should be smaller than packet size
RequestedActionOfThePacket Value(0x1) 00000000
UINT32 Result
Definition RequestStructures.h:1493
UINT64 Value
Definition RequestStructures.h:1492

◆ KdUninitializeKernelDebugger()

VOID KdUninitializeKernelDebugger ( )

uninitialize kernel debugger

this function should be called on vmx non-root

Returns
VOID
69{
70 ULONG ProcessorsCount;
71
73 {
74 ProcessorsCount = KeQueryActiveProcessorCount(0);
75
76 //
77 // Indicate that the kernel debugger is not active
78 //
80
81 //
82 // Reset pause break requests
83 //
85
86 //
87 // Remove all active breakpoints
88 //
90
91 //
92 // Disable vm-exit on Hardware debug exceptions and breakpoints
93 // so, not intercept #DBs and #BP by changing exception bitmap (one core)
94 //
96 }
97}
VOID BreakpointRemoveAllBreakpoints()
Remove all the breakpoints if possible.
Definition BreakpointCommands.c:859
IMPORT_EXPORT_VMM VOID BroadcastDisableDbAndBpExitingAllCores()
routines to unset vm-exit on all DBs and BP on all cores
Definition Broadcast.c:49

◆ KdUnlockTheHaltedCore()

VOID KdUnlockTheHaltedCore ( PROCESSOR_DEBUGGING_STATE * DbgState)

unlock the target core

Parameters
DbgStateThe state of the debugger on the target core
Returns
VOID
1779{
1780 SpinlockUnlock(&DbgState->Lock);
1781}
VOID SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:162

Variable Documentation

◆ DebuggerHandleBreakpointLock

volatile LONG DebuggerHandleBreakpointLock

Vmx-root lock for handling breaks to debugger.

◆ DebuggerResponseLock

volatile LONG DebuggerResponseLock

Vmx-root lock for sending response of debugger.