HyperDbg Debugger
Loading...
Searching...
No Matches
Ud.c File Reference

Routines related to user mode debugging. More...

#include "pch.h"

Functions

BOOLEAN UdInitializeUserDebugger ()
 initialize user debugger
VOID UdUninitializeUserDebugger ()
 uninitialize user debugger
BOOLEAN UdHandleInstantBreak (PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
 Handle cases where we instant break is needed on the user debugger.
VOID UdApplyHardwareDebugRegister (PVOID TargetAddress)
 Apply hardware debug registers to all cores.
VOID UdSendFormatsFunctionResult (UINT64 Value)
 Send the result of formats command to the user debugger.
VOID UdBroadcastSetHardwareDebugRegistersAllCores (PVOID TargetAddress)
 routines to broadcast setting hardware debug registers on all cores
VOID UdRegularStepOver (UINT64 LastRip, BOOLEAN IsNextInstructionACall, UINT32 CallLength)
 Regular step-over, step one instruction to the debuggee on user debugger if there is a call then it jumps the call.
BOOLEAN UdHandleDebugEventsWhenUserDebuggerIsAttached (PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN TrapSetByDebugger)
 Handles debug events when user-debugger is attached.
VOID UdStepInstructions (PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGER_REMOTE_STEPPING_REQUEST SteppingType, BOOLEAN IsCurrentInstructionACall, UINT32 CallInstructionSize)
 Perform stepping though the instructions in the target thread.
VOID UdReadRegisters (PROCESSOR_DEBUGGING_STATE *DbgState, UINT32 RegisterId)
 Perform reading register(s) in the target thread.
VOID UdRunScript (PROCESSOR_DEBUGGING_STATE *DbgState)
 Perform running script in the target thread.
BOOLEAN UdPerformCommand (PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGER_UD_COMMAND_ACTION_TYPE UserAction, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3, UINT64 OptionalParam4)
 Perform the user-mode commands.
BOOLEAN UdCheckForCommand (PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
 Check for the user-mode commands.
BOOLEAN UdDispatchUsermodeCommands (PDEBUGGER_UD_COMMAND_PACKET ActionRequest, UINT32 ActionRequestInputLength, UINT32 ActionRequestOutputLength)
 Dispatch the user-mode commands.
VOID UdSetThreadPausingState (PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails, PVOID InstructionBytesBuffer, UINT32 SizeOfInstruction)
 Set the thread pausing state.
VOID UdPrePausingReasons (PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
 Handle special reasons pre-pausings.
BOOLEAN UdCheckAndHandleBreakpointsAndDebugBreaks (PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
 Handle #DBs and #BPs for kernel debugger.

Detailed Description

Routines related to user mode debugging.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2022-01-06

Function Documentation

◆ UdApplyHardwareDebugRegister()

VOID UdApplyHardwareDebugRegister ( PVOID TargetAddress)

Apply hardware debug registers to all cores.

Parameters
TargetAddress
Returns
VOID
181{
184 FALSE,
185 (UINT64)TargetAddress);
186}
#define FALSE
Definition BasicTypes.h:113
@ 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
#define DEBUGGER_DEBUG_REGISTER_FOR_STEP_OVER
debug register for step-over
Definition Debugger.h:21

◆ UdBroadcastSetHardwareDebugRegistersAllCores()

VOID UdBroadcastSetHardwareDebugRegistersAllCores ( PVOID TargetAddress)

routines to broadcast setting hardware debug registers on all cores

Parameters
TargetAddress
Returns
VOID
209{
210 //
211 // Broadcast to all cores
212 //
213 KeGenericCallDpc(DpcRoutineSetHardwareDebugRegisters, TargetAddress);
214}
BOOLEAN DpcRoutineSetHardwareDebugRegisters(KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Broadcast applying hardware debug register.
Definition DpcRoutines.c:276

◆ UdCheckAndHandleBreakpointsAndDebugBreaks()

BOOLEAN UdCheckAndHandleBreakpointsAndDebugBreaks ( PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGEE_PAUSING_REASON Reason,
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails )

Handle #DBs and #BPs for kernel debugger.

This function can be used in vmx-root

Parameters
DbgStateThe state of the debugger on the current core
Reason
EventDetails
Returns
BOOLEAN
815{
816 DEBUGGEE_UD_PAUSED_PACKET PausePacket;
817 ULONG ExitInstructionLength = 0;
818 UINT32 SizeOfSafeBufferToRead = 0;
819 RFLAGS Rflags = {0};
820 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails = NULL;
821 PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails = NULL;
822 UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(DbgState->CoreId);
823
824 //
825 // Breaking only supported if user-debugger is loaded
826 //
828 {
829 return FALSE;
830 }
831
832 //
833 // Check entry of paused thread
834 //
835 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
836
837 if (!ProcessDebuggingDetails)
838 {
839 //
840 // Token not found!
841 //
842 return FALSE;
843 }
844
845 //
846 // Find the thread entry and if not found, create one for it
847 //
848 ThreadDebuggingDetails = ThreadHolderFindOrCreateThreadDebuggingDetail(HANDLE_TO_UINT32(PsGetCurrentThreadId()), ProcessDebuggingDetails);
849
850 if (!ThreadDebuggingDetails)
851 {
852 //
853 // Sth went wrong!
854 //
855 return FALSE;
856 }
857
858 //
859 // Check if the thread is already paused or not
860 //
861 if (ThreadDebuggingDetails->IsPaused)
862 {
863 //
864 // Increase the number of context switches
865 //
866 ThreadDebuggingDetails->NumberOfBlockedContextSwitches++;
867
868 //
869 // The thread is already paused, so we don't need to pause it again
870 //
871 return TRUE;
872 }
873
874 //
875 // Set it as active thread debugging
876 //
877 ProcessDebuggingDetails->ActiveThreadId = ThreadDebuggingDetails->ThreadId;
878
879 //
880 // Perform the pre-pausing tasks
881 //
882 UdPrePausingReasons(DbgState, ThreadDebuggingDetails, Reason, EventDetails);
883
884 //
885 // *** Fill the pausing structure ***
886 //
887
888 RtlZeroMemory(&PausePacket, sizeof(DEBUGGEE_UD_PAUSED_PACKET));
889
890 //
891 // Set the pausing reason
892 //
893 PausePacket.PausingReason = Reason;
894
895 //
896 // Set process debugging information
897 //
898 PausePacket.ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
899 PausePacket.ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId());
900 PausePacket.ProcessDebuggingToken = ProcessDebuggingDetails->Token;
901
902 //
903 // Set the RIP and mode of execution
904 //
905 PausePacket.Rip = LastVmexitRip;
906 PausePacket.Is32Bit = KdIsGuestOnUsermode32Bit();
907
908 //
909 // Set rflags for finding the results of conditional jumps
910 //
911 Rflags.AsUInt = VmFuncGetRflags();
912 PausePacket.Rflags = Rflags.AsUInt;
913
914 //
915 // Set the event tag (if it's an event)
916 //
917 if (EventDetails != NULL)
918 {
919 PausePacket.EventTag = EventDetails->Tag;
920 PausePacket.EventCallingStage = EventDetails->Stage;
921 }
922
923 //
924 // Read the instruction len
925 //
926 if (DbgState->InstructionLengthHint != 0)
927 {
928 ExitInstructionLength = DbgState->InstructionLengthHint;
929 }
930 else
931 {
932 //
933 // Reading instruction length (VMCS_VMEXIT_INSTRUCTION_LENGTH) proved to
934 // provide wrong results, so we won't use it
935 //
936
937 //
938 // Compute the amount of buffer we can read without problem
939 //
940 SizeOfSafeBufferToRead = (UINT32)(LastVmexitRip & 0xfff);
941 SizeOfSafeBufferToRead += MAXIMUM_INSTR_SIZE;
942
943 if (SizeOfSafeBufferToRead >= PAGE_SIZE)
944 {
945 SizeOfSafeBufferToRead = SizeOfSafeBufferToRead - PAGE_SIZE;
946 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE - SizeOfSafeBufferToRead;
947 }
948 else
949 {
950 SizeOfSafeBufferToRead = MAXIMUM_INSTR_SIZE;
951 }
952
953 //
954 // Set the length to notify debuggee
955 //
956 ExitInstructionLength = SizeOfSafeBufferToRead;
957 }
958
959 //
960 // Set the reading length of bytes (for instruction disassembling)
961 //
962 PausePacket.ReadInstructionLen = (UINT16)ExitInstructionLength;
963
964 //
965 // Find the current instruction
966 //
968 &PausePacket.InstructionBytesOnRip,
969 ExitInstructionLength);
970
971 //
972 // Send the pause packet, along with RIP and an indication
973 // to pause to the user debugger
974 //
976 &PausePacket,
978 TRUE);
979
980 //
981 // Set the thread debugging details
982 //
983 UdSetThreadPausingState(ThreadDebuggingDetails,
984 ProcessDebuggingDetails,
985 &PausePacket.InstructionBytesOnRip,
986 ExitInstructionLength);
987
988 //
989 // Everything was okay
990 //
991 return TRUE;
992}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId)
Find user-mode debugging details for threads by process Id.
Definition Attaching.c:184
BOOLEAN KdIsGuestOnUsermode32Bit()
determines if the guest was in 32-bit user-mode or 64-bit (long mode)
Definition Kd.c:3220
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderFindOrCreateThreadDebuggingDetail(UINT32 ThreadId, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Find or create user-mode debugging details for threads.
Definition ThreadHolder.c:293
struct _USERMODE_DEBUGGING_THREAD_DETAILS * PUSERMODE_DEBUGGING_THREAD_DETAILS
VOID UdPrePausingReasons(PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle special reasons pre-pausings.
Definition Ud.c:778
VOID UdSetThreadPausingState(PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails, PVOID InstructionBytesBuffer, UINT32 SizeOfInstruction)
Set the thread pausing state.
Definition Ud.c:734
unsigned short UINT16
Definition BasicTypes.h:53
#define TRUE
Definition BasicTypes.h:114
unsigned int UINT32
Definition BasicTypes.h:54
unsigned long ULONG
Definition BasicTypes.h:31
#define OPERATION_NOTIFICATION_FROM_USER_DEBUGGER_PAUSE
Definition Constants.h:390
#define MAXIMUM_INSTR_SIZE
maximum instruction size in Intel
Definition Constants.h:470
struct _DEBUGGEE_UD_PAUSED_PACKET DEBUGGEE_UD_PAUSED_PACKET
The structure of pausing packet in uHyperDbg.
IMPORT_EXPORT_HYPERLOG BOOLEAN LogCallbackSendBuffer(_In_ UINT32 OperationCode, _In_reads_bytes_(BufferLength) PVOID Buffer, _In_ UINT32 BufferLength, _In_ BOOLEAN Priority)
routines callback for sending buffer
Definition HyperLogCallback.c:123
IMPORT_EXPORT_VMM UINT64 VmFuncGetRflags()
Read guest's RFLAGS.
Definition Export.c:397
IMPORT_EXPORT_VMM UINT64 VmFuncGetLastVmexitRip(UINT32 CoreId)
get the last vm-exit RIP
Definition Export.c:363
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafeOnTargetProcess(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead)
BOOLEAN g_UserDebuggerState
shows whether the user debugger is enabled or disabled
Definition Global.h:157
struct _USERMODE_DEBUGGING_PROCESS_DETAILS * PUSERMODE_DEBUGGING_PROCESS_DETAILS
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80
NULL()
Definition test-case-generator.py:530
DEBUGGEE_PAUSING_REASON PausingReason
Definition DataTypes.h:266
UINT16 ReadInstructionLen
Definition DataTypes.h:273
UINT64 Rip
Definition DataTypes.h:263
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE EventCallingStage
Definition DataTypes.h:271
BOOLEAN Is32Bit
Definition DataTypes.h:265
UINT64 ProcessDebuggingToken
Definition DataTypes.h:264
UINT64 EventTag
Definition DataTypes.h:270
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition DataTypes.h:272
UINT64 Rflags
Definition DataTypes.h:269
UINT32 ThreadId
Definition DataTypes.h:268
UINT32 ProcessId
Definition DataTypes.h:267
UINT64 Tag
Definition DataTypes.h:226
VMM_CALLBACK_EVENT_CALLING_STAGE_TYPE Stage
Definition DataTypes.h:228
UINT32 CoreId
Definition State.h:168
UINT16 InstructionLengthHint
Definition State.h:182
UINT64 Token
Definition Ud.h:25
UINT32 ActiveThreadId
Definition Ud.h:28
UINT32 ThreadId
Definition ThreadHolder.h:34
UINT64 NumberOfBlockedContextSwitches
Definition ThreadHolder.h:39
BOOLEAN IsPaused
Definition ThreadHolder.h:36

◆ UdCheckForCommand()

BOOLEAN UdCheckForCommand ( PROCESSOR_DEBUGGING_STATE * DbgState,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail )

Check for the user-mode commands.

Parameters
DbgStateThe state of the debugger on the current core
ProcessDebuggingDetail
Returns
BOOLEAN
560{
561 PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails;
562 BOOLEAN CommandFound = FALSE;
563
564 ThreadDebuggingDetails = ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(HANDLE_TO_UINT32(PsGetCurrentProcessId()),
565 HANDLE_TO_UINT32(PsGetCurrentThreadId()));
566
567 if (!ThreadDebuggingDetails)
568 {
569 return FALSE;
570 }
571
572 //
573 // If we reached here, the current thread is in debugger attached mechanism
574 // now we check whether it's paused or not
575 //
576 if (!ThreadDebuggingDetails->IsPaused)
577 {
578 return FALSE;
579 }
580
581 //
582 // Here, we're sure that this thread is looking for command, let
583 // see if we find anything
584 //
585 for (SIZE_T i = 0; i < MAX_USER_ACTIONS_FOR_THREADS; i++)
586 {
587 if (ThreadDebuggingDetails->UdAction[i].ActionType != DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE)
588 {
589 //
590 // We found a command for this thread
591 //
592 CommandFound = TRUE;
593
594 //
595 // Perform the command
596 //
597 UdPerformCommand(DbgState,
598 ProcessDebuggingDetail,
599 ThreadDebuggingDetails,
600 ThreadDebuggingDetails->UdAction[i].ActionType,
601 ThreadDebuggingDetails->UdAction[i].OptionalParam1,
602 ThreadDebuggingDetails->UdAction[i].OptionalParam2,
603 ThreadDebuggingDetails->UdAction[i].OptionalParam3,
604 ThreadDebuggingDetails->UdAction[i].OptionalParam4);
605
606 //
607 // Remove the command
608 //
609 ThreadDebuggingDetails->UdAction[i].OptionalParam1 = (UINT64)NULL;
610 ThreadDebuggingDetails->UdAction[i].OptionalParam2 = (UINT64)NULL;
611 ThreadDebuggingDetails->UdAction[i].OptionalParam3 = (UINT64)NULL;
612 ThreadDebuggingDetails->UdAction[i].OptionalParam4 = (UINT64)NULL;
613
614 //
615 // At last disable it
616 //
617 ThreadDebuggingDetails->UdAction[i].ActionType = DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE;
618
619 //
620 // only one command at a time
621 //
622 break;
623 }
624 }
625
626 //
627 // Return whether we found a command or not
628 //
629 return CommandFound;
630}
#define MAX_USER_ACTIONS_FOR_THREADS
Maximum actions in paused threads storage.
Definition Attaching.h:22
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(UINT32 ProcessId, UINT32 ThreadId)
Find the active threads of the process from process id.
Definition ThreadHolder.c:145
BOOLEAN UdPerformCommand(PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGER_UD_COMMAND_ACTION_TYPE UserAction, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3, UINT64 OptionalParam4)
Perform the user-mode commands.
Definition Ud.c:487
UCHAR BOOLEAN
Definition BasicTypes.h:35
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE
Definition RequestStructures.h:920
DEBUGGER_UD_COMMAND_ACTION_TYPE ActionType
Definition RequestStructures.h:934
UINT64 OptionalParam1
Definition RequestStructures.h:935
UINT64 OptionalParam3
Definition RequestStructures.h:937
UINT64 OptionalParam4
Definition RequestStructures.h:938
UINT64 OptionalParam2
Definition RequestStructures.h:936
DEBUGGER_UD_COMMAND_ACTION UdAction[MAX_USER_ACTIONS_FOR_THREADS]
Definition ThreadHolder.h:40

◆ UdDispatchUsermodeCommands()

BOOLEAN UdDispatchUsermodeCommands ( PDEBUGGER_UD_COMMAND_PACKET ActionRequest,
UINT32 ActionRequestInputLength,
UINT32 ActionRequestOutputLength )

Dispatch the user-mode commands.

Parameters
ActionRequest
ActionRequestInputLength
ActionRequestOutputLength
Returns
BOOLEAN
645{
646 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
647 BOOLEAN Result;
648
649 //
650 // Find the thread debugging detail of the thread
651 //
652 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(ActionRequest->ProcessDebuggingDetailToken);
653
654 if (!ProcessDebuggingDetails)
655 {
656 //
657 // Token not found!
658 //
660
661 return FALSE;
662 }
663
664 //
665 // Check if this command needs the action request to be waited for completion or not
666 //
667 if (ActionRequest->WaitForEventCompletion)
668 {
669 //
670 // Set the command event buffer
671 //
673
674 //
675 // Set the input command buffer length
676 //
677 g_UserDebuggerWaitingCommandInputBufferLength = ActionRequestInputLength;
678
679 //
680 // Set the output command buffer length
681 //
682 g_UserDebuggerWaitingCommandOutputBufferLength = ActionRequestOutputLength;
683 }
684
685 //
686 // Apply the command to all threads or just one thread
687 //
688 Result = ThreadHolderApplyActionToPausedThreads(ProcessDebuggingDetails, ActionRequest);
689
690 //
691 // Check if we need to wait for the command event completion or not
692 //
693 if (Result && ActionRequest->WaitForEventCompletion)
694 {
695 //
696 // Wait for the command to be completed
697 //
699 }
700
701 //
702 // Since the command is applied successfully, we can set the result
703 // Note that if the command contains another layer of optional buffers
704 // the result of that optional buffer might be different than this result
705 // this one is just for applying the command itself
706 //
707 if (Result)
708 {
709 //
710 // If we are not waiting for the event completion, we should set the
711 // result of the action request here as we successfully applied the command
712 //
714 }
715 else
716 {
718 }
719
720 return Result;
721}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByToken(UINT64 Token)
Find user-mode debugging details for threads by token.
Definition Attaching.c:161
VOID SynchronizationWaitForEvent(PRKEVENT Event)
Wait for a waiting event.
Definition Synchronization.c:51
BOOLEAN ThreadHolderApplyActionToPausedThreads(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails, PDEBUGGER_UD_COMMAND_PACKET ActionRequest)
Apply the action of the user debugger to a specific thread or all threads.
Definition ThreadHolder.c:400
void * PVOID
Definition BasicTypes.h:56
#define DEBUGGER_ERROR_INVALID_THREAD_DEBUGGING_TOKEN
error, invalid thread debugging token
Definition ErrorCodes.h:332
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
#define DEBUGGER_ERROR_UNABLE_TO_APPLY_COMMAND_TO_THE_TARGET_THREAD
error, unable to apply the command to the target thread
Definition ErrorCodes.h:582
PVOID g_UserDebuggerWaitingCommandBuffer
Buffer to hold the command from user debugger.
Definition Global.h:53
UINT32 g_UserDebuggerWaitingCommandOutputBufferLength
Length of the output command buffer from user debugger.
Definition Global.h:65
UINT32 g_UserDebuggerWaitingCommandInputBufferLength
Length of the input command buffer from user debugger.
Definition Global.h:59
KEVENT g_UserDebuggerWaitingCommandEvent
Event to show whether the user debugger is waiting for a command or not.
Definition Global.h:47
UINT32 Result
Definition RequestStructures.h:953
BOOLEAN WaitForEventCompletion
Definition RequestStructures.h:952
UINT64 ProcessDebuggingDetailToken
Definition RequestStructures.h:949

◆ UdHandleDebugEventsWhenUserDebuggerIsAttached()

BOOLEAN UdHandleDebugEventsWhenUserDebuggerIsAttached ( PROCESSOR_DEBUGGING_STATE * DbgState,
BOOLEAN TrapSetByDebugger )

Handles debug events when user-debugger is attached.

Parameters
DbgStateThe state of the debugger on the current core
TrapSetByDebuggerShows whether a trap set by debugger or not
Returns
BOOLEAN
269{
270 UNREFERENCED_PARAMETER(TrapSetByDebugger);
271
272 if (UdHandleInstantBreak(DbgState,
274 NULL))
275 {
276 //
277 // Handled by user debugger
278 //
279 return TRUE;
280 }
281 else
282 {
283 //
284 // Not handled by user debugger
285 //
286 return FALSE;
287 }
288}
BOOLEAN UdHandleInstantBreak(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Handle cases where we instant break is needed on the user debugger.
Definition Ud.c:122
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_DEBUG_BREAK
Definition Connection.h:41

◆ UdHandleInstantBreak()

BOOLEAN UdHandleInstantBreak ( PROCESSOR_DEBUGGING_STATE * DbgState,
DEBUGGEE_PAUSING_REASON Reason,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail )

Handle cases where we instant break is needed on the user debugger.

Parameters
DbgStateThe state of the debugger on the current core
ReasonThe reason of the pausing
ProcessDebuggingDetail
Returns
BOOLEAN
125{
126 //
127 // Check if the process debugging details is available or not
128 //
129 if (ProcessDebuggingDetail == NULL)
130 {
131 //
132 // If the process debugging detail is not available, we should
133 // find it by the current process id
134 //
135 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
136
137 if (ProcessDebuggingDetail == NULL)
138 {
139 //
140 // If we reached here, it means that the process debugging detail is not found
141 // so, we should return FALSE to indicate that we couldn't handle the instant break
142 //
143 return FALSE;
144 }
145 }
146
147 //
148 // Add the process to the watching list to be able to intercept the threads
149 //
150 if (AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, TRUE))
151 {
152 //
153 // Since the adding it to the watching list will take effect from the next
154 // CR3 vm-exit, we should change the state of the core to prevent further execution
155 //
157
158 //
159 // Handling state through the user-mode debugger
160 //
162 Reason,
163 NULL);
164 }
165
166 //
167 // If we reached here, it means that we couldn't add the process to the
168 //
169 return FALSE;
170}
BOOLEAN AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enable)
Enable or disable the thread intercepting phase.
Definition Attaching.c:687
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:812
IMPORT_EXPORT_VMM VOID ConfigureExecTrapApplyMbecConfiguratinFromKernelSide(UINT32 CoreId)
Apply the MBEC configuration from the kernel side.
Definition Configuration.c:55

