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, UINT64 UsermodeReservedBuffer)
 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 AttachingCheckPageFaultsWithUserDebugger (UINT32 CoreId, UINT64 Address, UINT32 PageFaultErrorCode)
 Check page-faults with user-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 AttachingHandleCr3VmexitsForThreadInterception (UINT32 CoreId, CR3_TYPE NewCr3)
 Handle the cr3 vm-exits for thread interception.
 
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 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
558{
559 PEPROCESS SourceProcess;
560 KAPC_STATE State = {0};
561
562 if (PsLookupProcessByProcessId((HANDLE)ProcessId, &SourceProcess) != STATUS_SUCCESS)
563 {
564 //
565 // if the process not found
566 //
567 return FALSE;
568 }
569
570 __try
571 {
572 KeStackAttachProcess(SourceProcess, &State);
573
574 //
575 // Fill the memory with nops
576 //
577 memset((void *)ReservedBuffAddress, 0x90, PAGE_SIZE);
578
579 //
580 // Set jmps to form a loop (little endians)
581 //
582 // Disassembly of section .text:
583 // 0000000000000000 <NopLoop>:
584 // 0: 90 nop
585 // 1: 90 nop
586 // 2: 90 nop
587 // 3: 90 nop
588 // 4: 90 nop
589 // 5: 90 nop
590 // 6: 90 nop
591 // 7: 90 nop
592 // 8: 0f a2 cpuid
593 // a: eb f4 jmp 0 <NopLoop>
594 //
595 *(UINT16 *)(ReservedBuffAddress + PAGE_SIZE - 4) = 0xa20f;
596 *(UINT16 *)(ReservedBuffAddress + PAGE_SIZE - 2) = 0xf4eb;
597
598 KeUnstackDetachProcess(&State);
599
600 ObDereferenceObject(SourceProcess);
601 }
602 __except (EXCEPTION_EXECUTE_HANDLER)
603 {
604 KeUnstackDetachProcess(&State);
605
606 return FALSE;
607 }
608
609 return TRUE;
610}
unsigned short UINT16
Definition BasicTypes.h:47
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
#define PAGE_SIZE
Size of each page (4096 bytes)
Definition common.h:69

◆ 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
787{
788 UNREFERENCED_PARAMETER(AttachRequest);
789 UNREFERENCED_PARAMETER(ProcessDebuggingToken);
790
791 //
792 // Enable the memory access logging
793 //
795
796 return TRUE;
797}
BOOLEAN ConfigureInitializeExecTrapOnAllProcessors()
routines for initializing user-mode, kernel-mode exec trap
Definition Configuration.c:37

◆ AttachingCheckPageFaultsWithUserDebugger()

BOOLEAN AttachingCheckPageFaultsWithUserDebugger ( UINT32 CoreId,
UINT64 Address,
UINT32 PageFaultErrorCode )

Check page-faults with user-debugger.

