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

Attaching and detaching for debugging user-mode processes. More...

#include "pch.h"

Functions

BOOLEAN AttachingInitialize ()
 Initialize the attaching mechanism.
UINT64 AttachingCreateProcessDebuggingDetails (UINT32 ProcessId, BOOLEAN Enabled, BOOLEAN Is32Bit, BOOLEAN CheckCallbackAtFirstInstruction, PEPROCESS Eprocess, UINT64 PebAddressToMonitor)
 Create user-mode debugging details for threads.
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByToken (UINT64 Token)
 Find user-mode debugging details for threads by token.
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId (UINT32 ProcessId)
 Find user-mode debugging details for threads by process Id.
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsInStartingPhase ()
 Find user-mode debugging details for threads that is in the start-up phase.
VOID AttachingRemoveAndFreeAllProcessDebuggingDetails ()
 Remove and deallocate all thread debuggig details.
BOOLEAN AttachingRemoveProcessDebuggingDetailsByToken (UINT64 Token)
 Remove user-mode debugging details for threads by its token.
BOOLEAN AttachingSetStartingPhaseOfProcessDebuggingDetailsByToken (BOOLEAN Set, UINT64 Token)
 Set the start up phase of a debugging thread buffer by its token.
BOOLEAN AttachingReachedToValidLoadedModule (PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
 Handle cases where we reached to the valid loaded module The main module should be loaded once we reach to this function.
VOID AttachingHandleEntrypointInterception (PROCESSOR_DEBUGGING_STATE *DbgState)
 Handle the interception of finding the entrypoint on attaching to user-mode process.
BOOLEAN AttachingAdjustNopSledBuffer (UINT64 ReservedBuffAddress, UINT32 ProcessId)
 Allocate a nop-sled buffer.
BOOLEAN AttachingCheckThreadInterceptionWithUserDebugger (UINT32 CoreId)
 Check thread interceptions with user-mode debugger.
BOOLEAN AttachingConfigureInterceptingThreads (UINT64 ProcessDebuggingToken, BOOLEAN Enable)
 Enable or disable the thread intercepting phase.
BOOLEAN AttachingCheckForSafeCallbackRequestedInitializations (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest, UINT64 ProcessDebuggingToken)
 This function checks whether any special initialization is needed while attaching to a process that requests a callback.
BOOLEAN AttachingPerformAttachToProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest, BOOLEAN IsAttachingToEntrypoint)
 Attach to the target process.
BOOLEAN AttachingCheckUnhandledEptViolation (UINT32 CoreId, UINT64 ViolationQualification, UINT64 GuestPhysicalAddr)
 handling unhandled EPT violations
BOOLEAN AttachingRemoveHooks (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest)
 Clearing hooks after resuming the process.
BOOLEAN AttachingPauseProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest)
 Pauses the target process.
BOOLEAN AttachingContinueProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS ContinueRequest)
 Continues the target process.
BOOLEAN AttachingKillProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS KillRequest)
 Kill the target process from kernel-mode.
BOOLEAN AttachingPerformDetach (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest)
 Clearing hooks after resuming the process.
BOOLEAN AttachingSwitchProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest)
 Switch to the target thread.
BOOLEAN AttachingQueryCountOfActiveDebuggingThreadsAndProcesses (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfDebugThreadsRequest)
 Query count of active debugging threads.
BOOLEAN AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses (PVOID BufferToStoreDetails, UINT32 BufferSize)
 Query details of active debugging threads.
VOID AttachingTargetProcess (PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request)
 Dispatch and perform attaching tasks.

Detailed Description

Attaching and detaching for debugging user-mode processes.

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

Function Documentation

◆ AttachingAdjustNopSledBuffer()

BOOLEAN AttachingAdjustNopSledBuffer ( UINT64 ReservedBuffAddress,
UINT32 ProcessId )

Allocate a nop-sled buffer.

Parameters
ReservedBuffAddress
ProcessId
Returns
BOOLEAN
563{
564 PEPROCESS SourceProcess;
565 KAPC_STATE State = {0};
566
567 if (PsLookupProcessByProcessId((HANDLE)ProcessId, &SourceProcess) != STATUS_SUCCESS)
568 {
569 //
570 // if the process not found
571 //
572 return FALSE;
573 }
574
575 __try
576 {
577 KeStackAttachProcess(SourceProcess, &State);
578
579 //
580 // Fill the memory with nops
581 //
582 memset((PVOID)ReservedBuffAddress, 0x90, PAGE_SIZE);
583
584 //
585 // Set jmps to form a loop (little endians)
586 //
587 // Disassembly of section .text:
588 // 0000000000000000 <NopLoop>:
589 // 0: 90 nop
590 // 1: 90 nop
591 // 2: 90 nop
592 // 3: 90 nop
593 // 4: 90 nop
594 // 5: 90 nop
595 // 6: 90 nop
596 // 7: 90 nop
597 // 8: 0f a2 cpuid
598 // a: eb f4 jmp 0 <NopLoop>
599 //
600 *(UINT16 *)(ReservedBuffAddress + PAGE_SIZE - 4) = 0xa20f;
601 *(UINT16 *)(ReservedBuffAddress + PAGE_SIZE - 2) = 0xf4eb;
602
603 KeUnstackDetachProcess(&State);
604
605 ObDereferenceObject(SourceProcess);
606 }
607 __except (EXCEPTION_EXECUTE_HANDLER)
608 {
609 KeUnstackDetachProcess(&State);
610
611 return FALSE;
612 }
613
614 return TRUE;
615}
unsigned short UINT16
Definition BasicTypes.h:53
void * PVOID
Definition BasicTypes.h:56
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
#define PAGE_SIZE
Size of each page (4096 bytes).
Definition common.h:80

◆ AttachingCheckForSafeCallbackRequestedInitializations()

BOOLEAN AttachingCheckForSafeCallbackRequestedInitializations ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest,
UINT64 ProcessDebuggingToken )

This function checks whether any special initialization is needed while attaching to a process that requests a callback.

this function should not be called in vmx-root

Parameters
AttachRequest
ProcessDebuggingToken
Returns
BOOLEAN
755{
756 UNREFERENCED_PARAMETER(AttachRequest);
757 UNREFERENCED_PARAMETER(ProcessDebuggingToken);
758
759 //
760 // Enable the memory access logging
761 //
763
764 return TRUE;
765}
IMPORT_EXPORT_VMM BOOLEAN ConfigureInitializeExecTrapOnAllProcessors()
routines for initializing user-mode, kernel-mode exec trap
Definition Configuration.c:32

◆ AttachingCheckThreadInterceptionWithUserDebugger()

BOOLEAN AttachingCheckThreadInterceptionWithUserDebugger ( UINT32 CoreId)

Check thread interceptions with user-mode debugger.

