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

Commands for setting breakpoints. More...

Go to the source code of this file.

Functions

VOID BreakpointRemoveAllBreakpoints ()
 Remove all the breakpoints if possible.
 
BOOLEAN BreakpointAddNew (PDEBUGGEE_BP_PACKET BpDescriptorArg)
 Add new breakpoints.
 
BOOLEAN BreakpointListOrModify (PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints)
 List of modify breakpoints.
 
BOOLEAN BreakpointHandleBreakpoints (UINT32 CoreId)
 Handle breakpoint vm-exits (#BP)
 
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.
 
BOOLEAN BreakpointCheckAndHandleReApplyingBreakpoint (UINT32 CoreId)
 Check and reapply breakpoint.
 
BOOLEAN BreakpointCheckAndHandleDebugBreakpoint (UINT32 CoreId)
 Check and handle debug breakpoint exceptions.
 
BOOLEAN BreakpointRestoreTheTrapFlagOnceTriggered (UINT32 ProcessId, UINT32 ThreadId)
 This function makes sure to unset the RFLAGS.TF on next trigger of #DB on the target process/thread.
 

Variables

volatile LONG BreakpointCommandTrapListLock
 The lock for modifying list of process/thread for unsetting TRAP FLAG.
 

Detailed Description

Commands for setting breakpoints.

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

Function Documentation

◆ BreakpointAddNew()

BOOLEAN BreakpointAddNew ( PDEBUGGEE_BP_PACKET BpDescriptorArg)

Add new breakpoints.

Parameters
BpDescriptor
Returns
BOOLEAN
894{
895 PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL;
896 CR3_TYPE GuestCr3 = {0};
897 BOOLEAN IsAddress32Bit = FALSE;
898
899 //
900 // Find the current process cr3
901 //
903
904 //
905 // *** Validate arguments ***
906 //
907
908 //
909 // Check if address is safe (only one byte for 0xcc)
910 //
911 if (!CheckAccessValidityAndSafety(BpDescriptorArg->Address, sizeof(BYTE)))
912 {
914 return FALSE;
915 }
916
917 //
918 // Check if the core number is not invalid
919 //
920 if (BpDescriptorArg->Core != DEBUGGEE_BP_APPLY_TO_ALL_CORES &&
921 !CommonValidateCoreNumber(BpDescriptorArg->Core))
922 {
923 //
924 // Core is invalid (Set the error)
925 //
926 BpDescriptorArg->Result = DEBUGGER_ERROR_INVALID_CORE_ID;
927 return FALSE;
928 }
929
930 //
931 // Check if breakpoint already exists on list or not
932 //
933 if (BreakpointGetEntryByAddress(BpDescriptorArg->Address) != NULL)
934 {
935 //
936 // Address is already on the list (Set the error)
937 //
939 return FALSE;
940 }
941
942 //
943 // We won't check for process id and thread id, if these arguments are invalid
944 // then the HyperDbg simply ignores the breakpoints but it makes the computer slow
945 // it just won't be triggered
946 //
947
948 //
949 // When we reach here means that the arguments are valid and address is
950 // safe to access (put 0xcc)
951 //
952
953 //
954 // Get the pre-allocated buffer
955 //
957
958 if (BreakpointDescriptor == NULL)
959 {
960 //
961 // No pool ! Probably the user set more than MAXIMUM_BREAKPOINTS_WITHOUT_CONTINUE
962 // pools without IOCTL (continue)
963 //
965 return FALSE;
966 }
967
968 //
969 // Copy details of breakpoint to the descriptor structure
970 //
972 BreakpointDescriptor->BreakpointId = g_MaximumBreakpointId;
973 BreakpointDescriptor->Address = BpDescriptorArg->Address;
974 BreakpointDescriptor->PhysAddress = VirtualAddressToPhysicalAddressByProcessCr3((PVOID)BpDescriptorArg->Address,
975 GuestCr3);
976 BreakpointDescriptor->Core = BpDescriptorArg->Core;
977 BreakpointDescriptor->Pid = BpDescriptorArg->Pid;
978 BreakpointDescriptor->Tid = BpDescriptorArg->Tid;
979 BreakpointDescriptor->RemoveAfterHit = BpDescriptorArg->RemoveAfterHit;
980 BreakpointDescriptor->CheckForCallbacks = BpDescriptorArg->CheckForCallbacks;
981
982 //
983 // Check whether address is 32-bit or 64-bit
984 //
985 if (BpDescriptorArg->Address & 0xff00000000000000)
986 {
987 //
988 // This is a kernel-base address and as the kernel is 64-bit, we assume it's a 64-bit address
989 //
990 IsAddress32Bit = FALSE;
991 }
992 else
993 {
994 //
995 // The address is not a kernel address, thus, we check whether the debuggee is running on user-mode
996 // or not
997 //
998 IsAddress32Bit = KdIsGuestOnUsermode32Bit();
999 }
1000
1001 //
1002 // Use length disassembler engine to get the instruction length
1003 //
1005 (PVOID)BpDescriptorArg->Address,
1006 IsAddress32Bit);
1007
1008 //
1009 // Breakpoints are enabled by default
1010 //
1011 BreakpointDescriptor->Enabled = TRUE;
1012
1013 //
1014 // Now we should add the breakpoint to the list of breakpoints (LIST_ENTRY)
1015 //
1016 InsertHeadList(&g_BreakpointsListHead, &(BreakpointDescriptor->BreakpointsList));
1017
1018 //
1019 // Apply the breakpoint
1020 //
1021 BreakpointWrite(BreakpointDescriptor);
1022
1023 //
1024 // Show that operation was successful
1025 //
1026 BpDescriptorArg->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1027
1028 return TRUE;
1029}
BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:156
unsigned short UINT16
Definition BasicTypes.h:47
UCHAR BOOLEAN
Definition BasicTypes.h:39
unsigned char BYTE
Definition BasicTypes.h:24
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
BOOLEAN BreakpointWrite(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor)
writes the 0xcc and applies the breakpoint @detail this function won't remove the descriptor from the...
Definition BreakpointCommands.c:762
PDEBUGGEE_BP_DESCRIPTOR BreakpointGetEntryByAddress(UINT64 Address)
Find entry of breakpoint descriptor from list of breakpoints by address.
Definition BreakpointCommands.c:863
#define DEBUGGEE_BP_APPLY_TO_ALL_CORES
The constant to apply to all cores for bp command.
Definition Constants.h:647
_Use_decl_annotations_ UINT64 VirtualAddressToPhysicalAddressByProcessCr3(PVOID VirtualAddress, CR3_TYPE TargetCr3)
Converts Virtual Address to Physical Address based on a specific process's kernel cr3.
Definition Conversion.c:215
@ BREAKPOINT_DEFINITION_STRUCTURE
Definition DataTypes.h:45
UINT32 DisassemblerLengthDisassembleEngineInVmxRootOnTargetProcess(PVOID Address, BOOLEAN Is32Bit)
Disassembler length disassembler engine.
Definition Disassembler.c:297
#define DEBUGGER_ERROR_MAXIMUM_BREAKPOINT_WITHOUT_CONTINUE
error, maximum pools were used without continuing debuggee
Definition ErrorCodes.h:184
#define DEBUGGER_ERROR_BREAKPOINT_ALREADY_EXISTS_ON_THE_ADDRESS
error, breakpoint already exists on the target address
Definition ErrorCodes.h:190
#define DEBUGGER_ERROR_INVALID_CORE_ID
error, the core id is invalid
Definition ErrorCodes.h:69
#define DEBUGGER_ERROR_EDIT_MEMORY_STATUS_INVALID_ADDRESS_BASED_ON_CURRENT_PROCESS
error, an invalid address is specified based on current cr3 in !e* or e* commands
Definition ErrorCodes.h:106
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
BOOLEAN KdIsGuestOnUsermode32Bit()
determines if the guest was in 32-bit user-mode or 64-bit (long mode)
Definition Kd.c:3107
CR3_TYPE LayoutGetCurrentProcessCr3()
Get cr3 of the target running process.
Definition Layout.c:55
UINT64 PoolManagerRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size)
This function should be called from vmx-root in order to get a pool from the list.
Definition PoolManager.c:212
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ PLIST_ENTRY Entry)
Definition Windows.h:115
_Use_decl_annotations_ BOOLEAN CommonValidateCoreNumber(UINT32 CoreNumber)
Validate core number.
Definition Common.c:256
LIST_ENTRY g_BreakpointsListHead
List header of breakpoints for debugger-mode.
Definition Global.h:91
UINT64 g_MaximumBreakpointId
Seed for setting id of breakpoints.
Definition Global.h:97
NULL()
Definition test-case-generator.py:530
CR3 Structure.
Definition BasicTypes.h:130
UINT64 Flags
Definition BasicTypes.h:133
The structure of storing breakpoints.
Definition State.h:72
UINT64 BreakpointId
Definition State.h:73
BOOLEAN RemoveAfterHit
Definition State.h:85
BOOLEAN CheckForCallbacks
Definition State.h:86
UINT16 InstructionLength
Definition State.h:81
UINT64 Address
Definition State.h:76
LIST_ENTRY BreakpointsList
Definition State.h:74
BOOLEAN Enabled
Definition State.h:75
UINT64 PhysAddress
Definition State.h:77
UINT32 Pid
Definition State.h:78
UINT32 Tid
Definition State.h:79
UINT32 Core
Definition State.h:80
UINT32 Tid
Definition RequestStructures.h:1063
UINT32 Result
Definition RequestStructures.h:1067
BOOLEAN RemoveAfterHit
Definition RequestStructures.h:1065
UINT32 Core
Definition RequestStructures.h:1064
BOOLEAN CheckForCallbacks
Definition RequestStructures.h:1066
UINT64 Address
Definition RequestStructures.h:1061
UINT32 Pid
Definition RequestStructures.h:1062