◆ UdInitializeUserDebugger()

BOOLEAN UdInitializeUserDebugger ( )

initialize user debugger

this function should be called on vmx non-root

Returns
BOOLEAN
22{
23 //
24 // Check if it's already initialized or not, we'll ignore it if it's
25 // previously initialized
26 //
28 {
29 return TRUE;
30 }
31
32 //
33 // Configure the exec-trap on all processors
34 //
36 {
37 return FALSE;
38 }
39
40 //
41 // Check if we have functions we need for attaching mechanism
42 //
44 {
45 LogError("Err, unable to find needed functions for user-debugger");
46 // return FALSE;
47 }
48
49 //
50 // Start the seed of user-mode debugging thread
51 //
53
54 //
55 // Initialize the thread debugging details list
56 //
57 InitializeListHead(&g_ProcessDebuggingDetailsListHead);
58
59 //
60 // Enable vm-exit on Hardware debug exceptions and breakpoints
61 // so, intercept #DBs and #BP by changing exception bitmap (one core)
62 //
64
65 //
66 // Request to allocate buffers for thread holder of threads
67 //
69
70 //
71 // Initialize command waiting event
72 //
74
75 //
76 // Indicate that the user debugger is active
77 //
79
80 return TRUE;
81}
VOID SynchronizationInitializeEvent(PRKEVENT Event)
Initialize a waiting event.
Definition Synchronization.c:21
VOID ThreadHolderAllocateThreadHoldingBuffers()
Pre allocate buffer for thread holder.
Definition ThreadHolder.c:21
ZwQueryInformationProcess g_ZwQueryInformationProcess
Address of ZwQueryInformationProcess.
Definition UserAccess.h:187
PsGetProcessPeb g_PsGetProcessPeb
Address of PsGetProcessPeb.
Definition UserAccess.h:193
PsGetProcessWow64Process g_PsGetProcessWow64Process
Address of PsGetProcessWow64Process.
Definition UserAccess.h:199
#define DebuggerThreadDebuggingTagStartSeed
The seeds that user-mode thread detail token start with it.
Definition Constants.h:237
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
IMPORT_EXPORT_VMM VOID BroadcastEnableDbAndBpExitingAllCores()
routines to set vm-exit on all DBs and BP on all cores
Definition Broadcast.c:35
IMPORT_EXPORT_VMM BOOLEAN ConfigureInitializeExecTrapOnAllProcessors()
routines for initializing user-mode, kernel-mode exec trap
Definition Configuration.c:32
LIST_ENTRY g_ProcessDebuggingDetailsListHead
List header of thread debugging details.
Definition Global.h:200
UINT64 g_SeedOfUserDebuggingDetails
Seed for tokens of unique details buffer for threads.
Definition Global.h:187