Parameters
CoreId
Returns
BOOLEAN if TRUE show that the thread interceptin is handled otherwise FALSE
626{
627 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
628 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
629
630 //
631 // Check whether user-debugger is initialized or not
632 //
634 {
635 return FALSE;
636 }
637
638 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
639
640 //
641 // Check if the process debugging detail is found
642 //
643 if (!ProcessDebuggingDetail)
644 {
645 //
646 // not related to user debugger
647 //
648 return FALSE;
649 }
650
651 //
652 // Check if thread is in the intercepting phase
653 //
654 if (ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
655 {
656 //
657 // Handling state through the user-mode debugger
658 //
661 NULL))
662 {
663 //
664 // Check for possible commands that need to be executed
665 //
666 UdCheckForCommand(DbgState, ProcessDebuggingDetail);
667
668 return TRUE;
669 }
670 }
671
672 //
673 // this thread is not in intercepting phase
674 //
675 return FALSE;
676}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId)
Find user-mode debugging details for threads by process Id.
Definition Attaching.c:184
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
BOOLEAN UdCheckForCommand(PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Check for the user-mode commands.
Definition Ud.c:558
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
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED
Definition Connection.h:42
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:157
struct _PROCESSOR_DEBUGGING_STATE PROCESSOR_DEBUGGING_STATE
Saves the debugger state.
struct _USERMODE_DEBUGGING_PROCESS_DETAILS * PUSERMODE_DEBUGGING_PROCESS_DETAILS
BOOLEAN IsOnThreadInterceptingPhase
Definition Ud.h:38

◆ AttachingCheckUnhandledEptViolation()

BOOLEAN AttachingCheckUnhandledEptViolation ( UINT32 CoreId,
UINT64 ViolationQualification,
UINT64 GuestPhysicalAddr )

handling unhandled EPT violations

Parameters
CoreId
ViolationQualification
GuestPhysicalAddr
Returns
BOOLEAN
979{
980 UNREFERENCED_PARAMETER(CoreId);
981 UNREFERENCED_PARAMETER(ViolationQualification);
982 UNREFERENCED_PARAMETER(GuestPhysicalAddr);
983
984 //
985 // Not handled here
986 //
987 return FALSE;
988}

◆ AttachingConfigureInterceptingThreads()

BOOLEAN AttachingConfigureInterceptingThreads ( UINT64 ProcessDebuggingToken,
BOOLEAN Enable )

Enable or disable the thread intercepting phase.

this function should be called in vmx non-root

Parameters
ProcessDebuggingToken
Enable
Returns
BOOLEAN
688{
689 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
690
691 //
692 // Get the current process debugging detail
693 //
694 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByToken(ProcessDebuggingToken);
695
696 if (!ProcessDebuggingDetail)
697 {
698 return FALSE;
699 }
700
701 //
702 // If the thread is already in intercepting phase, we should return,
703 //
704 if (Enable && ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
705 {
706 LogError("Err, thread is already in intercepting phase");
707 return FALSE;
708 }
709
710 //
711 // We're or we're not in thread intercepting phase now
712 //
713 ProcessDebuggingDetail->IsOnThreadInterceptingPhase = Enable;
714
715 //
716 // Intercepting threads is enabled
717 //
718 if (Enable)
719 {
720 //
721 // Add the process to the watching list to be able to intercept the threads
722 //
724 }
725 else
726 {
727 //
728 // Unpause the threads of the target process
729 //
730 ThreadHolderUnpauseAllThreadsInProcess(ProcessDebuggingDetail);
731
732 //
733 // Remove the process from the watching list
734 //
736 }
737
738 return TRUE;
739}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByToken(UINT64 Token)
Find user-mode debugging details for threads by token.
Definition Attaching.c:161
BOOLEAN ThreadHolderUnpauseAllThreadsInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Unpause all threads in the process debugging details.
Definition ThreadHolder.c:108
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
IMPORT_EXPORT_VMM BOOLEAN ConfigureExecTrapAddProcessToWatchingList(UINT32 ProcessId)
Add the target process to the watching list.
Definition Configuration.c:67
IMPORT_EXPORT_VMM BOOLEAN ConfigureExecTrapRemoveProcessFromWatchingList(UINT32 ProcessId)
Remove the target process from the watching list.
Definition Configuration.c:79
UINT32 ProcessId
Definition Ud.h:35

◆ AttachingContinueProcess()

BOOLEAN AttachingContinueProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS ContinueRequest)

Continues the target process.

this function should not be called in vmx-root

Parameters
ContinueRequest
Returns
BOOLEAN
1085{
1086 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
1087
1088 //
1089 // Get the thread debugging detail
1090 //
1091 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(ContinueRequest->Token);
1092
1093 //
1094 // Check if token is valid or not
1095 //
1096 if (!ProcessDebuggingDetails)
1097 {
1099 return FALSE;
1100 }
1101
1102 //
1103 // Configure the intercepting threads to be disabled
1104 //
1105 if (AttachingConfigureInterceptingThreads(ContinueRequest->Token, FALSE))
1106 {
1107 //
1108 // The continuing operation was successful
1109 //
1110 ContinueRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1111 return TRUE;
1112 }
1113 else
1114 {
1116 return FALSE;
1117 }
1118}
BOOLEAN AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enable)
Enable or disable the thread intercepting phase.
Definition Attaching.c:687
#define DEBUGGER_ERROR_UNABLE_TO_PAUSE_THE_PROCESS_THREADS
error, unable to pause the process's threads
Definition ErrorCodes.h:338
#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
UINT64 Result
Definition RequestStructures.h:693
UINT64 Token
Definition RequestStructures.h:692

◆ AttachingCreateProcessDebuggingDetails()

UINT64 AttachingCreateProcessDebuggingDetails ( UINT32 ProcessId,
BOOLEAN Enabled,
BOOLEAN Is32Bit,
BOOLEAN CheckCallbackAtFirstInstruction,
PEPROCESS Eprocess,
UINT64 PebAddressToMonitor )

Create user-mode debugging details for threads.