Parameters
CoreId
Address
PageFaultErrorCode
Returns
BOOLEAN if TRUE show that the page-fault injection should be ignored
624{
625 UNREFERENCED_PARAMETER(Address);
626 UNREFERENCED_PARAMETER(PageFaultErrorCode);
627
628 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
629 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
630
631 //
632 // Check whether user-debugger is initialized or not
633 //
635 {
636 return FALSE;
637 }
638
639 //
640 // Check if thread is in user-mode
641 //
642 if (VmFuncGetLastVmexitRip(CoreId) & 0xf000000000000000)
643 {
644 //
645 // We won't intercept threads in kernel-mode
646 //
647 return FALSE;
648 }
649
650 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
651
652 if (!ProcessDebuggingDetail)
653 {
654 //
655 // not related to user debugger
656 //
657 return FALSE;
658 }
659
660 //
661 // Check if thread is in intercepting phase
662 //
663 if (ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
664 {
665 //
666 // Handling state through the user-mode debugger
667 //
670 NULL);
671
672 //
673 // related to user debugger
674 //
676
677 return TRUE;
678 }
679
680 //
681 // this thread is not in intercepting phase
682 //
683 return FALSE;
684}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId)
Find user-mode debugging details for threads by process Id.
Definition Attaching.c:187
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED
Definition Connection.h:42
UINT64 VmFuncGetLastVmexitRip(UINT32 CoreId)
get the last vm-exit RIP
Definition Export.c:318
VOID VmFuncSuppressRipIncrement(UINT32 CoreId)
Suppress the incrementation of RIP.
Definition Export.c:34
UINT64 Address
Definition HyperDbgScriptImports.h:67
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
BOOLEAN UdCheckAndHandleBreakpointsAndDebugBreaks(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle #DBs and #BPs for kernel debugger.
Definition Ud.c:443
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
BOOLEAN g_UserDebuggerState
shows whether the user debugger is enabled or disabled
Definition Global.h:109
Saves the debugger state.
Definition State.h:165
Description of each active thread in user-mode attaching mechanism.
Definition Attaching.h:49
BOOLEAN IsOnThreadInterceptingPhase
Definition Attaching.h:64

◆ AttachingCheckUnhandledEptViolation()

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

handling unhandled EPT violations

Parameters
CoreId
ViolationQualification
GuestPhysicalAddr
Returns
BOOLEAN
1105{
1106 UNREFERENCED_PARAMETER(CoreId);
1107 UNREFERENCED_PARAMETER(ViolationQualification);
1108 UNREFERENCED_PARAMETER(GuestPhysicalAddr);
1109
1110 //
1111 // Not handled here
1112 //
1113 return FALSE;
1114}

◆ 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
696{
697 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
698
699 //
700 // Get the current process debugging detail
701 //
702 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByToken(ProcessDebuggingToken);
703
704 if (!ProcessDebuggingDetail)
705 {
706 return FALSE;
707 }
708
709 //
710 // If the thread is already in intercepting phase, we should return,
711 //
712 if (Enable && ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
713 {
714 LogError("Err, thread is already in intercepting phase");
715 return FALSE;
716 }
717
718 //
719 // if the user want to disable the intercepting phase, we just ignore the
720 // request without a message
721 //
722 if (!Enable && !ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
723 {
724 return FALSE;
725 }
726
727 //
728 // We're or we're not in thread intercepting phase now
729 //
730 ProcessDebuggingDetail->IsOnThreadInterceptingPhase = Enable;
731
732 if (Enable)
733 {
734 //
735 // Intercept all mov 2 cr3s
736 //
738 }
739 else
740 {
741 //
742 // Removing the mov to cr3 vm-exits
743 //
745 }
746
747 //
748 // Set the supervisor bit to 1 when we want to continue all the threads
749 //
750 if (!Enable)
751 {
752 for (size_t i = 0; i < MAX_CR3_IN_A_PROCESS; i++)
753 {
754 if (ProcessDebuggingDetail->InterceptedCr3[i].Flags != (UINT64)NULL)
755 {
756 //
757 // This cr3 should not be intercepted on threads' user mode execution
758 //
760 TRUE,
762 ProcessDebuggingDetail->InterceptedCr3[i]))
763 {
764 return FALSE;
765 }
766 }
767 }
768 }
769
770 return TRUE;
771}
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByToken(UINT64 Token)
Find user-mode debugging details for threads by token.
Definition Attaching.c:164
#define MAX_CR3_IN_A_PROCESS
Maximum number of CR3 registers that a process can have.
Definition Attaching.h:37
unsigned __int64 UINT64
Definition BasicTypes.h:21
@ PagingLevelPageMapLevel4
Definition DataTypes.h:28
VOID DebuggerEventDisableMovToCr3ExitingOnAllProcessors()
routines for debugging threads (disable mov-to-cr3 exiting)
Definition DebuggerEvents.c:53
VOID DebuggerEventEnableMovToCr3ExitingOnAllProcessors()
routines for debugging threads (enable mov-to-cr3 exiting)
Definition DebuggerEvents.c:42
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
_Use_decl_annotations_ BOOLEAN MemoryMapperSetSupervisorBitWithoutSwitchingByCr3(PVOID Va, BOOLEAN Set, PAGING_LEVEL Level, CR3_TYPE TargetCr3)
This function the Supervisor bit of the target PTE based on the specific cr3.
Definition MemoryMapper.c:1697
UINT64 Flags
Definition BasicTypes.h:133
CR3_TYPE InterceptedCr3[MAX_CR3_IN_A_PROCESS]
Definition Attaching.h:66

◆ AttachingCreateProcessDebuggingDetails()

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

Create user-mode debugging details for threads.

Parameters
ProcessId
Is32Bit
Eprocess
PebAddressToMonitor
UsermodeReservedBuffer
Returns
UINT64 returns the unique token
107{
108 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
109
110 //
111 // Allocate the buffer
112 //
113 ProcessDebuggingDetail = (USERMODE_DEBUGGING_PROCESS_DETAILS *)
115
116 if (!ProcessDebuggingDetail)
117 {
118 return (UINT64)NULL;
119 }
120
121 //
122 // Set the unique tag and increment it
123 //
124 ProcessDebuggingDetail->Token = g_SeedOfUserDebuggingDetails++;
125
126 //
127 // Set the details of the created buffer
128 //
129 ProcessDebuggingDetail->ProcessId = ProcessId;
130 ProcessDebuggingDetail->Enabled = Enabled;
131 ProcessDebuggingDetail->Is32Bit = Is32Bit;
132 ProcessDebuggingDetail->CheckCallBackForInterceptingFirstInstruction = CheckCallbackAtFirstInstruction;
133 ProcessDebuggingDetail->Eprocess = Eprocess;
134 ProcessDebuggingDetail->PebAddressToMonitor = (PVOID)PebAddressToMonitor;
135 ProcessDebuggingDetail->UsermodeReservedBuffer = UsermodeReservedBuffer;
136
137 //
138 // Allocate a thread holder buffer for this process
139 //
141 {
142 PlatformMemFreePool(ProcessDebuggingDetail);
143 return (UINT64)NULL;
144 }
145
146 //
147 // Attach it to the list of active thread (LIST_ENTRY)
148 //
150
151 //
152 // return the token
153 //
154 return ProcessDebuggingDetail->Token;
155}
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (zeroed)
Definition Mem.c:69
BOOLEAN ThreadHolderAssignThreadHolderToProcessDebuggingDetails(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Assign a thread holder to process debugging details.
Definition ThreadHolder.c:42
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ PLIST_ENTRY Entry)
Definition Windows.h:115
LIST_ENTRY g_ProcessDebuggingDetailsListHead
List header of thread debugging details.
Definition Global.h:152
UINT64 g_SeedOfUserDebuggingDetails
Seed for tokens of unique details buffer for threads.
Definition Global.h:139
NULL()
Definition test-case-generator.py:530
UINT64 Token
Definition Attaching.h:50
BOOLEAN CheckCallBackForInterceptingFirstInstruction
Definition Attaching.h:65
BOOLEAN Is32Bit
Definition Attaching.h:62
UINT64 UsermodeReservedBuffer
Definition Attaching.h:57
BOOLEAN Enabled
Definition Attaching.h:51
UINT32 ProcessId
Definition Attaching.h:61
PVOID PebAddressToMonitor
Definition Attaching.h:52
PEPROCESS Eprocess
Definition Attaching.h:60
LIST_ENTRY AttachedProcessList
Definition Attaching.h:56

◆ 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
188{
190 {
191 //
192 // Check if we found the target thread and if it's enabled
193 //
194 if (ProcessDebuggingDetails->ProcessId == ProcessId && ProcessDebuggingDetails->Enabled)
195 {
196 return ProcessDebuggingDetails;
197 }
198 }
199
200 return NULL;
201}
#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
165{
167 {
168 //
169 // Check if we found the target thread and if it's enabled
170 //
171 if (ProcessDebuggingDetails->Token == Token && ProcessDebuggingDetails->Enabled)
172 {
173 return ProcessDebuggingDetails;
174 }
175 }
176
177 return NULL;
178}

◆ 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
211{
213 {
214 if (ProcessDebuggingDetails->IsOnTheStartingPhase)
215 {
216 return ProcessDebuggingDetails;
217 }
218 }
219
220 return NULL;
221}

◆ AttachingHandleCr3VmexitsForThreadInterception()

BOOLEAN AttachingHandleCr3VmexitsForThreadInterception ( UINT32 CoreId,
CR3_TYPE NewCr3 )

Handle the cr3 vm-exits for thread interception.

this function should be called in vmx-root

Parameters
CoreId
NewCr3
Returns
BOOLEAN
1037{
1038 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1039
1040 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(HANDLE_TO_UINT32(PsGetCurrentProcessId()));
1041
1042 //
1043 // Check if process is valid or if thread is in intercepting phase
1044 //
1045 if (!ProcessDebuggingDetail || !ProcessDebuggingDetail->IsOnThreadInterceptingPhase)
1046 {
1047 //
1048 // not related to user debugger
1049 //
1051 return FALSE;
1052 }
1053
1054 //
1055 // Save the cr3 for future continuing the thread
1056 //
1057 for (size_t i = 0; i < MAX_CR3_IN_A_PROCESS; i++)
1058 {
1059 if (ProcessDebuggingDetail->InterceptedCr3[i].Flags == NewCr3.Flags)
1060 {
1061 //
1062 // We found it saved previously, no need any further action
1063 //
1064 break;
1065 }
1066
1067 if (ProcessDebuggingDetail->InterceptedCr3[i].Flags == (UINT64)NULL)
1068 {
1069 //
1070 // Save the cr3
1071 //
1072 ProcessDebuggingDetail->InterceptedCr3[i].Flags = NewCr3.Flags;
1073 break;
1074 }
1075 }
1076
1077 //
1078 // This thread should be intercepted
1079 //
1081 {
1082 return FALSE;
1083 }
1084
1085 //
1086 // Intercept #PFs
1087 //
1089
1090 return TRUE;
1091}
VOID VmFuncSetExceptionBitmap(UINT32 CoreId, UINT32 IdtIndex)
Set exception bitmap in VMCS.
Definition Export.c:253
VOID VmFuncUnsetExceptionBitmap(UINT32 CoreId, UINT32 IdtIndex)
Unset exception bitmap in VMCS.
Definition Export.c:267
@ EXCEPTION_VECTOR_PAGE_FAULT
Definition Events.h:38

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

◆ 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
Definition casting.cpp:25

◆ 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
1211{
1212 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1213 BOOLEAN WasKilled = FALSE;
1214
1215 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(KillRequest->ProcessId);
1216
1217 //
1218 // Check if process is valid in process debugging details
1219 //
1220 if (!ProcessDebuggingDetail)
1221 {
1222 //
1223 // not found
1224 //
1226 return FALSE;
1227 }
1228
1229 //
1230 // Check if process exists or not
1231 //
1232 if (!CommonIsProcessExist(ProcessDebuggingDetail->ProcessId))
1233 {
1234 //
1235 // Process was killed before killing it here (not exists)
1236 //
1237
1238 //
1239 // Remove the entry from the process debugging details list
1240 //
1242
1244 return FALSE;
1245 }
1246
1247 //
1248 // Check if we can kill it using the first method
1249 //
1250 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_1);
1251
1252 if (WasKilled)
1253 {
1254 goto Success;
1255 }
1256
1257 //
1258 // Check if we can kill it using the second method
1259 //
1260 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_2);
1261
1262 if (WasKilled)
1263 {
1264 goto Success;
1265 }
1266
1267 //
1268 // Check if we can kill it using the third method
1269 //
1270 WasKilled = CommonKillProcess(KillRequest->ProcessId, PROCESS_KILL_METHOD_3);
1271
1272 if (WasKilled)
1273 {
1274 goto Success;
1275 }
1276
1277 //
1278 // No way we can kill the shit :(
1279 //
1281 return FALSE;
1282
1283Success:
1284
1285 //
1286 // Remove the entry from the process debugging details list
1287 //
1289
1291 return TRUE;
1292}
BOOLEAN AttachingRemoveProcessDebuggingDetailsByToken(UINT64 Token)
Remove user-mode debugging details for threads by its token.
Definition Attaching.c:257
UCHAR BOOLEAN
Definition BasicTypes.h:39
#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
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
_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:633
UINT64 Result
Definition RequestStructures.h:641