◆ UdPerformCommand()

BOOLEAN UdPerformCommand ( PROCESSOR_DEBUGGING_STATE * DbgState,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail,
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails,
DEBUGGER_UD_COMMAND_ACTION_TYPE UserAction,
UINT64 OptionalParam1,
UINT64 OptionalParam2,
UINT64 OptionalParam3,
UINT64 OptionalParam4 )

Perform the user-mode commands.

Parameters
DbgStateThe state of the debugger on the current core
ProcessDebuggingDetails
ThreadDebuggingDetails
UserAction
OptionalParam1
OptionalParam2
OptionalParam3
OptionalParam4
Returns
BOOLEAN
495{
496 UNREFERENCED_PARAMETER(OptionalParam4);
497
498 //
499 // Perform the command
500 //
501 switch (UserAction)
502 {
504
505 //
506 // Stepping through the instructions
507 //
508 UdStepInstructions(DbgState,
509 ProcessDebuggingDetail,
510 ThreadDebuggingDetails,
511 (DEBUGGER_REMOTE_STEPPING_REQUEST)OptionalParam1,
512 (BOOLEAN)OptionalParam2,
513 (UINT32)OptionalParam3);
514
515 break;
516
518
519 //
520 // Read the registers
521 //
522 UdReadRegisters(DbgState,
523 (UINT32)OptionalParam1);
524
525 break;
526
528
529 //
530 // Execute the script buffer
531 //
532 UdRunScript(DbgState);
533
534 break;
535
536 default:
537
538 //
539 // Invalid user action
540 //
541 return FALSE;
542
543 break;
544 }
545
546 return TRUE;
547}
VOID UdReadRegisters(PROCESSOR_DEBUGGING_STATE *DbgState, UINT32 RegisterId)
Perform reading register(s) in the target thread.
Definition Ud.c:359
VOID UdStepInstructions(PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail, PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails, DEBUGGER_REMOTE_STEPPING_REQUEST SteppingType, BOOLEAN IsCurrentInstructionACall, UINT32 CallInstructionSize)
Perform stepping though the instructions in the target thread.
Definition Ud.c:303
VOID UdRunScript(PROCESSOR_DEBUGGING_STATE *DbgState)
Perform running script in the target thread.
Definition Ud.c:403
enum _DEBUGGER_REMOTE_STEPPING_REQUEST DEBUGGER_REMOTE_STEPPING_REQUEST
stepping and tracking types
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_EXECUTE_SCRIPT_BUFFER
Definition RequestStructures.h:924
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_READ_REGISTERS
Definition RequestStructures.h:923
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP
Definition RequestStructures.h:922