Parameters
ProcessId
Is32Bit
Eprocess
PebAddressToMonitor
Returns
UINT64 returns the unique token
105{
106 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
107
108 //
109 // Allocate the buffer
110 //
111 ProcessDebuggingDetail = (USERMODE_DEBUGGING_PROCESS_DETAILS *)
113
114 if (!ProcessDebuggingDetail)
115 {
116 return (UINT64)NULL;
117 }
118
119 //
120 // Set the unique tag and increment it
121 //
122 ProcessDebuggingDetail->Token = g_SeedOfUserDebuggingDetails++;
123
124 //
125 // Set the details of the created buffer
126 //
127 ProcessDebuggingDetail->ProcessId = ProcessId;
128 ProcessDebuggingDetail->Enabled = Enabled;
129 ProcessDebuggingDetail->Is32Bit = Is32Bit;
130 ProcessDebuggingDetail->CheckCallBackForInterceptingFirstInstruction = CheckCallbackAtFirstInstruction;
131 ProcessDebuggingDetail->Eprocess = Eprocess;
132 ProcessDebuggingDetail->PebAddressToMonitor = (PVOID)PebAddressToMonitor;
133
134 //
135 // Allocate a thread holder buffer for this process
136 //
138 {
139 PlatformMemFreePool(ProcessDebuggingDetail);
140 return (UINT64)NULL;
141 }
142
143 //
144 // Attach it to the list of active thread (LIST_ENTRY)
145 //
146 InsertHeadList(&g_ProcessDebuggingDetailsListHead, &(ProcessDebuggingDetail->AttachedProcessList));
147
148 //
149 // return the token
150 //
151 return ProcessDebuggingDetail->Token;
152}
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocates zeroed non-paged pool memory.
Definition PlatformMem.c:248
PVOID PlatformMemFreePool(PVOID BufferAddress)
Frees a memory pool.
Definition PlatformMem.c:269
BOOLEAN ThreadHolderAssignThreadHolderToProcessDebuggingDetails(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Assign a thread holder to process debugging details.
Definition ThreadHolder.c:42
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
struct _USERMODE_DEBUGGING_PROCESS_DETAILS USERMODE_DEBUGGING_PROCESS_DETAILS
Description of each active thread in user-mode attaching mechanism.
NULL()
Definition test-case-generator.py:530
UINT64 Token
Definition Ud.h:25
BOOLEAN CheckCallBackForInterceptingFirstInstruction
Definition Ud.h:39
BOOLEAN Is32Bit
Definition Ud.h:36
BOOLEAN Enabled
Definition Ud.h:26
PVOID PebAddressToMonitor
Definition Ud.h:27
PEPROCESS Eprocess
Definition Ud.h:34
LIST_ENTRY AttachedProcessList
Definition Ud.h:31

◆ AttachingFindProcessDebuggingDetailsByProcessId()

PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId ( UINT32 ProcessId)

Find user-mode debugging details for threads by process Id.

Parameters
ProcessId
Returns
PUSERMODE_DEBUGGING_PROCESS_DETAILS
185{
187 {
188 //
189 // Check if we found the target thread and if it's enabled
190 //
191 if (ProcessDebuggingDetails->ProcessId == ProcessId && ProcessDebuggingDetails->Enabled)
192 {
193 return ProcessDebuggingDetails;
194 }
195 }
196
197 return NULL;
198}
#define LIST_FOR_EACH_LINK(_head, _struct_type, _member, _var)
Definition MetaMacros.h:34

◆ AttachingFindProcessDebuggingDetailsByToken()

PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByToken ( UINT64 Token)

Find user-mode debugging details for threads by token.

Parameters
Token
Returns
PUSERMODE_DEBUGGING_PROCESS_DETAILS
162{
164 {
165 //
166 // Check if we found the target thread and if it's enabled
167 //
168 if (ProcessDebuggingDetails->Token == Token && ProcessDebuggingDetails->Enabled)
169 {
170 return ProcessDebuggingDetails;
171 }
172 }
173
174 return NULL;
175}

◆ AttachingFindProcessDebuggingDetailsInStartingPhase()

PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsInStartingPhase ( )

Find user-mode debugging details for threads that is in the start-up phase.

Returns
PUSERMODE_DEBUGGING_PROCESS_DETAILS
208{
210 {
211 if (ProcessDebuggingDetails->IsOnTheStartingPhase)
212 {
213 return ProcessDebuggingDetails;
214 }
215 }
216
217 return NULL;
218}

◆ AttachingHandleEntrypointInterception()

VOID AttachingHandleEntrypointInterception ( PROCESSOR_DEBUGGING_STATE * DbgState)

Handle the interception of finding the entrypoint on attaching to user-mode process.

Parameters
DbgStateThe state of the debugger on the current core
Returns
VOID
442{
443 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail = NULL;
444 PAGE_FAULT_EXCEPTION PageFaultErrorCode = {0};
445
446 //
447 // Not increment the RIP register as no instruction is intended to go
448 //
450
451 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
452
453 //
454 // Check to only break on the target process id and thread id and when
455 // the entrypoint is not called, if the thread debugging detail is found
456 //
457 if (ProcessDebuggingDetail != NULL)
458 {
460 {
461 //
462 // Show a message that we reached to the entrypoint
463 //
464 // Log("Reached to the main module entrypoint (%016llx)\n", VmFuncGetLastVmexitRip(DbgState->CoreId));
465
466 //
467 // Not waiting for these event anymore
468 //
470
471 //
472 // Whenever Windows calls the start entrypoint of the target PE, initially,
473 // the module is not loaded in the memory, thus a page-fault will happen and
474 // the page-fault handler will bring the module content to the memory and after
475 // that, the start entrypoint of PE is called again
476 // It's not possible for us to handle everything here without checking for the
477 // possible page-fault, it is because the first instruction is not available to be
478 // read from the memory, thus, it shows a wrong instruction and the user might not
479 // use the instrumentation step-in from the start up of the entrypoint.
480 // Because if the user uses the instrumentation step-in command then it should go
481 // the page-fault handler routine in the kernel and it's not what the user expects
482 // we inject a #PF here and let the Windows handle the page-fault. Meanwhile, we
483 // set the hardware debug breakpoint again at the start of the entrypoint, so, the
484 // next time that the instruction is about to be fetched, a vm-exit happens as a
485 // result of intercepting #DBs
486 // In some cases, there is no need to inject #PF to the guest. One example is when
487 // the target page is already available in the memory like the same process is also
488 // open in the debuggee. In these cases, we handle the break directly without injecting
489 // any page-fault
490 //
491
492 if (!CheckAccessValidityAndSafety(ProcessDebuggingDetail->EntrypointOfMainModule, sizeof(CHAR)))
493 {
494 // LogInfo("Injecting #PF for entrypoint at : %llx", ProcessDebuggingDetail->EntrypointOfMainModule);
495
496 //
497 // We're waiting for this pointer to be called again after handling page-fault
498 //
500
501 //
502 // Create page-fault error code (user, fetch #PF)
503 //
504 PageFaultErrorCode.AsUInt = 0x14;
505
506 //
507 // Inject the page-fault
508 //
510 ProcessDebuggingDetail->EntrypointOfMainModule,
511 PageFaultErrorCode.AsUInt);
512
513 //
514 // Also, set the RFLAGS.TF to intercept the process (thread) again after inject #PF
515 //
517
518 //
519 // Indicate that we should set the trap flag to the FALSE next time on
520 // the same process/thread
521 //
522 if (!BreakpointRestoreTheTrapFlagOnceTriggered(HANDLE_TO_UINT32(PsGetCurrentProcessId()), HANDLE_TO_UINT32(PsGetCurrentThreadId())))
523 {
524 LogWarning("Warning, it is currently not possible to add the current process/thread to the list of processes "
525 "where the trap flag should be masked. Please ensure that you manually unset the trap flag");
526 }
527 }
528 else
529 {
530 //
531 // Address is valid, probably the module is previously loaded
532 // or another process with same image is currently running
533 // Thus, there is no need to inject #PF, we'll handle it in debugger
534 //
535 AttachingReachedToValidLoadedModule(DbgState, ProcessDebuggingDetail);
536 }
537 }
539 {
540 //
541 // not waiting for a break after the page-fault anymore
542 //
544
545 //
546 // We reached here as a result of setting the trap flag after
547 // injecting a page-fault
548 //
549 AttachingReachedToValidLoadedModule(DbgState, ProcessDebuggingDetail);
550 }
551 }
552}
BOOLEAN AttachingReachedToValidLoadedModule(PROCESSOR_DEBUGGING_STATE *DbgState, PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Handle cases where we reached to the valid loaded module The main module should be loaded once we rea...
Definition Attaching.c:345
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.
Definition BreakpointCommands.c:174
char CHAR
Definition BasicTypes.h:33
#define LogWarning(format,...)
Log in the case of warning.
Definition HyperDbgHyperLogIntrinsics.h:99
IMPORT_EXPORT_VMM VOID VmFuncSetRflagTrapFlag(BOOLEAN Set)
Set Rflag's trap flag.
Definition Export.c:123
IMPORT_EXPORT_VMM BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:318
IMPORT_EXPORT_VMM VOID VmFuncSuppressRipIncrement(UINT32 CoreId)
Suppress the incrementation of RIP.
Definition Export.c:34
IMPORT_EXPORT_VMM VOID VmFuncEventInjectPageFaultWithCr2(UINT32 CoreId, UINT64 Address, UINT32 PageFaultCode)
Inject PF and configure CR2 register.
Definition Export.c:900
BOOLEAN g_IsWaitingForReturnAndRunFromPageFault
Whether the thread attaching mechanism is waiting for a page-fault finish or not.
Definition Global.h:194
BOOLEAN g_IsWaitingForUserModeProcessEntryToBeCalled
Whether the thread attaching mechanism is waiting for DB or not.
Definition Global.h:206
UINT32 CoreId
Definition State.h:168
UINT64 EntrypointOfMainModule
Definition Ud.h:32

◆ AttachingInitialize()

BOOLEAN AttachingInitialize ( )

Initialize the attaching mechanism.

as we use the functionalities for these functions, we initialize them from the debugger at start up of debugger (not initialization of user-debugger)

Returns
BOOLEAN
23{
24 UNICODE_STRING FunctionName;
25
26 //
27 // Find address of PsGetProcessPeb
28 //
29 if (g_PsGetProcessPeb == NULL)
30 {
31 RtlInitUnicodeString(&FunctionName, L"PsGetProcessPeb");
32 g_PsGetProcessPeb = (PsGetProcessPeb)MmGetSystemRoutineAddress(&FunctionName);
33
34 if (g_PsGetProcessPeb == NULL)
35 {
36 LogError("Err, cannot resolve PsGetProcessPeb");
37
38 //
39 // Won't fail the entire debugger for not finding this
40 //
41 // return FALSE;
42 }
43 }
44
45 //
46 // Find address of PsGetProcessWow64Process
47 //
49 {
50 RtlInitUnicodeString(&FunctionName, L"PsGetProcessWow64Process");
51 g_PsGetProcessWow64Process = (PsGetProcessWow64Process)MmGetSystemRoutineAddress(&FunctionName);
52
54 {
55 LogError("Err, cannot resolve PsGetProcessPeb");
56
57 //
58 // Won't fail the entire debugger for not finding this
59 //
60 // return FALSE;
61 }
62 }
63
64 //
65 // Find address of ZwQueryInformationProcess
66 //
68 {
69 UNICODE_STRING RoutineName;
70
71 RtlInitUnicodeString(&RoutineName, L"ZwQueryInformationProcess");
72
73 g_ZwQueryInformationProcess = (ZwQueryInformationProcess)MmGetSystemRoutineAddress(&RoutineName);
74
76 {
77 LogError("Err, cannot resolve ZwQueryInformationProcess");
78
79 //
80 // Won't fail the entire debugger for not finding this
81 //
82 // return FALSE;
83 }
84 }
85
86 return TRUE;
87}
ZwQueryInformationProcess g_ZwQueryInformationProcess
Address of ZwQueryInformationProcess.
Definition UserAccess.h:187
PsGetProcessPeb g_PsGetProcessPeb
Address of PsGetProcessPeb.
Definition UserAccess.h:193
PPEB32(NTAPI * PsGetProcessWow64Process)(PEPROCESS Process)
Definition UserAccess.h:177
PsGetProcessWow64Process g_PsGetProcessWow64Process
Address of PsGetProcessWow64Process.
Definition UserAccess.h:199
NTSTATUS(* ZwQueryInformationProcess)(__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __out_bcount(ProcessInformationLength) PVOID ProcessInformation, __in ULONG ProcessInformationLength, __out_opt PULONG ReturnLength)
Definition UserAccess.h:168
PPEB(NTAPI * PsGetProcessPeb)(PEPROCESS Process)
Definition UserAccess.h:175
struct _UNICODE_STRING UNICODE_STRING

◆ AttachingKillProcess()

BOOLEAN AttachingKillProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS KillRequest)