◆ 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
1186{
1188 {
1189 //
1190 // The pausing operation was successful
1191 //
1193 return TRUE;
1194 }
1195 else
1196 {
1198 return FALSE;
1199 }
1200}
BOOLEAN AttachingConfigureInterceptingThreads(UINT64 ProcessDebuggingToken, BOOLEAN Enable)
Enable or disable the thread intercepting phase.
Definition Attaching.c:695
#define DEBUGGER_ERROR_UNABLE_TO_PAUSE_THE_PROCESS_THREADS
error, unable to pause the process's threads
Definition ErrorCodes.h:338
UINT64 Token
Definition RequestStructures.h:640

◆ 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
809{
810 PEPROCESS SourceProcess;
811 UINT64 ProcessDebuggingToken;
812 UINT64 PebAddressToMonitor;
813 UINT64 UsermodeReservedBuffer;
814 BOOLEAN ResultOfApplyingEvent;
815 BOOLEAN Is32Bit;
816 PUSERMODE_DEBUGGING_PROCESS_DETAILS TempProcessDebuggingDetail;
818
819 if (g_PsGetProcessWow64Process == NULL || g_PsGetProcessPeb == NULL)
820 {
822 return FALSE;
823 }
824
825 if (PsLookupProcessByProcessId((HANDLE)AttachRequest->ProcessId, &SourceProcess) != STATUS_SUCCESS)
826 {
827 //
828 // if the process not found
829 //
831 return FALSE;
832 }
833
834 ObDereferenceObject(SourceProcess);
835
836 //
837 // Check to avoid double attaching to a process
838 //
839 TempProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(AttachRequest->ProcessId);
840
841 if (TempProcessDebuggingDetail != NULL && TempProcessDebuggingDetail->Eprocess == SourceProcess)
842 {
843 //
844 // The user already attached to this process
845 //
847 return FALSE;
848 }
849
850 //
851 // check whether the target process is 32-bit or 64-bit
852 //
853 if (!UserAccessIsWow64Process((HANDLE)AttachRequest->ProcessId, &Is32Bit))
854 {
855 //
856 // Unable to detect whether it's 32-bit or 64-bit
857 //
859 return FALSE;
860 }
861
862 //
863 // Set the Is32Bit flag of attach request
864 //
865 AttachRequest->Is32Bit = Is32Bit;
866
867 //
868 // Get 32-bit or 64-bit PEB
869 //
870 if (Is32Bit)
871 {
872 PebAddressToMonitor = (UINT64)((PPEB32)g_PsGetProcessWow64Process(SourceProcess));
873 }
874 else
875 {
876 PebAddressToMonitor = (UINT64)((PPEB)g_PsGetProcessPeb(SourceProcess));
877 }
878
879 if (PebAddressToMonitor == (UINT64)NULL)
880 {
882 return FALSE;
883 }
884
885 //
886 // allocate memory in the target user-mode process
887 //
888 UsermodeReservedBuffer = MemoryMapperReserveUsermodeAddressOnTargetProcess(AttachRequest->ProcessId, TRUE);
889
890 if (UsermodeReservedBuffer == (UINT64)NULL)
891 {
893 return FALSE;
894 }
895
896 //
897 // Adjust the nop sled buffer
898 //
899 if (!AttachingAdjustNopSledBuffer(UsermodeReservedBuffer,
900 AttachRequest->ProcessId))
901 {
903 return FALSE;
904 }
905
906 //
907 // Log for test
908 //
909 // LogInfo("Reserved address on the target process: %llx\n", UsermodeReservedBuffer);
910
911 //
912 // Create the debugging detail for process
913 //
914 ProcessDebuggingToken = AttachingCreateProcessDebuggingDetails(AttachRequest->ProcessId,
915 TRUE,
916 Is32Bit,
917 AttachRequest->CheckCallbackAtFirstInstruction,
918 SourceProcess,
919 PebAddressToMonitor,
920 UsermodeReservedBuffer);
921
922 //
923 // Check if we successfully get the token
924 //
925 if (ProcessDebuggingToken == (UINT64)NULL)
926 {
928 return FALSE;
929 }
930
931 //
932 // Check if it's attaching at entrypoint or attaching to a previously running process
933 //
934 if (IsAttachingToEntrypoint)
935 {
936 //
937 // *** attaching to the entrypoint of the process ***
938 //
939
940 //
941 // Check whether any special initialization for thread safe features
942 // is needed or not
943 //
944 if (AttachRequest->CheckCallbackAtFirstInstruction)
945 {
946 AttachingCheckForSafeCallbackRequestedInitializations(AttachRequest, ProcessDebuggingToken);
947 }
948
949 //
950 // Waiting for #DB to be triggered
951 //
953
954 //
955 // Set the starting point of the thread
956 //
958 {
959 //
960 // Remove the created thread debugging detail
961 //
963
966 return FALSE;
967 }
968
969 //
970 // Apply monitor memory range to the PEB address
971 //
972
973 EptHookDetails.StartAddress = PebAddressToMonitor;
974
975 //
976 // both start and the end are at the same address
977 // because it hooks an entire page anyway
978 //
979 EptHookDetails.EndAddress = PebAddressToMonitor;
980 EptHookDetails.SetHookForRead = TRUE;
981 EptHookDetails.SetHookForWrite = TRUE;
982 EptHookDetails.SetHookForExec = FALSE;
983
984 ResultOfApplyingEvent = DebuggerEventEnableMonitorReadWriteExec(
985 &EptHookDetails,
986 AttachRequest->ProcessId,
987 FALSE // Applied from VMX non-root mode
988 );
989
990 if (!ResultOfApplyingEvent)
991 {
992 //
993 // Remove the created thread debugging detail
994 //
996
999 return FALSE;
1000 }
1001 }
1002 else
1003 {
1004 //
1005 // *** attaching to previously running process ***
1006 //
1007 if (!AttachingConfigureInterceptingThreads(ProcessDebuggingToken, TRUE))
1008 {
1009 //
1010 // Remove the created thread debugging details
1011 //
1012 AttachingRemoveProcessDebuggingDetailsByToken(ProcessDebuggingToken);
1013
1015 return FALSE;
1016 }
1017 }
1018
1019 //
1020 // Operation was successful
1021 //
1022 AttachRequest->Token = ProcessDebuggingToken;
1024 return TRUE;
1025}
BOOLEAN AttachingSetStartingPhaseOfProcessDebuggingDetailsByToken(BOOLEAN Set, UINT64 Token)
Set the start up phase of a debugging thread buffer by its token.
Definition Attaching.c:300
UINT64 AttachingCreateProcessDebuggingDetails(UINT32 ProcessId, BOOLEAN Enabled, BOOLEAN Is32Bit, BOOLEAN CheckCallbackAtFirstInstruction, PEPROCESS Eprocess, UINT64 PebAddressToMonitor, UINT64 UsermodeReservedBuffer)
Create user-mode debugging details for threads.
Definition Attaching.c:100
BOOLEAN AttachingAdjustNopSledBuffer(UINT64 ReservedBuffAddress, UINT32 ProcessId)
Allocate a nop-sled buffer.
Definition Attaching.c:557
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:785
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
#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
_Use_decl_annotations_ UINT64 MemoryMapperReserveUsermodeAddressOnTargetProcess(UINT32 ProcessId, BOOLEAN Allocate)
Reserve user mode address (not allocated) in the target user mode application.
Definition MemoryMapper.c:1457
BOOLEAN UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit.
Definition UserAccess.c:753
BOOLEAN CheckCallbackAtFirstInstruction
Definition RequestStructures.h:635
BOOLEAN Is32Bit
Definition RequestStructures.h:636
Setting details for EPT Hooks (!monitor)
Definition DataTypes.h:331
UINT64 StartAddress
Definition DataTypes.h:332
BOOLEAN SetHookForRead
Definition DataTypes.h:334
BOOLEAN SetHookForWrite
Definition DataTypes.h:335
UINT64 EndAddress
Definition DataTypes.h:333
BOOLEAN SetHookForExec
Definition DataTypes.h:336
PEB 32-bit.
Definition UserAccess.h:82
PEB 64-bit.
Definition UserAccess.h:55