◆ BreakpointCheckAndHandleDebugBreakpoint()

BOOLEAN BreakpointCheckAndHandleDebugBreakpoint ( UINT32 CoreId)

Check and handle debug breakpoint exceptions.

Parameters
CoreId
Returns
BOOLEAN
239{
240 BOOLEAN TrapSetByDebugger;
241 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
242 BOOLEAN HandledByDebuggerRoutines = TRUE;
243
244 //
245 // *** Check whether anything should be changed with trap-flags
246 // and also it indicates whether the debugger itself set this trap
247 // flag or it's not supposed to be set by the debugger ***
248 //
250 HANDLE_TO_UINT32(PsGetCurrentThreadId()),
251 &TrapSetByDebugger))
252 {
254 {
255 //
256 // This check was to show whether it is because of thread change detection or not
257 //
258
259 // This way of handling has a problem, if the user set to change
260 // the thread and instead of using 'g', it pressed the 'p' to
261 // set or a trap happens somewhere then will be ignored
262 // it because we don't know the origin of this debug breakpoint
263 // and it only happens on '.thread2' command, the correct way
264 // to handle it is to find the exact hw debug register that caused
265 // this vm-exit, but it's a really rare case, so we left it without
266 // handling this case
267 //
268 ThreadHandleThreadChange(DbgState);
269 }
270 else if (g_UserDebuggerState == TRUE &&
272 {
273 //
274 // Handle for user-mode attaching mechanism
275 //
277 }
278 else if (g_KernelDebuggerState == TRUE)
279 {
280 //
281 // Here we added the handler for the kernel because we want
282 // stepping routines to work, even if the debugger masks the
283 // traps by using 'test trap off', so stepping still works
284 //
285
286
287 //
288 // Handle debug events (breakpoint, traps, hardware debug register when kernel
289 // debugger is attached)
290 //
291 KdHandleDebugEventsWhenKernelDebuggerIsAttached(DbgState, TrapSetByDebugger);
292 }
295 NULL))
296 {
297 //
298 // if the above function returns true, no need for further action
299 // it's handled in the user debugger
300 //
301 }
302 else
303 {
304 //
305 // Here it means that the trap is supposed to be handled by
306 // HyperDbg but, we couldn't find any routines that gonna
307 // handle it (it's probably an error)
308 //
309 HandledByDebuggerRoutines = FALSE;
310 LogError("Err, trap is supposed to be handled by the debugger, but none of routines handled it");
311 }
312 }
313 else
314 {
315 //
316 // *** it's not supposed to be handled by the debugger routines, the guest
317 // or the target debuggee throws a debug break (#DB) ***
318 //
319
320 //
321 // It means that it's not handled by the debugger routines
322 // By default HyperDbg intercepts all #DBs and break the debugger if
323 // it's attached to the debugger, otherwise injects to the guest VM
324 //
326 {
327 //
328 // The user explicitly told the debugger not to intercept any
329 // traps (e.g., by using 'test trap off')
330 //
331 HandledByDebuggerRoutines = FALSE;
332 }
333 else if (g_KernelDebuggerState == TRUE)
334 {
335 //
336 // Handle debug events (breakpoint, traps, hardware debug register when kernel
337 // debugger is attached)
338 //
339 KdHandleDebugEventsWhenKernelDebuggerIsAttached(DbgState, TrapSetByDebugger);
340 }
343 NULL))
344 {
345 //
346 // if the above function returns true, no need for further action
347 // it's handled in the user debugger
348 //
349 }
350 else
351 {
352 //
353 // Inject to back to the guest as it's not either handled by the kernel debugger
354 // routines or the user debugger
355 //
356 HandledByDebuggerRoutines = FALSE;
357 }
358 }
359
360 return HandledByDebuggerRoutines;
361}
VOID AttachingHandleEntrypointInterception(PROCESSOR_DEBUGGING_STATE *DbgState)
Handle the interception of finding the entrypoint on attaching to user-mode process.
Definition Attaching.c:436
BOOLEAN BreakpointCheckAndPerformActionsOnTrapFlags(UINT32 ProcessId, UINT32 ThreadId, BOOLEAN *TrapSetByDebugger)
Check and perform actions on RFLAGS.TF.
Definition BreakpointCommands.c:23
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK
Definition Connection.h:41
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
VOID KdHandleDebugEventsWhenKernelDebuggerIsAttached(PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN TrapSetByDebugger)
Handles debug events when kernel-debugger is attached.
Definition Kd.c:426
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
BOOLEAN ThreadHandleThreadChange(PROCESSOR_DEBUGGING_STATE *DbgState)
handle thread changes
Definition Thread.c:22
BOOLEAN UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle #DBs and #BPs for kernel debugger.
Definition Ud.c:443
BOOLEAN g_IsWaitingForReturnAndRunFromPageFault
Whether the thread attaching mechanism is waiting for a page-fault finish or not.
Definition Global.h:146
BOOLEAN g_InterceptDebugBreaks
shows whether the debugger should intercept breakpoints (#DB) or not
Definition Global.h:121
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
BOOLEAN g_UserDebuggerState
shows whether the user debugger is enabled or disabled
Definition Global.h:109
BOOLEAN g_KernelDebuggerState
shows whether the kernel debugger is enabled or disabled
Definition Global.h:103
BOOLEAN g_IsWaitingForUserModeProcessEntryToBeCalled
Whether the thread attaching mechanism is waiting for #DB or not.
Definition Global.h:158
BOOLEAN DebugRegisterInterceptionState
Definition State.h:56
Saves the debugger state.
Definition State.h:165
DEBUGGEE_PROCESS_OR_THREAD_TRACING_DETAILS ThreadOrProcessTracingDetails
Definition State.h:178

◆ BreakpointCheckAndHandleDebuggerDefinedBreakpoints()

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.

Parameters
DbgStateThe state of the debugger on the current core
GuestRip
Reason
ChangeMtfState
Returns
BOOLEAN
501{
502 CR3_TYPE GuestCr3 = {0};
503 BOOLEAN IsHandledByBpRoutines = FALSE;
504 PLIST_ENTRY TempList = 0;
505 UINT64 GuestRipPhysical = (UINT64)NULL;
506 DEBUGGER_TRIGGERED_EVENT_DETAILS TargetContext = {0};
507 RFLAGS Rflags = {0};
508 BOOLEAN AvoidUnsetMtf = FALSE;
509 BOOLEAN IgnoreUserHandling = FALSE;
510
511 //
512 // ***** Check breakpoint for 'bp' command *****
513 //
514
515 //
516 // Find the current process cr3
517 //
519
520 //
521 // Convert breakpoint to physical address
522 //
523 GuestRipPhysical = VirtualAddressToPhysicalAddressByProcessCr3((PVOID)GuestRip, GuestCr3);
524
525 //
526 // Iterate through the list of breakpoints
527 //
528 TempList = &g_BreakpointsListHead;
529
530 while (&g_BreakpointsListHead != TempList->Flink)
531 {
532 TempList = TempList->Flink;
533 PDEBUGGEE_BP_DESCRIPTOR CurrentBreakpointDesc = CONTAINING_RECORD(TempList, DEBUGGEE_BP_DESCRIPTOR, BreakpointsList);
534
535 if (CurrentBreakpointDesc->PhysAddress == GuestRipPhysical)
536 {
537 //
538 // It's a breakpoint by 'bp' command
539 //
540 IsHandledByBpRoutines = TRUE;
541
542 //
543 // First, we remove the breakpoint
544 //
546 (UINT64)&CurrentBreakpointDesc->PreviousByte,
547 sizeof(BYTE));
548
549 //
550 // Now, halt the debuggee
551 //
552 TargetContext.Context = (PVOID)VmFuncGetLastVmexitRip(DbgState->CoreId);
553
554 //
555 // In breakpoints tag is breakpoint id, not event tag
556 //
558 {
559 TargetContext.Tag = CurrentBreakpointDesc->BreakpointId;
560 }
561
562 //
563 // Hint the debuggee about the length
564 //
565 DbgState->InstructionLengthHint = CurrentBreakpointDesc->InstructionLength;
566
567 //
568 // Check constraints
569 //
570 if ((CurrentBreakpointDesc->Pid == DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES || CurrentBreakpointDesc->Pid == HANDLE_TO_UINT32(PsGetCurrentProcessId())) &&
571 (CurrentBreakpointDesc->Tid == DEBUGGEE_BP_APPLY_TO_ALL_THREADS || CurrentBreakpointDesc->Tid == HANDLE_TO_UINT32(PsGetCurrentThreadId())) &&
572 (CurrentBreakpointDesc->Core == DEBUGGEE_BP_APPLY_TO_ALL_CORES || CurrentBreakpointDesc->Core == DbgState->CoreId))
573 {
574 //
575 // Check if breakpoint should be removed after this hit or not
576 //
577 if (CurrentBreakpointDesc->RemoveAfterHit)
578 {
579 //
580 // One hit, we have to remove it
581 //
582 BreakpointClearAndDeallocateMemory(CurrentBreakpointDesc);
583 }
584
585 //
586 // Check if it needs to check for callbacks or not
587 //
588 if (CurrentBreakpointDesc->CheckForCallbacks)
589 {
590 //
591 // check callbacks
592 //
593 IgnoreUserHandling = BreakpointTriggerCallbacks(DbgState, HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId()));
594 }
595
596 //
597 // Check if we need to handle the breakpoint by user or just ignore handling it
598 //
600 {
601 //
602 // *** It's not safe to access CurrentBreakpointDesc anymore as the
603 // breakpoint might be removed ***
604 //
606 Reason,
607 &TargetContext);
608 }
609 }
610
611 //
612 // Reset hint to instruction length
613 //
614 DbgState->InstructionLengthHint = 0;
615
616 //
617 // Check if we should re-apply the breakpoint after this instruction
618 // or not (in other words, is breakpoint still valid)
619 //
620 if (!CurrentBreakpointDesc->AvoidReApplyBreakpoint)
621 {
622 //
623 // We should re-apply the breakpoint on next mtf
624 //
625 DbgState->SoftwareBreakpointState = CurrentBreakpointDesc;
626
627 //
628 // Fire and MTF
629 //
631 AvoidUnsetMtf = TRUE;
632
633 //
634 // As we want to continue debuggee, the MTF might arrive when the
635 // host finish executing it's time slice; thus, a clock interrupt
636 // or an IPI might be arrived and the next instruction is not what
637 // we expect, because of that we check if the IF (Interrupt enable)
638 // flag of RFLAGS is enabled or not, if enabled then we remove it
639 // to avoid any clock-interrupt or IPI to arrive and the next
640 // instruction is our next instruction in the current execution
641 // context
642 //
643 Rflags.AsUInt = VmFuncGetRflags();
644
645 if (Rflags.InterruptEnableFlag)
646 {
647 Rflags.InterruptEnableFlag = FALSE;
648 VmFuncSetRflags(Rflags.AsUInt);
649
650 //
651 // An indicator to restore RFLAGS if to enabled state
652 //
654 }
655 }
656
657 //
658 // Do not increment rip
659 //
661
662 //
663 // No need to iterate anymore
664 //
665 break;
666 }
667 }
668
669 if (IsHandledByBpRoutines && ChangeMtfState)
670 {
671 VmFuncChangeMtfUnsettingState(DbgState->CoreId, AvoidUnsetMtf);
672 }
673
674 return IsHandledByBpRoutines;
675}
unsigned __int64 UINT64
Definition BasicTypes.h:21
VOID BreakpointClearAndDeallocateMemory(PDEBUGGEE_BP_DESCRIPTOR BreakpointDesc)
Clears the breakpoint and remove the entry from the breakpoint list.
Definition BreakpointCommands.c:416
BOOLEAN BreakpointTriggerCallbacks(PROCESSOR_DEBUGGING_STATE *DbgState, UINT32 ProcessId, UINT32 ThreadId)
Trigger callback for breakpoint hit.
Definition BreakpointCommands.c:148
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_SOFTWARE_BREAKPOINT_HIT
Definition Connection.h:29
#define DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES
The constant to apply to all processes for bp command.
Definition Constants.h:653
#define DEBUGGEE_BP_APPLY_TO_ALL_THREADS
The constant to apply to all threads for bp command.
Definition Constants.h:659
VOID VmFuncChangeMtfUnsettingState(UINT32 CoreId, BOOLEAN Set)
Suppress unsetting MTF.
Definition Export.c:47
VOID VmFuncSetRflags(UINT64 Rflags)
Set guest's RFLAGS.
Definition Export.c:364
UINT64 VmFuncGetRflags()
Read guest's RFLAGS.
Definition Export.c:352
VOID VmFuncSetMonitorTrapFlag(BOOLEAN Set)
Set the monitor trap flag.
Definition Export.c:98
UINT64 VmFuncGetLastVmexitRip(UINT32 CoreId)
get the last vm-exit RIP
Definition Export.c:318
VOID VmFuncSuppressRipIncrement(UINT32 CoreId)
Suppress the incrementation of RIP.
Definition Export.c:34
_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:1214
_Use_decl_annotations_ BOOLEAN MemoryMapperWriteMemorySafeByPhysicalAddress(UINT64 DestinationPa, UINT64 Source, SIZE_T SizeToWrite)
Write memory safely by mapping the buffer.
Definition MemoryMapper.c:1432
BOOLEAN g_InterceptBreakpoints
shows whether the debugger should intercept breakpoints (#BP) or not
Definition Global.h:115
BOOLEAN g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer
To avoid getting stuck from getting hit from the breakpoints while executing the commands in the remo...
Definition Global.h:166
BYTE PreviousByte
Definition State.h:82
BOOLEAN SetRflagsIFBitOnMtf
Definition State.h:83
BOOLEAN AvoidReApplyBreakpoint
Definition State.h:84
The structure of detail of a triggered event in HyperDbg.
Definition DataTypes.h:192
UINT64 Tag
Definition DataTypes.h:193
PVOID Context
Definition DataTypes.h:194
UINT32 CoreId
Definition State.h:169
UINT16 InstructionLengthHint
Definition State.h:182
PDEBUGGEE_BP_DESCRIPTOR SoftwareBreakpointState
Definition State.h:174

◆ BreakpointCheckAndHandleReApplyingBreakpoint()

BOOLEAN BreakpointCheckAndHandleReApplyingBreakpoint ( UINT32 CoreId)

Check and reapply breakpoint.

Parameters
CoreId
Returns
BOOLEAN
443{
444 BOOLEAN Result = FALSE;
445 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
446
447 if (DbgState->SoftwareBreakpointState != NULL)
448 {
449 BYTE BreakpointByte = 0xcc;
450
451 //
452 // MTF is handled
453 //
454 Result = TRUE;
455
456 //
457 // Restore previous breakpoint byte
458 //
461 (UINT64)&BreakpointByte,
462 sizeof(BYTE));
463
464 //
465 // Check if we should re-enabled IF bit of RFLAGS or not
466 //
468 {
469 RFLAGS Rflags = {0};
470
471 Rflags.AsUInt = VmFuncGetRflags();
472
473 Rflags.InterruptEnableFlag = TRUE;
474
475 VmFuncSetRflags(Rflags.AsUInt);
476
478 }
479
480 DbgState->SoftwareBreakpointState = NULL;
481 }
482
483 return Result;
484}