Kill the target process from kernel-mode.

this function should not be called in vmx-root

Parameters
KillRequest
Returns
BOOLEAN
1129{
1130 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1131 BOOLEAN WasKilled = FALSE;
1132
1133 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(KillRequest->ProcessId);
1134
1135 //
1136 // Check if process is valid in process debugging details
1137 //
1138 if (!ProcessDebuggingDetail)
1139 {
1140 //
1141 // not found
1142 //
1144 return FALSE;
1145 }
1146
1147 //
1148 // Check if process exists or not
1149 //
1150 if (!CommonIsProcessExist(ProcessDebuggingDetail->ProcessId))
1151 {
1152 //
1153 // Process was killed before killing it here (not exists)
1154 //
1155
1156 //
1157 // Remove the entry from the process debugging details list
1158 //
1160
1162 return FALSE;
1163 }
1164
1165 //
1166 // Check if we can kill it using the first method
1167 //
1168 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_1);
1169
1170 if (WasKilled)
1171 {
1172 goto Success;
1173 }
1174
1175 //
1176 // Check if we can kill it using the second method
1177 //
1178 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_2);
1179
1180 if (WasKilled)
1181 {
1182 goto Success;
1183 }
1184
1185 //
1186 // Check if we can kill it using the third method
1187 //
1188 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_3);
1189
1190 if (WasKilled)
1191 {
1192 goto Success;
1193 }
1194
1195 //
1196 // No way we can kill the shit :(
1197 //
1199 return FALSE;
1200
1201Success:
1202
1203 //
1204 // Remove the entry from the process debugging details list
1205 //
1207
1209 return TRUE;
1210}
BOOLEAN AttachingRemoveProcessDebuggingDetailsByToken(UINT64 Token)
Remove user-mode debugging details for threads by its token.
Definition Attaching.c:254
UCHAR BOOLEAN
Definition BasicTypes.h:35
#define DEBUGGER_ERROR_UNABLE_TO_KILL_THE_PROCESS
error, unable to kill the target process
Definition ErrorCodes.h:326
#define DEBUGGER_ERROR_THE_USER_DEBUGGER_NOT_ATTACHED_TO_THE_PROCESS
error, the user debugger is not attached to the target process
Definition ErrorCodes.h:350
#define DEBUGGER_ERROR_UNABLE_TO_KILL_THE_PROCESS_DOES_NOT_EXISTS
error, unable to kill the target process. process does not exists
Definition ErrorCodes.h:417
_Use_decl_annotations_ BOOLEAN CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod)
Kill a user-mode process with different methods.
Definition Common.c:159
BOOLEAN CommonIsProcessExist(UINT32 ProcId)
Checks whether the process with ProcId exists or not.
Definition Common.c:24
@ PROCESS_KILL_METHOD_2
Definition Common.h:66
@ PROCESS_KILL_METHOD_1
Definition Common.h:65
@ PROCESS_KILL_METHOD_3
Definition Common.h:67
UINT32 ProcessId
Definition RequestStructures.h:682