◆ 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
1303{
1304 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1305
1306 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(DetachRequest->ProcessId);
1307
1308 //
1309 // Check if process is valid in process debugging details
1310 //
1311 if (!ProcessDebuggingDetail)
1312 {
1313 //
1314 // not found
1315 //
1317 return FALSE;
1318 }
1319
1320 //
1321 // If the threads are paused, we can't detach from the target process
1322 // before sending this request, the debugger should continued all the
1323 // threads by sending a continue packet
1324 //
1325 if (ThreadHolderIsAnyPausedThreadInProcess(ProcessDebuggingDetail))
1326 {
1327 //
1328 // We found a thread that is still pause
1329 //
1331 return FALSE;
1332 }
1333
1334 //
1335 // Free the reserved memory in the target process
1336 //
1338 (PVOID)ProcessDebuggingDetail->UsermodeReservedBuffer))
1339 {
1340 //
1341 // Still, we continue, no need to abort the operation
1342 //
1343 LogError("Err, cannot deallocate reserved buffer in the detached process");
1344 }
1345
1346 //
1347 // Remove the entry from the process debugging details list
1348 //
1350
1352 return TRUE;
1353}
#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
_Use_decl_annotations_ BOOLEAN MemoryMapperFreeMemoryOnTargetProcess(UINT32 ProcessId, PVOID BaseAddress)
Deallocates a previously reserved user mode address in the target user mode application.
Definition MemoryMapper.c:1537
BOOLEAN ThreadHolderIsAnyPausedThreadInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Check if there is any thread paused by checking process debugging details.
Definition ThreadHolder.c:77