◆ UdPrePausingReasons()

VOID UdPrePausingReasons ( PROCESSOR_DEBUGGING_STATE * DbgState,
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails,
DEBUGGEE_PAUSING_REASON Reason,
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails )

Handle special reasons pre-pausings.

This function can be used in vmx-root

Parameters
DbgStateThe state of the debugger on the current core
ThreadDebuggingDetails
Reason
EventDetails
Returns
VOID
783{
784 UNREFERENCED_PARAMETER(DbgState);
785 UNREFERENCED_PARAMETER(ThreadDebuggingDetails);
786 UNREFERENCED_PARAMETER(EventDetails);
787
788 //
789 // *** Handle events before pausing ***
790 //
791 switch (Reason)
792 {
794
795 break;
796
797 default:
798 break;
799 }
800}

◆ UdReadRegisters()

VOID UdReadRegisters ( PROCESSOR_DEBUGGING_STATE * DbgState,
UINT32 RegisterId )

Perform reading register(s) in the target thread.

Parameters
DbgStateThe state of the debugger on the current core
RegisterId
Returns
VOID
361{
362 UNREFERENCED_PARAMETER(DbgState);
363 UNREFERENCED_PARAMETER(RegisterId);
364
365 PDEBUGGER_UD_COMMAND_PACKET ActionRequest;
367
368 //
369 // Recover the action request buffer and optional storage buffer
370 //
373
374 //
375 // *** Here, we should read the registers and put them in the optional storage buffer ***
376 //
377 DebuggerCommandReadRegisters(DbgState->Regs, RegDesc);
378
379 //
380 // Set the register request result
381 //
383
384 //
385 // Set the action request result
386 //
388
389 //
390 // Set the event to indicate that the command is completed
391 //
393}
BOOLEAN DebuggerCommandReadRegisters(GUEST_REGS *Regs, PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterRequest)
read registers
Definition DebuggerCommands.c:23
VOID SynchronizationSetEvent(PRKEVENT Event)
Set (signal) a waiting event.
Definition Synchronization.c:36
unsigned char UINT8
Definition BasicTypes.h:52
struct _DEBUGGEE_REGISTER_READ_DESCRIPTION * PDEBUGGEE_REGISTER_READ_DESCRIPTION
struct _DEBUGGER_UD_COMMAND_PACKET DEBUGGER_UD_COMMAND_PACKET
The structure of command packet in uHyperDbg.
struct _DEBUGGER_UD_COMMAND_PACKET * PDEBUGGER_UD_COMMAND_PACKET
UINT32 KernelStatus
Definition RequestStructures.h:1619
GUEST_REGS * Regs
Definition State.h:167