◆ AttachingPauseProcess()

BOOLEAN AttachingPauseProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest)

Pauses the target process.

this function should not be called in vmx-root

Parameters
PauseRequest
Returns
BOOLEAN
1060{
1062 {
1063 //
1064 // The pausing operation was successful
1065 //
1067 return TRUE;
1068 }
1069 else
1070 {
1072 return FALSE;
1073 }
1074}

◆ AttachingPerformAttachToProcess()

BOOLEAN AttachingPerformAttachToProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest,
BOOLEAN IsAttachingToEntrypoint )

Attach to the target process.

this function should not be called in vmx-root

Parameters
AttachRequest
IsAttachingToEntrypoint
Returns
BOOLEAN
777{
778 PEPROCESS SourceProcess;
779 UINT64 ProcessDebuggingToken;
780 UINT64 PebAddressToMonitor;
781 BOOLEAN ResultOfApplyingEvent;
782 BOOLEAN Is32Bit;
783 PUSERMODE_DEBUGGING_PROCESS_DETAILS TempProcessDebuggingDetail;
785
786 if (g_PsGetProcessWow64Process == NULL || g_PsGetProcessPeb == NULL)
787 {
789 return FALSE;
790 }
791
792 if (PsLookupProcessByProcessId((HANDLE)AttachRequest->ProcessId, &SourceProcess) != STATUS_SUCCESS)
793 {
794 //
795 // if the process not found
796 //
798 return FALSE;
799 }
800
801 ObDereferenceObject(SourceProcess);
802
803 //
804 // Check to avoid double attaching to a process
805 //
806 TempProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(AttachRequest->ProcessId);
807
808 if (TempProcessDebuggingDetail != NULL && TempProcessDebuggingDetail->Eprocess == SourceProcess)
809 {
810 //
811 // The user already attached to this process
812 //
814 return FALSE;
815 }
816
817 //
818 // check whether the target process is 32-bit or 64-bit
819 //
820 if (!UserAccessIsWow64Process((HANDLE)AttachRequest->ProcessId, &Is32Bit))
821 {
822 //
823 // Unable to detect whether it's 32-bit or 64-bit
824 //
826 return FALSE;
827 }
828
829 //
830 // Set the Is32Bit flag of attach request
831 //
832 AttachRequest->Is32Bit = Is32Bit;
833
834 //
835 // Get 32-bit or 64-bit PEB
836 //
837 if (Is32Bit)
838 {
839 PebAddressToMonitor = (UINT64)((PPEB32)g_PsGetProcessWow64Process(SourceProcess));
840 }
841 else
842 {
843 PebAddressToMonitor = (UINT64)((PPEB)g_PsGetProcessPeb(SourceProcess));
844 }
845
846 if (PebAddressToMonitor == (UINT64)NULL)
847 {
849 return FALSE;
850 }
851
852 //
853 // Create the debugging detail for process
854 //
855 ProcessDebuggingToken = AttachingCreateProcessDebuggingDetails(AttachRequest->ProcessId,
856 TRUE,
857 Is32Bit,
858 AttachRequest->CheckCallbackAtFirstInstruction,
859 SourceProcess,
860 PebAddressToMonitor);
861
862 //
863 // Check if we successfully get the token
864 //
865 if (ProcessDebuggingToken == (UINT64)NULL)
866 {
868 return FALSE;
869 }
870
871 //
872 // Check if it's attaching at entrypoint or attaching to a previously running process
873 //
874 if (IsAttachingToEntrypoint)
875 {
876 //
877 // *** attaching to the entrypoint of the process ***
878 //
879
880 //
881 // Check whether any special initialization for thread safe features
882 // is needed or not
883 //
884 if (AttachRequest->CheckCallbackAtFirstInstruction)
885 {
886 AttachingCheckForSafeCallbackRequestedInitializations(AttachRequest, ProcessDebuggingToken);
887 }
888
889 //
890 // Waiting for #DB to be triggered
891 //
893
894 //
895 // Set the starting point of the thread
896 //
898 {
899 //
900 // Remove the created thread debugging detail
901 //
903
906 return FALSE;
907 }
908
909 //
910 // Apply monitor memory range to the PEB address
911 //
912
913 EptHookDetails.StartAddress = PebAddressToMonitor;
914
915 //
916 // both start and the end are at the same address
917 // because it hooks an entire page anyway
918 //
919 EptHookDetails.EndAddress = PebAddressToMonitor;
920 EptHookDetails.SetHookForRead = TRUE;
921 EptHookDetails.SetHookForWrite = TRUE;
922 EptHookDetails.SetHookForExec = FALSE;
923
924 ResultOfApplyingEvent = DebuggerEventEnableMonitorReadWriteExec(
925 &EptHookDetails,
926 AttachRequest->ProcessId,
927 FALSE // Applied from VMX non-root mode
928 );
929
930 if (!ResultOfApplyingEvent)
931 {
932 //
933 // Remove the created thread debugging detail
934 //
936
939 return FALSE;
940 }
941 }
942 else
943 {
944 //
945 // *** attaching to previously running process ***
946 //
947 if (!AttachingConfigureInterceptingThreads(ProcessDebuggingToken, TRUE))
948 {
949 //
950 // Remove the created thread debugging details
951 //
953
955 return FALSE;
956 }
957 }
958
959 //
960 // Operation was successful
961 //
962 AttachRequest->Token = ProcessDebuggingToken;
964 return TRUE;
965}
UINT64 AttachingCreateProcessDebuggingDetails(UINT32 ProcessId, BOOLEAN Enabled, BOOLEAN Is32Bit, BOOLEAN CheckCallbackAtFirstInstruction, PEPROCESS Eprocess, UINT64 PebAddressToMonitor)
Create user-mode debugging details for threads.
Definition Attaching.c:99
BOOLEAN AttachingSetStartingPhaseOfProcessDebuggingDetailsByToken(BOOLEAN Set, UINT64 Token)
Set the start up phase of a debugging thread buffer by its token.
Definition Attaching.c:297
BOOLEAN AttachingCheckForSafeCallbackRequestedInitializations(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest, UINT64 ProcessDebuggingToken)
This function checks whether any special initialization is needed while attaching to a process that r...
Definition Attaching.c:753
BOOLEAN DebuggerEventEnableMonitorReadWriteExec(EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR *HookingDetails, UINT32 ProcessId, BOOLEAN ApplyDirectlyFromVmxRoot)
Apply monitor ept hook events for address.
Definition DebuggerEvents.c:68
BOOLEAN UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit.
Definition UserAccess.c:753
struct _PEB32 * PPEB32
struct _PEB * PPEB
struct _EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR EPT_HOOKS_ADDRESS_DETAILS_FOR_MEMORY_MONITOR
Setting details for EPT Hooks (!monitor).
#define DEBUGGER_ERROR_UNABLE_TO_DETECT_32_BIT_OR_64_BIT_PROCESS
error, unable to get 32-bit or 64-bit of the target process
Definition ErrorCodes.h:320
#define DEBUGGER_ERROR_UNABLE_TO_ATTACH_TO_AN_ALREADY_ATTACHED_PROCESS
error, user debugger already attached to this process
Definition ErrorCodes.h:344
#define DEBUGGER_ERROR_UNABLE_TO_ATTACH_TO_TARGET_USER_MODE_PROCESS
error, failed to attach to the target user-mode process
Definition ErrorCodes.h:294
#define DEBUGGER_ERROR_FUNCTIONS_FOR_INITIALIZING_PEB_ADDRESSES_ARE_NOT_INITIALIZED
error, the needed routines for debugging is not initialized
Definition ErrorCodes.h:314
BOOLEAN CheckCallbackAtFirstInstruction
Definition RequestStructures.h:684
BOOLEAN Is32Bit
Definition RequestStructures.h:685
UINT64 StartAddress
Definition DataTypes.h:381
BOOLEAN SetHookForRead
Definition DataTypes.h:383
BOOLEAN SetHookForWrite
Definition DataTypes.h:384
UINT64 EndAddress
Definition DataTypes.h:382
BOOLEAN SetHookForExec
Definition DataTypes.h:385