◆ BreakpointHandleBreakpoints()

BOOLEAN BreakpointHandleBreakpoints ( UINT32 CoreId)

Handle breakpoint vm-exits (#BP)

Parameters
CoreId
Returns
BOOLEAN
686{
687 DEBUGGER_TRIGGERED_EVENT_DETAILS TargetContext = {0};
688 UINT64 GuestRip = 0;
689 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
690
691 //
692 // re-inject #BP back to the guest if not handled by the hidden breakpoint
693 //
694
696 {
697 //
698 // Kernel debugger is attached, let's halt everything
699 //
700 GuestRip = VmFuncGetRip();
701
702 //
703 // A breakpoint triggered and two things might be happened,
704 // first, a breakpoint is triggered randomly in the computer and
705 // we shouldn't do anything on it (won't change the instruction)
706 // second, the breakpoint is because of the 'bp' command, we should
707 // replace it with exact byte
708 //
709
711 GuestRip,
713 FALSE))
714 {
715 //
716 // To avoid the computer crash situation from the HyperDbg's breakpoint hitting while the interception is on
717 // we should always call BreakpointCheckAndHandleDebuggerDefinedBreakpoints first to handle the breakpoint
718 //
719
721 {
722 //
723 // re-inject back to the guest as not handled if the interception is on and the breakpoint is not from the Hyperdbg's breakpoints
724 //
725 return FALSE;
726 }
727
728 //
729 // It's a random breakpoint byte
730 //
731 TargetContext.Context = (PVOID)GuestRip;
734 &TargetContext);
735
736 //
737 // Increment rip
738 //
740 }
741 }
742 else
743 {
744 //
745 // re-inject back to the guest as not handled here
746 //
747 return FALSE;
748 }
749
750 return TRUE;
751}
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:497
VOID VmFuncPerformRipIncrement(UINT32 CoreId)
Perform the incrementation of RIP.
Definition Export.c:22
UINT64 VmFuncGetRip()
Read guest's RIP.
Definition Export.c:375