◆ AttachingQueryCountOfActiveDebuggingThreadsAndProcesses()

BOOLEAN AttachingQueryCountOfActiveDebuggingThreadsAndProcesses ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfDebugThreadsRequest)

Query count of active debugging threads.

Parameters
QueryCountOfDebugThreadsRequest
Returns
BOOLEAN
1451{
1452 UINT32 CountOfProcessesAndThreads;
1453
1454 //
1455 // Count the result
1456 //
1458
1459 //
1460 // Set the results
1461 //
1462 QueryCountOfDebugThreadsRequest->CountOfActiveDebuggingThreadsAndProcesses = CountOfProcessesAndThreads;
1463 QueryCountOfDebugThreadsRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
1464
1465 return TRUE;
1466}
unsigned int UINT32
Definition BasicTypes.h:48
UINT32 ThreadHolderQueryCountOfActiveDebuggingThreadsAndProcesses()
Query count of active debugging threads and processes.
Definition ThreadHolder.c:491
UINT32 CountOfActiveDebuggingThreadsAndProcesses
Definition RequestStructures.h:639

◆ AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses()

BOOLEAN AttachingQueryDetailsOfActiveDebuggingThreadsAndProcesses ( PVOID BufferToStoreDetails,
UINT32 BufferSize )

Query details of active debugging threads.