◆ AttachingPerformDetach()

BOOLEAN AttachingPerformDetach ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest)

Clearing hooks after resuming the process.

this function should not be called in vmx-root

Parameters
DetachRequest
Returns
BOOLEAN
1221{
1222 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1223
1224 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(DetachRequest->ProcessId);
1225
1226 //
1227 // Check if process is valid in process debugging details
1228 //
1229 if (!ProcessDebuggingDetail)
1230 {
1231 //
1232 // not found
1233 //
1235 return FALSE;
1236 }
1237
1238 //
1239 // If the threads are paused, we can't detach from the target process
1240 // before sending this request, the debugger should continued all the
1241 // threads by sending a continue packet
1242 //
1243 if (ThreadHolderIsAnyPausedThreadInProcess(ProcessDebuggingDetail))
1244 {
1245 //
1246 // We found a thread that is still pause
1247 //
1249 return FALSE;
1250 }
1251
1252 //
1253 // Remove the process from interception mechanisms
1254 //
1255 AttachingConfigureInterceptingThreads(ProcessDebuggingDetail->Token, FALSE);
1256
1257 //
1258 // Remove the entry from the process debugging details list
1259 //
1261
1263 return TRUE;
1264}
BOOLEAN ThreadHolderIsAnyPausedThreadInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Check if there is any thread paused by checking process debugging details.
Definition ThreadHolder.c:77
#define DEBUGGER_ERROR_UNABLE_TO_DETACH_AS_THERE_ARE_PAUSED_THREADS
error, cannot detach from the process as there are paused threads
Definition ErrorCodes.h:356

◆ AttachingQueryCountOfActiveDebuggingThreadsAndProcesses()

BOOLEAN AttachingQueryCountOfActiveDebuggingThreadsAndProcesses ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfDebugThreadsRequest)

Query count of active debugging threads.

Parameters
QueryCountOfDebugThreadsRequest
Returns
BOOLEAN
1368{
1369 UINT32 CountOfProcessesAndThreads;
1370
1371 //
1372 // Count the result
1373 //
1375
1376 //
1377 // Set the results
1378 //
1379 QueryCountOfDebugThreadsRequest->CountOfActiveDebuggingThreadsAndProcesses = CountOfProcessesAndThreads;
1380 QueryCountOfDebugThreadsRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1381
1382 return TRUE;
1383}
UINT32 ThreadHolderQueryCountOfActiveDebuggingThreadsAndProcesses()
Query count of active debugging threads and processes.
Definition ThreadHolder.c:527
unsigned int UINT32
Definition BasicTypes.h:54
UINT32 CountOfActiveDebuggingThreadsAndProcesses
Definition RequestStructures.h:691

◆ AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses()

BOOLEAN AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses ( PVOID BufferToStoreDetails,
UINT32 BufferSize )

Query details of active debugging threads.

Parameters
BufferToStoreDetails
BufferSize
Returns
BOOLEAN
1394{
1395 UINT32 CountOfProcessesAndThreadsToStore;
1396
1397 CountOfProcessesAndThreadsToStore = BufferSize / SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS;
1398
1399 if (CountOfProcessesAndThreadsToStore == 0)
1400 {
1401 //
1402 // No active thread or process
1403 //
1404 return FALSE;
1405 }
1406
1407 // LogInfo("Count of active process and threads : %x", CountOfProcessesAndThreadsToStore);
1408
1409 //
1410 // Get the results
1411 //
1412 ThreadHolderQueryDetailsOfActiveDebuggingThreadsAndProcesses(BufferToStoreDetails, CountOfProcessesAndThreadsToStore);
1413
1414 return TRUE;
1415}
VOID ThreadHolderQueryDetailsOfActiveDebuggingThreadsAndProcesses(USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS *BufferToStoreDetails, UINT32 MaxCount)
Query details of active debugging threads and processes.
Definition ThreadHolder.c:585
#define SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS
Definition RequestStructures.h:860

◆ AttachingReachedToValidLoadedModule()

BOOLEAN AttachingReachedToValidLoadedModule ( PROCESSOR_DEBUGGING_STATE * DbgState,
PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail )

Handle cases where we reached to the valid loaded module The main module should be loaded once we reach to this function.

Parameters
DbgStateThe state of the debugger on the current core
ProcessDebuggingDetail
Returns
BOOLEAN
347{
348 DEBUGGEE_BP_PACKET BpRequest = {0};
349
350 //
351 // Double check to make sure the main module is loaded
352 //
353 if (!CheckAccessValidityAndSafety(ProcessDebuggingDetail->EntrypointOfMainModule, sizeof(CHAR)))
354 {
355 LogError("Err, the main module is not loaded or the main entrypoint is not valid");
356 return FALSE;
357 }
358
359 //
360 // Setting a breakpoint to the main entrypoint of the module
361 //
362 BpRequest.Address = ProcessDebuggingDetail->EntrypointOfMainModule;
366
367 //
368 // Remove the breakpoint after hit
369 //
370 BpRequest.RemoveAfterHit = TRUE;
371
372 //
373 // Check if the process needs to check for callbacks for the very first instruction
374 //
375 if (ProcessDebuggingDetail->CheckCallBackForInterceptingFirstInstruction)
376 {
377 //
378 // This breakpoint should check for callbacks
379 //
380 BpRequest.CheckForCallbacks = TRUE;
381 }
382
383 //
384 // Register the breakpoint
385 // Note that, even though it's a user-mode breakpoint, we are currently
386 // in the memory layout of the target process, thus, no switching memory
387 // layout is needed
388 //
389 if (!BreakpointAddNew(&BpRequest, FALSE))
390 {
391 LogError("Err, unable to set breakpoint on the entrypoint module");
392 return FALSE;
393 }
394
395 //
396 // Finish the starting point of the thread
397 //
399
400 //
401 // Check if we're connect to the kHyperDbg or uHyperDbg
402 //
404 {
405 //
406 // Handling state through the kernel-mode debugger
407 //
410 NULL);
411 }
412 else if (g_UserDebuggerState)
413 {
414 //
415 // Handling state through the user-mode debugger
416 //
417 UdHandleInstantBreak(DbgState,
419 ProcessDebuggingDetail);
420 }
421 else
422 {
423 LogError("Err, no debugger is attached to handle the entrypoint interception");
424 return FALSE;
425 }
426
427 //
428 // Handled successfully
429 //
430 return TRUE;
431}
BOOLEAN BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg, BOOLEAN SwitchToTargetMemoryLayout)
Add new breakpoints.
Definition BreakpointCommands.c:950
_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
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_STARTING_MODULE_LOADED
Definition Connection.h:36
#define DEBUGGEE_BP_APPLY_TO_ALL_PROCESSES
The constant to apply to all processes for bp command.
Definition Constants.h:781
#define DEBUGGEE_BP_APPLY_TO_ALL_THREADS
The constant to apply to all threads for bp command.
Definition Constants.h:787
#define DEBUGGEE_BP_APPLY_TO_ALL_CORES
The constant to apply to all cores for bp command.
Definition Constants.h:775
struct _DEBUGGEE_BP_PACKET DEBUGGEE_BP_PACKET
The structure of bp command packet in HyperDbg.
BOOLEAN g_KernelDebuggerState
shows whether the kernel debugger is enabled or disabled
Definition Global.h:151
UINT32 Tid
Definition RequestStructures.h:1519
BOOLEAN RemoveAfterHit
Definition RequestStructures.h:1521
UINT32 Core
Definition RequestStructures.h:1520
BOOLEAN CheckForCallbacks
Definition RequestStructures.h:1522
UINT64 Address
Definition RequestStructures.h:1517
UINT32 Pid
Definition RequestStructures.h:1518