◆ BreakpointListOrModify()

BOOLEAN BreakpointListOrModify ( PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET ListOrModifyBreakpoints)

List of modify breakpoints.

Parameters
ListOrModifyBreakpoints
Returns
BOOLEAN
1090{
1091 PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor = NULL;
1092
1094 {
1096 }
1097 else if (ListOrModifyBreakpoints->Request == DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_ENABLE)
1098 {
1099 BreakpointDescriptor = BreakpointGetEntryByBreakpointId(ListOrModifyBreakpoints->BreakpointId);
1100
1101 if (BreakpointDescriptor == NULL)
1102 {
1103 //
1104 // Breakpoint id is invalid
1105 //
1106 ListOrModifyBreakpoints->Result = DEBUGGER_ERROR_BREAKPOINT_ID_NOT_FOUND;
1107 return FALSE;
1108 }
1109
1110 //
1111 // Check to make sure that breakpoint is not already enabled
1112 //
1113 if (BreakpointDescriptor->Enabled)
1114 {
1115 ListOrModifyBreakpoints->Result = DEBUGGER_ERROR_BREAKPOINT_ALREADY_ENABLED;
1116 return FALSE;
1117 }
1118
1119 //
1120 // Set the breakpoint (without removing from list)
1121 //
1122 BreakpointWrite(BreakpointDescriptor);
1123 }
1124 else if (ListOrModifyBreakpoints->Request == DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_DISABLE)
1125 {
1126 BreakpointDescriptor = BreakpointGetEntryByBreakpointId(ListOrModifyBreakpoints->BreakpointId);
1127
1128 if (BreakpointDescriptor == NULL)
1129 {
1130 //
1131 // Breakpoint id is invalid
1132 //
1133 ListOrModifyBreakpoints->Result = DEBUGGER_ERROR_BREAKPOINT_ID_NOT_FOUND;
1134 return FALSE;
1135 }
1136
1137 //
1138 // Check to make sure that breakpoint is not already disabled
1139 //
1140 if (!BreakpointDescriptor->Enabled)
1141 {
1142 ListOrModifyBreakpoints->Result = DEBUGGER_ERROR_BREAKPOINT_ALREADY_DISABLED;
1143 return FALSE;
1144 }
1145
1146 //
1147 // Unset the breakpoint (without removing from list)
1148 //
1149 BreakpointClear(BreakpointDescriptor);
1150 }
1151 else if (ListOrModifyBreakpoints->Request == DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_CLEAR)
1152 {
1153 BreakpointDescriptor = BreakpointGetEntryByBreakpointId(ListOrModifyBreakpoints->BreakpointId);
1154
1155 if (BreakpointDescriptor == NULL)
1156 {
1157 //
1158 // Breakpoint id is invalid
1159 //
1160 ListOrModifyBreakpoints->Result = DEBUGGER_ERROR_BREAKPOINT_ID_NOT_FOUND;
1161 return FALSE;
1162 }
1163
1164 //
1165 // Clear and deallocate the breakpoint
1166 //
1167 BreakpointClearAndDeallocateMemory(BreakpointDescriptor);
1168 }
1169
1170 //
1171 // Operation was successful
1172 //
1173 ListOrModifyBreakpoints->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1174
1175 return TRUE;
1176}
PDEBUGGEE_BP_DESCRIPTOR BreakpointGetEntryByBreakpointId(UINT64 BreakpointId)
Find entry of breakpoint descriptor from list of breakpoints by breakpoint id.
Definition BreakpointCommands.c:832
VOID BreakpointListAllBreakpoint()
List all breakpoints.
Definition BreakpointCommands.c:1037
BOOLEAN BreakpointClear(PDEBUGGEE_BP_DESCRIPTOR BreakpointDescriptor)
clears the 0xcc and removes the breakpoint @detail this function won't remove the descriptor from the...
Definition BreakpointCommands.c:371
#define DEBUGGER_ERROR_BREAKPOINT_ID_NOT_FOUND
error, breakpoint id not found
Definition ErrorCodes.h:196
#define DEBUGGER_ERROR_BREAKPOINT_ALREADY_DISABLED
error, breakpoint already disabled
Definition ErrorCodes.h:202
#define DEBUGGER_ERROR_BREAKPOINT_ALREADY_ENABLED
error, breakpoint already enabled
Definition ErrorCodes.h:208
@ DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_DISABLE
Definition RequestStructures.h:1080
@ DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_LIST_BREAKPOINTS
Definition RequestStructures.h:1078
@ DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_ENABLE
Definition RequestStructures.h:1079
@ DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST_CLEAR
Definition RequestStructures.h:1081
UINT64 BreakpointId
Definition RequestStructures.h:1091
UINT32 Result
Definition RequestStructures.h:1093
DEBUGGEE_BREAKPOINT_MODIFICATION_REQUEST Request
Definition RequestStructures.h:1092