◆ UdRegularStepOver()

VOID UdRegularStepOver ( UINT64 LastRip,
BOOLEAN IsNextInstructionACall,
UINT32 CallLength )

Regular step-over, step one instruction to the debuggee on user debugger if there is a call then it jumps the call.

Parameters
LastRipLast RIP register
IsNextInstructionACall
CallLength
Returns
VOID
228{
229 UINT64 NextAddressForHardwareDebugBp = 0;
230
231 // LogInfo("Last Rip: %llx, IsNextInstructionACall: %s, Call length: %x",
232 // LastRip,
233 // IsNextInstructionACall ? "true" : "false",
234 // CallLength);
235
236 if (IsNextInstructionACall)
237 {
238 //
239 // It's a call, we should put a hardware debug register breakpoint
240 // on the next instruction
241 //
242 NextAddressForHardwareDebugBp = LastRip + CallLength;
243
244 //
245 // Broadcast to apply hardware debug registers to all cores
246 //
247 UdBroadcastSetHardwareDebugRegistersAllCores((PVOID)NextAddressForHardwareDebugBp);
248 }
249 else
250 {
251 //
252 // Any instruction other than call (regular step)
253 //
255 }
256}
VOID TracingRegularStepInInstruction()
Regular step-in, step one instruction to the debuggee.
Definition Tracing.c:112
VOID UdBroadcastSetHardwareDebugRegistersAllCores(PVOID TargetAddress)
routines to broadcast setting hardware debug registers on all cores
Definition Ud.c:208