Parameters
BufferToStoreDetails
BufferSize
Returns
BOOLEAN
1477{
1478 UINT32 CountOfProcessesAndThreadsToStore;
1479
1480 CountOfProcessesAndThreadsToStore = BufferSize / SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS;
1481
1482 if (CountOfProcessesAndThreadsToStore == 0)
1483 {
1484 //
1485 // No active thread or process
1486 //
1487 return FALSE;
1488 }
1489
1490 // LogInfo("Count of active process and threads : %x", CountOfProcessesAndThreadsToStore);
1491
1492 //
1493 // Get the results
1494 //
1495 ThreadHolderQueryDetailsOfActiveDebuggingThreadsAndProcesses(BufferToStoreDetails, CountOfProcessesAndThreadsToStore);
1496
1497 return TRUE;
1498}
#define SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS
Definition RequestStructures.h:806
VOID ThreadHolderQueryDetailsOfActiveDebuggingThreadsAndProcesses(USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS *BufferToStoreDetails, UINT32 MaxCount)
Query details of active debugging threads and processes.
Definition ThreadHolder.c:549

◆ 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
350{
351 DEBUGGEE_BP_PACKET BpRequest = {0};
352
353 //
354 // Double check to make sure the main module is loaded
355 //
356 if (!CheckAccessValidityAndSafety(ProcessDebuggingDetail->EntrypointOfMainModule, sizeof(CHAR)))
357 {
358 LogError("Err, the main module is not loaded or the main entrypoint is not valid");
359 return FALSE;
360 }
361
362 //
363 // Setting a breakpoint to the main entrypoint of the module
364 //
365 BpRequest.Address = ProcessDebuggingDetail->EntrypointOfMainModule;
369
370 //
371 // Remove the breakpoint after hit
372 //
373 BpRequest.RemoveAfterHit = TRUE;
374
375 //
376 // Check if the process needs to check for callbacks for the very first instruction
377 //
378 if (ProcessDebuggingDetail->CheckCallBackForInterceptingFirstInstruction)
379 {
380 //
381 // This breakpoint should check for callbacks
382 //
383 BpRequest.CheckForCallbacks = TRUE;
384 }
385
386 //
387 // Register the breakpoint
388 //
389 if (!BreakpointAddNew(&BpRequest))
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
413 {
414 //
415 // Handling state through the user-mode debugger
416 //
419 NULL);
420 }
421
422 //
423 // Handled successfully
424 //
425 return TRUE;
426}
BOOLEAN BreakpointAddNew(PDEBUGGEE_BP_PACKET BpDescriptorArg)
Add new breakpoints.
Definition BreakpointCommands.c:893
@ 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:653
#define DEBUGGEE_BP_APPLY_TO_ALL_THREADS
The constant to apply to all threads for bp command.
Definition Constants.h:659
#define DEBUGGEE_BP_APPLY_TO_ALL_CORES
The constant to apply to all cores for bp command.
Definition Constants.h:647
_Use_decl_annotations_ VOID KdHandleBreakpointAndDebugBreakpoints(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle #DBs and #BPs for kernel debugger.
Definition Kd.c:1214
BOOLEAN g_KernelDebuggerState
shows whether the kernel debugger is enabled or disabled
Definition Global.h:103
The structure of bp command packet in HyperDbg.
Definition RequestStructures.h:1060
UINT32 Tid
Definition RequestStructures.h:1063
BOOLEAN RemoveAfterHit
Definition RequestStructures.h:1065
UINT32 Core
Definition RequestStructures.h:1064
BOOLEAN CheckForCallbacks
Definition RequestStructures.h:1066
UINT64 Address
Definition RequestStructures.h:1061
UINT32 Pid
Definition RequestStructures.h:1062

◆ AttachingRemoveAndFreeAllProcessDebuggingDetails()

VOID AttachingRemoveAndFreeAllProcessDebuggingDetails ( )

Remove and deallocate all thread debuggig details.

Returns
VOID
230{
232 {
233 //
234 // Free the thread holding structure(s)
235 //
236 ThreadHolderFreeHoldingStructures(ProcessDebuggingDetails);
237
238 //
239 // Remove thread debugging detail from the list active threads
240 //
241 RemoveEntryList(&ProcessDebuggingDetails->AttachedProcessList);
242
243 //
244 // Unallocate the pool
245 //
246 PlatformMemFreePool(ProcessDebuggingDetails);
247 }
248}
VOID ThreadHolderFreeHoldingStructures(PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail)
Free all of thread holder structures.
Definition ThreadHolder.c:465
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition Windows.h:56

◆ 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
1125{
1126 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetails;
1127
1128 //
1129 // Get the thread debugging detail
1130 //
1131 ProcessDebuggingDetails = AttachingFindProcessDebuggingDetailsByToken(AttachRequest->Token);
1132
1133 //
1134 // Check if token is valid or not
1135 //
1136 if (!ProcessDebuggingDetails)
1137 {
1139 return FALSE;
1140 }
1141
1142 //
1143 // Check if the entrypoint is reached or not,
1144 // if it's not reached then we won't remove the hooks
1145 //
1147 {
1148 //
1149 // The entrypoint is called, we should remove the hook
1150 //
1151 if (!ConfigureEptHookUnHookSingleAddress((UINT64)ProcessDebuggingDetails->PebAddressToMonitor,
1152 (UINT64)NULL,
1153 ProcessDebuggingDetails->ProcessId))
1154 {
1156 return FALSE;
1157 }
1158 else
1159 {
1160 //
1161 // The unhooking operation was successful
1162 //
1164 return TRUE;
1165 }
1166 }
1167 else
1168 {
1169 //
1170 // The entrypoint is not called, we shouldn't remove the hook
1171 //
1173 return FALSE;
1174 }
1175}
BOOLEAN ConfigureEptHookUnHookSingleAddress(UINT64 VirtualAddress, UINT64 PhysAddress, UINT32 ProcessId)
Remove single hook from the hooked pages list and invalidate TLB.
Definition Configuration.c:188
#define DEBUGGER_ERROR_UNABLE_TO_REMOVE_HOOKS
error, could not remove the previous hook
Definition ErrorCodes.h:308
#define DEBUGGER_ERROR_INVALID_THREAD_DEBUGGING_TOKEN
error, invalid thread debugging token
Definition ErrorCodes.h:332
#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

◆ AttachingRemoveProcessDebuggingDetailsByToken()

BOOLEAN AttachingRemoveProcessDebuggingDetailsByToken ( UINT64 Token)

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

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

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

◆ AttachingSwitchProcess()

BOOLEAN AttachingSwitchProcess ( PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest)

Switch to the target thread.

Parameters
SwitchRequest
Returns
BOOLEAN
1363{
1364 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
1365 PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadDebuggingDetail;
1366
1367 if (SwitchRequest->ProcessId != NULL_ZERO)
1368 {
1369 //
1370 // Switch by process id
1371 //
1372 ProcessDebuggingDetail = AttachingFindProcessDebuggingDetailsByProcessId(SwitchRequest->ProcessId);
1373 }
1374 else if (SwitchRequest->ThreadId != NULL_ZERO)
1375 {
1376 //
1377 // Switch by thread id
1378 //
1379 ProcessDebuggingDetail = ThreadHolderGetProcessDebuggingDetailsByThreadId(SwitchRequest->ThreadId);
1380 }
1381 else
1382 {
1384 return FALSE;
1385 }
1386
1387 //
1388 // Check if process is valid in process debugging details
1389 //
1390 if (!ProcessDebuggingDetail)
1391 {
1392 //
1393 // not found
1394 //
1396 return FALSE;
1397 }
1398
1399 //
1400 // Set the IsPaused field
1401 //
1402 if (SwitchRequest->ThreadId != NULL_ZERO)
1403 {
1404 //
1405 // Find the thread's state
1406 //
1407 ThreadDebuggingDetail = ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(ProcessDebuggingDetail->ProcessId,
1408 SwitchRequest->ThreadId);
1409 }
1410 else
1411 {
1412 //
1413 // Find the first thread in the process
1414 //
1415 ThreadDebuggingDetail = ThreadHolderGetProcessFirstThreadDetailsByProcessId(ProcessDebuggingDetail->ProcessId);
1416 }
1417
1418 //
1419 // Check if we find the target thread
1420 //
1421 if (!ThreadDebuggingDetail)
1422 {
1423 //
1424 // not found
1425 //
1427 return FALSE;
1428 }
1429
1430 //
1431 // Fill the needed details by user mode
1432 //
1433 SwitchRequest->Token = ProcessDebuggingDetail->Token;
1434 SwitchRequest->ProcessId = ProcessDebuggingDetail->ProcessId;
1435 SwitchRequest->ThreadId = ThreadDebuggingDetail->ThreadId;
1436 SwitchRequest->Is32Bit = ProcessDebuggingDetail->Is32Bit;
1437 SwitchRequest->IsPaused = ThreadDebuggingDetail->IsPaused;
1438
1440 return TRUE;
1441}
#define NULL_ZERO
Definition BasicTypes.h:51
#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
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(UINT32 ProcessId, UINT32 ThreadId)
Find the active threads of the process from process id.
Definition ThreadHolder.c:109
PUSERMODE_DEBUGGING_THREAD_DETAILS ThreadHolderGetProcessFirstThreadDetailsByProcessId(UINT32 ProcessId)
Find the first active threads of the process from process id.
Definition ThreadHolder.c:157
PUSERMODE_DEBUGGING_PROCESS_DETAILS ThreadHolderGetProcessDebuggingDetailsByThreadId(UINT32 ThreadId)
Find the active process debugging detail from the thread id.
Definition ThreadHolder.c:205
BOOLEAN IsPaused
Definition RequestStructures.h:637
UINT32 ThreadId
Definition RequestStructures.h:634
Details of each thread in process.
Definition ThreadHolder.h:33
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
1509{
1510 //
1511 // As we're here, we need to initialize the user-mode debugger
1512 //
1514
1515 switch (Request->Action)
1516 {
1518
1520
1521 break;
1522
1524
1525 AttachingPerformDetach(Request);
1526
1527 break;
1528
1530
1531 AttachingRemoveHooks(Request);
1532
1533 break;
1534
1536
1537 AttachingKillProcess(Request);
1538
1539 break;
1540
1542
1543 AttachingPauseProcess(Request);
1544
1545 break;
1546
1548
1549 AttachingSwitchProcess(Request);
1550
1551 break;
1552
1554
1556
1557 break;
1558
1559 default:
1560
1562
1563 break;
1564 }
1565}
BOOLEAN AttachingSwitchProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest)
Switch to the target thread.
Definition Attaching.c:1362
BOOLEAN AttachingPerformDetach(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS DetachRequest)
Clearing hooks after resuming the process.
Definition Attaching.c:1302
BOOLEAN AttachingPerformAttachToProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest, BOOLEAN IsAttachingToEntrypoint)
Attach to the target process.
Definition Attaching.c:808
BOOLEAN AttachingPauseProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS PauseRequest)
Pauses the target process.
Definition Attaching.c:1185
BOOLEAN AttachingQueryCountOfActiveDebuggingThreadsAndProcesses(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfDebugThreadsRequest)
Query count of active debugging threads.
Definition Attaching.c:1450
BOOLEAN AttachingRemoveHooks(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS AttachRequest)
Clearing hooks after resuming the process.
Definition Attaching.c:1124
BOOLEAN AttachingKillProcess(PDEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS KillRequest)
Kill the target process from kernel-mode.
Definition Attaching.c:1210
#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:617
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_QUERY_COUNT_OF_ACTIVE_DEBUGGING_THREADS
Definition RequestStructures.h:622
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_KILL_PROCESS
Definition RequestStructures.h:619
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_SWITCH_BY_PROCESS_OR_THREAD
Definition RequestStructures.h:621
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_PAUSE_PROCESS
Definition RequestStructures.h:620
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_ATTACH
Definition RequestStructures.h:616
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_REMOVE_HOOKS
Definition RequestStructures.h:618
BOOLEAN UdInitializeUserDebugger()
initialize user debugger
Definition Ud.c:21
DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_TYPE Action
Definition RequestStructures.h:638
BOOLEAN IsStartingNewProcess
Definition RequestStructures.h:632