◆ BreakpointRemoveAllBreakpoints()

VOID BreakpointRemoveAllBreakpoints ( )

Remove all the breakpoints if possible.

Returns
VOID
804{
805 PLIST_ENTRY TempList = 0;
806
807 //
808 // Iterate through the list of breakpoints
809 //
810 TempList = &g_BreakpointsListHead;
811
812 while (&g_BreakpointsListHead != TempList->Flink)
813 {
814 TempList = TempList->Flink;
815 PDEBUGGEE_BP_DESCRIPTOR CurrentBreakpointDesc = CONTAINING_RECORD(TempList, DEBUGGEE_BP_DESCRIPTOR, BreakpointsList);
816
817 //
818 // Clear and deallocate the breakpoint
819 //
820 BreakpointClearAndDeallocateMemory(CurrentBreakpointDesc);
821 }
822}

◆ BreakpointRestoreTheTrapFlagOnceTriggered()

BOOLEAN BreakpointRestoreTheTrapFlagOnceTriggered ( UINT32 ProcessId,
UINT32 ThreadId )

This function makes sure to unset the RFLAGS.TF on next trigger of #DB on the target process/thread.

Parameters
ProcessId
ThreadId
Returns
BOOLEAN
175{
176 UINT32 Index;
177 BOOLEAN Result;
178 BOOLEAN SuccessfullyStored;
179 DEBUGGER_PROCESS_THREAD_INFORMATION ProcThrdInfo = {0};
180
181 //
182 // Form the process id and thread id into a 64-bit value
183 //
184 ProcThrdInfo.Fields.ProcessId = ProcessId;
185 ProcThrdInfo.Fields.ThreadId = ThreadId;
186
187 //
188 // Make sure, nobody is in the middle of modifying the list
189 //
191
192 //
193 // *** Search the list of processes/threads for the current process's trap flag state ***
194 //
197 &Index,
198 ProcThrdInfo.asUInt);
199
200 if (Result)
201 {
202 //
203 // It means that we already find this entry in the stored list
204 // so, just imply that the addition was successful (no need for extra addition)
205 //
206 SuccessfullyStored = TRUE;
207 goto Return;
208 }
209 else
210 {
211 //
212 // Insert the thread into the list as the item is not already present
213 //
217 ProcThrdInfo.asUInt);
218 goto Return;
219 }
220
221Return:
222 //
223 // Unlock the list modification lock
224 //
226
227 return SuccessfullyStored;
228}
unsigned int UINT32
Definition BasicTypes.h:48
BOOLEAN BinarySearchPerformSearchItem(UINT64 ArrayPtr[], UINT32 NumberOfItems, UINT32 *ResultIndex, UINT64 Key)
A utility function to perform the binary search.
Definition BinarySearch.c:46
volatile LONG BreakpointCommandTrapListLock
The lock for modifying list of process/thread for unsetting TRAP FLAG.
Definition BreakpointCommands.h:22
#define MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS
maximum number of thread/process ids to be allocated for a simultaneous debugging
Definition Constants.h:407
BOOLEAN InsertionSortInsertItem(UINT64 ArrayPtr[], UINT32 *NumberOfItems, UINT32 MaxNumOfItems, UINT64 Key)
Function to implement insertion sort.
Definition InsertionSort.c:24
void SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:52
void SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:158
DEBUGGER_TRAP_FLAG_STATE g_TrapFlagState
State of the trap-flag.
Definition Global.h:29
The thread/process information.
Definition State.h:106
UINT64 asUInt
Definition State.h:109
UINT32 ProcessId
Definition State.h:113
struct _DEBUGGER_PROCESS_THREAD_INFORMATION::@49::@51 Fields
UINT32 ThreadId
Definition State.h:114
DEBUGGER_PROCESS_THREAD_INFORMATION ThreadInformation[MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS]
Definition State.h:128
UINT32 NumberOfItems
Definition State.h:127

Variable Documentation

◆ BreakpointCommandTrapListLock

volatile LONG BreakpointCommandTrapListLock

The lock for modifying list of process/thread for unsetting TRAP FLAG.