◆ UdRunScript()

VOID UdRunScript ( PROCESSOR_DEBUGGING_STATE * DbgState)

Perform running script in the target thread.

Parameters
DbgStateThe state of the debugger on the current core
Returns
VOID
404{
405 PDEBUGGER_UD_COMMAND_PACKET ActionRequest;
406 DEBUGGEE_SCRIPT_PACKET * ScriptPacket;
407 DEBUGGER_TRIGGERED_EVENT_DETAILS EventTriggerDetail = {0};
408
409 //
410 // Recover the action request buffer and optional storage buffer
411 //
414
415 //
416 // *** Here, we should execute script buffer and put them in the optional storage buffer ***
417 //
418
419 //
420 // Set a tag to the script so it shows the message is from script engine
421 //
422 EventTriggerDetail.Tag = OPERATION_LOG_MESSAGE_MANDATORY;
423
424 //
425 // Run the script in the target process (thread)
426 //
427 if (DebuggerPerformRunScript(DbgState,
428 NULL,
429 ScriptPacket,
430 &EventTriggerDetail))
431 {
432 //
433 // Check if we need to format the output or not
434 //
435 if (ScriptPacket->IsFormat)
436 {
437 //
438 // For the format, we need to get the result from the script engine
439 // through global variables, we store the result of format into
440 // optional parameters
441 //
442 ScriptPacket->Result = g_UserDebuggerFormatsResultPacket.Result;
444 }
445 else
446 {
447 //
448 // Set status
449 //
451 }
452 }
453 else
454 {
455 //
456 // Set status
457 //
459 }
460
461 //
462 // Set the action request result
463 //
465
466 //
467 // Set the event to indicate that the command is completed
468 //
470}
BOOLEAN DebuggerPerformRunScript(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGER_EVENT_ACTION *Action, DEBUGGEE_SCRIPT_PACKET *ScriptDetails, DEBUGGER_TRIGGERED_EVENT_DETAILS *EventTriggerDetail)
Managing run script action.
Definition Debugger.c:1662
#define OPERATION_LOG_MESSAGE_MANDATORY
Definition Constants.h:380
struct _DEBUGGER_TRIGGERED_EVENT_DETAILS DEBUGGER_TRIGGERED_EVENT_DETAILS
The structure of detail of a triggered event in HyperDbg.
#define DEBUGGER_ERROR_PREPARING_DEBUGGEE_TO_RUN_SCRIPT
error, unable to run script in remote debuggee
Definition ErrorCodes.h:172
struct _DEBUGGEE_SCRIPT_PACKET DEBUGGEE_SCRIPT_PACKET
The structure of script packet in HyperDbg.
DEBUGGEE_FORMATS_PACKET g_UserDebuggerFormatsResultPacket
Holds the result of user debugger formats command.
Definition Global.h:109
BOOLEAN IsFormat
Definition RequestStructures.h:1586
UINT64 FormatValue
Definition RequestStructures.h:1587
UINT32 Result
Definition RequestStructures.h:1588