◆ AttachingRemoveAndFreeAllProcessDebuggingDetails()

VOID AttachingRemoveAndFreeAllProcessDebuggingDetails ( )

Remove and deallocate all thread debuggig details.

Returns
VOID
227{
229 {
230 //
231 // Free the thread holding structure(s)
232 //
233 ThreadHolderFreeHoldingStructures(ProcessDebuggingDetails);
234
235 //
236 // Remove thread debugging detail from the list active threads
237 //
238 RemoveEntryList(&ProcessDebuggingDetails->AttachedProcessList);
239
240 //
241 // Unallocate the pool
242 //
243 PlatformMemFreePool(ProcessDebuggingDetails);
244 }
245}
VOID ThreadHolderFreeHoldingStructures(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Free all of thread holder structures.
Definition ThreadHolder.c:501

◆ AttachingRemoveHooks()

BOOLEAN AttachingRemoveHooks ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest)

Clearing hooks after resuming the process.

this function should not be called in vmx-root

Parameters
AttachRequest
Returns
BOOLEAN
999{
1000 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
1001
1002 //
1003 // Get the thread debugging detail
1004 //
1005 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(AttachRequest->Token);
1006
1007 //
1008 // Check if token is valid or not
1009 //
1010 if (!ProcessDebuggingDetails)
1011 {
1013 return FALSE;
1014 }
1015
1016 //
1017 // Check if the entrypoint is reached or not,
1018 // if it's not reached then we won't remove the hooks
1019 //
1021 {
1022 //
1023 // The entrypoint is called, we should remove the hook
1024 //
1025 if (!ConfigureEptHookUnHookSingleAddress((UINT64)ProcessDebuggingDetails->PebAddressToMonitor,
1026 (UINT64)NULL,
1027 ProcessDebuggingDetails->ProcessId))
1028 {
1030 return FALSE;
1031 }
1032 else
1033 {
1034 //
1035 // The unhooking operation was successful
1036 //
1038 return TRUE;
1039 }
1040 }
1041 else
1042 {
1043 //
1044 // The entrypoint is not called, we shouldn't remove the hook
1045 //
1047 return FALSE;
1048 }
1049}
#define DEBUGGER_ERROR_UNABLE_TO_REMOVE_HOOKS
error, could not remove the previous hook
Definition ErrorCodes.h:308
#define DEBUGGER_ERROR_UNABLE_TO_REMOVE_HOOKS_ENTRYPOINT_NOT_REACHED
error, failed to remove hooks as entrypoint is not reached yet
Definition ErrorCodes.h:302
IMPORT_EXPORT_VMM BOOLEAN ConfigureEptHookUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, UINT32 ProcessId)
Remove single hook from the hooked pages list and invalidate TLB.
Definition Configuration.c:190

◆ AttachingRemoveProcessDebuggingDetailsByToken()

BOOLEAN AttachingRemoveProcessDebuggingDetailsByToken ( UINT64 Token)

Remove user-mode debugging details for threads by its token.

Parameters
Token
Returns
BOOLEAN
255{
256 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
257
258 //
259 // Find the entry
260 //
261 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(Token);
262
263 if (!ProcessDebuggingDetails)
264 {
265 //
266 // Token not found!
267 //
268 return FALSE;
269 }
270
271 //
272 // Free the thread holding structure(s)
273 //
274 ThreadHolderFreeHoldingStructures(ProcessDebuggingDetails);
275
276 //
277 // Remove thread debugging detail from the list active threads
278 //
279 RemoveEntryList(&ProcessDebuggingDetails->AttachedProcessList);
280
281 //
282 // Unallocate the pool
283 //
284 PlatformMemFreePool(ProcessDebuggingDetails);
285
286 return TRUE;
287}

◆ AttachingSetStartingPhaseOfProcessDebuggingDetailsByToken()

BOOLEAN AttachingSetStartingPhaseOfProcessDebuggingDetailsByToken ( BOOLEAN Set,
UINT64 Token )

Set the start up phase of a debugging thread buffer by its token.

Parameters
Set
Token
Returns
BOOLEAN
298{
299 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
300
301 //
302 // If it's set to TRUE, then we check to only put 1 thread at the time
303 // to the starting phase
304 //
305 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsInStartingPhase();
306
307 if (Set && ProcessDebuggingDetails != NULL)
308 {
309 //
310 // There is another thread in starting phase!
311 //
312 return FALSE;
313 }
314
315 //
316 // Find the entry
317 //
318 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(Token);
319
320 if (!ProcessDebuggingDetails)
321 {
322 //
323 // Token not found!
324 //
325 return FALSE;
326 }
327
328 //
329 // Set the starting phase
330 //
331 ProcessDebuggingDetails->IsOnTheStartingPhase = Set;
332
333 return TRUE;
334}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsInStartingPhase()
Find user-mode debugging details for threads that is in the start-up phase.
Definition Attaching.c:207
BOOLEAN IsOnTheStartingPhase
Definition Ud.h:37

◆ AttachingSwitchProcess()

BOOLEAN AttachingSwitchProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest)

Switch to the target thread.