◆ UdSendFormatsFunctionResult()

VOID UdSendFormatsFunctionResult ( UINT64 Value)

Send the result of formats command to the user debugger.

Parameters
Value
Returns
VOID
196{
199}
RequestedActionOfThePacket Value(0x1) 00000000

◆ UdSetThreadPausingState()

VOID UdSetThreadPausingState ( PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails,
PVOID InstructionBytesBuffer,
UINT32 SizeOfInstruction )

Set the thread pausing state.

Parameters
ThreadDebuggingDetails
ProcessDebuggingDetails
InstructionBytesBuffer
SizeOfInstruction
Returns
VOID
738{
739 UNREFERENCED_PARAMETER(ProcessDebuggingDetails);
740
741 //
742 // Save the RIP for future return
743 //
744 ThreadDebuggingDetails->ThreadRip = VmFuncGetRip();
745
746 //
747 // Set the number of context switches to one (reset it if already set)
748 //
749 ThreadDebuggingDetails->NumberOfBlockedContextSwitches = 1;
750
751 //
752 // Indicate that it's spinning
753 //
754 ThreadDebuggingDetails->IsPaused = TRUE;
755
756 //
757 // Set size of instruction
758 //
759 ThreadDebuggingDetails->SizeOfInstruction = SizeOfInstruction;
760
761 //
762 // Copy the current running instruction
763 //
764 memcpy(&ThreadDebuggingDetails->InstructionBytesOnRip[0], InstructionBytesBuffer, SizeOfInstruction);
765}
IMPORT_EXPORT_VMM UINT64 VmFuncGetRip()
Read guest's RIP.
Definition Export.c:420
UINT32 SizeOfInstruction
Definition ThreadHolder.h:38
UINT64 ThreadRip
Definition ThreadHolder.h:35
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition ThreadHolder.h:37