Parameters
SwitchRequest
Returns
BOOLEAN
1274{
1275 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1276 PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetail;
1277
1278 if (SwitchRequest->ProcessId != NULL_ZERO)
1279 {
1280 //
1281 // Switch by process id
1282 //
1283 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(SwitchRequest->ProcessId);
1284 }
1285 else if (SwitchRequest->ThreadId != NULL_ZERO)
1286 {
1287 //
1288 // Switch by thread id
1289 //
1290 ProcessDebuggingDetail = ThreadHolderGetProcessDebuggingDetailsByThreadId(SwitchRequest->ThreadId);
1291 }
1292 else
1293 {
1295 return FALSE;
1296 }
1297
1298 //
1299 // Check if process is valid in process debugging details
1300 //
1301 if (!ProcessDebuggingDetail)
1302 {
1303 //
1304 // not found
1305 //
1307 return FALSE;
1308 }
1309
1310 //
1311 // Set the IsPaused field
1312 //
1313 if (SwitchRequest->ThreadId != NULL_ZERO)
1314 {
1315 //
1316 // Find the thread's state
1317 //
1318 ThreadDebuggingDetail = ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(ProcessDebuggingDetail->ProcessId,
1319 SwitchRequest->ThreadId);
1320 }
1321 else
1322 {
1323 //
1324 // Find the first thread in the process
1325 //
1326 ThreadDebuggingDetail = ThreadHolderGetProcessFirstThreadDetailsByProcessId(ProcessDebuggingDetail->ProcessId);
1327 }
1328
1329 //
1330 // Check if we find the target thread
1331 //
1332 if (!ThreadDebuggingDetail)
1333 {
1334 //
1335 // not found
1336 //
1338 return FALSE;
1339 }
1340
1341 //
1342 // Fill the needed details by user mode
1343 //
1344 SwitchRequest->Token = ProcessDebuggingDetail->Token;
1345 SwitchRequest->ProcessId = ProcessDebuggingDetail->ProcessId;
1346 SwitchRequest->ThreadId = ThreadDebuggingDetail->ThreadId;
1347 SwitchRequest->Is32Bit = ProcessDebuggingDetail->Is32Bit;
1348 SwitchRequest->Rip = ThreadDebuggingDetail->ThreadRip;
1349 SwitchRequest->IsPaused = ThreadDebuggingDetail->IsPaused;
1350 SwitchRequest->SizeOfInstruction = ThreadDebuggingDetail->SizeOfInstruction;
1351
1352 memcpy(&SwitchRequest->InstructionBytesOnRip[0],
1353 &ThreadDebuggingDetail->InstructionBytesOnRip[0],
1354 ThreadDebuggingDetail->SizeOfInstruction);
1355
1357 return TRUE;
1358}
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(UINT32 ProcessId, UINT32 ThreadId)
Find the active threads of the process from process id.
Definition ThreadHolder.c:145
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessFirstThreadDetailsByProcessId(UINT32 ProcessId)
Find the first active threads of the process from process id.
Definition ThreadHolder.c:193
PUSERMODE_DEBUGGING_PROCESS_DETAILS ThreadHolderGetProcessDebuggingDetailsByThreadId(UINT32 ThreadId)
Find the active process debugging detail from the thread id.
Definition ThreadHolder.c:241
struct _USERMODE_DEBUGGING_THREAD_DETAILS * PUSERMODE_DEBUGGING_THREAD_DETAILS
#define NULL_ZERO
Definition BasicTypes.h:110
#define DEBUGGER_ERROR_UNABLE_TO_SWITCH_PROCESS_ID_OR_THREAD_ID_IS_INVALID
error, cannot switch to new thread as the process id or thread id is not found
Definition ErrorCodes.h:362
#define DEBUGGER_ERROR_UNABLE_TO_SWITCH_THERE_IS_NO_THREAD_ON_THE_PROCESS
error, cannot switch to new thread the process doesn't contain an active thread
Definition ErrorCodes.h:368
UINT32 SizeOfInstruction
Definition RequestStructures.h:688
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition RequestStructures.h:687
BOOLEAN IsPaused
Definition RequestStructures.h:689
UINT32 ThreadId
Definition RequestStructures.h:683
UINT64 Rip
Definition RequestStructures.h:686
UINT32 SizeOfInstruction
Definition ThreadHolder.h:38
UINT64 ThreadRip
Definition ThreadHolder.h:35
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition ThreadHolder.h:37
UINT32 ThreadId
Definition ThreadHolder.h:34
BOOLEAN IsPaused
Definition ThreadHolder.h:36

◆ AttachingTargetProcess()

VOID AttachingTargetProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS Request)

Dispatch and perform attaching tasks.

this function should not be called in vmx-root

Parameters
AttachRequest
Returns
VOID
1426{
1427 //
1428 // As we're here, we need to initialize the user-mode debugger
1429 //
1431 {
1433 return;
1434 }
1435
1436 switch (Request->Action)
1437 {
1439
1441
1442 break;
1443
1445
1446 AttachingPerformDetach(Request);
1447
1448 break;
1449
1451
1452 AttachingRemoveHooks(Request);
1453
1454 break;
1455
1457
1458 AttachingKillProcess(Request);
1459
1460 break;
1461
1463
1464 AttachingContinueProcess(Request);
1465
1466 break;
1467
1469
1470 AttachingPauseProcess(Request);
1471
1472 break;
1473
1475
1476 AttachingSwitchProcess(Request);
1477
1478 break;
1479
1481
1483
1484 break;
1485
1486 default:
1487
1489
1490 break;
1491 }
1492}
BOOLEAN AttachingSwitchProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest)
Switch to the target thread.
Definition Attaching.c:1273
BOOLEAN AttachingPerformDetach(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest)
Clearing hooks after resuming the process.
Definition Attaching.c:1220
BOOLEAN AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest, BOOLEAN IsAttachingToEntrypoint)
Attach to the target process.
Definition Attaching.c:776
BOOLEAN AttachingPauseProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest)
Pauses the target process.
Definition Attaching.c:1059
BOOLEAN AttachingQueryCountOfActiveDebuggingThreadsAndProcesses(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfDebugThreadsRequest)
Query count of active debugging threads.
Definition Attaching.c:1367
BOOLEAN AttachingRemoveHooks(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest)
Clearing hooks after resuming the process.
Definition Attaching.c:998
BOOLEAN AttachingKillProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS KillRequest)
Kill the target process from kernel-mode.
Definition Attaching.c:1128
BOOLEAN AttachingContinueProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS ContinueRequest)
Continues the target process.
Definition Attaching.c:1084
BOOLEAN UdInitializeUserDebugger()
initialize user debugger
Definition Ud.c:21
#define DEBUGGER_ERROR_DEBUGGER_NOT_INITIALIZED
error, the user debugger cannot be initialized
Definition ErrorCodes.h:558
#define DEBUGGER_ERROR_INVALID_ACTION_TYPE
error, invalid type of action
Definition ErrorCodes.h:39
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_DETACH
Definition RequestStructures.h:665
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_QUERY_COUNT_OF_ACTIVE_DEBUGGING_THREADS
Definition RequestStructures.h:671
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_CONTINUE_PROCESS
Definition RequestStructures.h:668
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_KILL_PROCESS
Definition RequestStructures.h:667
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_SWITCH_BY_PROCESS_OR_THREAD
Definition RequestStructures.h:670
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_PAUSE_PROCESS
Definition RequestStructures.h:669
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_ATTACH
Definition RequestStructures.h:664
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_REMOVE_HOOKS
Definition RequestStructures.h:666
DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_TYPE Action
Definition RequestStructures.h:690
BOOLEAN IsStartingNewProcess
Definition RequestStructures.h:681