◆ UdStepInstructions()

VOID UdStepInstructions ( PROCESSOR_DEBUGGING_STATE * DbgState,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail,
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetails,
DEBUGGER_REMOTE_STEPPING_REQUEST SteppingType,
BOOLEAN IsCurrentInstructionACall,
UINT32 CallInstructionSize )

Perform stepping though the instructions in the target thread.

Parameters
DbgStateThe state of the debugger on the current core
ProcessDebuggingDetail
ThreadDebuggingDetails
SteppingType
IsCurrentInstructionACall
CallInstructionSize
Returns
VOID
309{
310 UNREFERENCED_PARAMETER(ThreadDebuggingDetails);
311
312 switch (SteppingType)
313 {
315
316 //
317 // Apply step-in (t command)
318 //
320
321 //
322 // Continue the debuggee process
323 //
324 AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE);
325
326 break;
327
329
330 //
331 // Apply Step-over (p command)
332 //
335 IsCurrentInstructionACall,
336 CallInstructionSize);
337
338 //
339 // Continue the debuggee process
340 //
341 AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE);
342
343 break;
344
345 default:
346 break;
347 }
348}
VOID UdRegularStepOver(UINT64 LastRip, BOOLEAN IsNextInstructionACall, UINT32 CallLength)
Regular step-over, step one instruction to the debuggee on user debugger if there is a call then it j...
Definition Ud.c:227
@ DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_IN
Definition RequestStructures.h:1046
@ DEBUGGER_REMOTE_STEPPING_REQUEST_STEP_OVER
Definition RequestStructures.h:1050

◆ UdUninitializeUserDebugger()

VOID UdUninitializeUserDebugger ( )

uninitialize user debugger

this function should be called on vmx non-root

Returns
VOID
91{
93 {
94 //
95 // Indicate that the user debugger is not active
96 //
98
99 //
100 // Uninitialize the exec-trap on all processors
101 //
103
104 //
105 // Free and deallocate all the buffers (pools) relating to
106 // thread debugging details
107 //
109 }
110}
VOID AttachingRemoveAndFreeAllProcessDebuggingDetails()
Remove and deallocate all thread debuggig details.
Definition Attaching.c:226
IMPORT_EXPORT_VMM VOID ConfigureUninitializeExecTrapOnAllProcessors()
routines for uninitializing user-mode, kernel-mode exec trap
Definition Configuration.c:43