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

headers for user-mode debugging routines More...

Go to the source code of this file.

Classes

struct  _ACTIVE_DEBUGGING_PROCESS
 structures related to current thread debugging state More...
 

Macros

#define DbgWaitForUserResponse(UserSyncObjectId)
 
#define DbgReceivedUserResponse(UserSyncObjectId)
 

Typedefs

typedef struct _ACTIVE_DEBUGGING_PROCESS ACTIVE_DEBUGGING_PROCESS
 structures related to current thread debugging state
 
typedef struct _ACTIVE_DEBUGGING_PROCESSPACTIVE_DEBUGGING_PROCESS
 

Functions

VOID UdInitializeUserDebugger ()
 initialize user debugger
 
VOID UdUninitializeUserDebugger ()
 uninitialize user debugger
 
VOID UdRemoveActiveDebuggingProcess (BOOLEAN DontSwitchToNewProcess)
 Remove the current active debugging process (thread)
 
VOID UdHandleUserDebuggerPausing (PDEBUGGEE_UD_PAUSED_PACKET PausePacket)
 Handle pause packets from user debugger.
 
VOID UdContinueDebuggee (UINT64 ProcessDetailToken)
 Continue the target user debugger.
 
VOID UdSendStepPacketToDebuggee (UINT64 ThreadDetailToken, UINT32 TargetThreadId, DEBUGGER_REMOTE_STEPPING_REQUEST StepType)
 Send stepping instructions packet to user debugger.
 
VOID UdSetActiveDebuggingProcess (UINT64 DebuggingId, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, BOOLEAN IsPaused)
 set the current active debugging process (thread)
 
BOOLEAN UdSetActiveDebuggingThreadByPidOrTid (UINT32 TargetPidOrTid, BOOLEAN IsTid)
 Set the active debugging thread by process id or thread id.
 
BOOLEAN UdShowListActiveDebuggingProcessesAndThreads ()
 Show list of active debugging processes and threads.
 
BOOL UdListProcessThreads (DWORD OwnerPID)
 List of threads by owner process id.
 
BOOLEAN UdCheckThreadByProcessId (DWORD Pid, DWORD Tid)
 Check if a thread belongs to special process.
 
BOOLEAN UdAttachToProcess (UINT32 TargetPid, const WCHAR *TargetFileAddress, const WCHAR *CommandLine, BOOLEAN RunCallbackAtTheFirstInstruction)
 Attach to target process.
 
BOOLEAN UdKillProcess (UINT32 TargetPid)
 Kill the target process from kernel.
 
BOOLEAN UdDetachProcess (UINT32 TargetPid, UINT64 ProcessDetailToken)
 Detach the target process.
 
BOOLEAN UdPauseProcess (UINT64 ProcessDebuggingToken)
 Pause the target process.
 

Detailed Description

headers for user-mode debugging routines

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

Macro Definition Documentation

◆ DbgReceivedUserResponse

#define DbgReceivedUserResponse ( UserSyncObjectId)
Value:
do \
{ \
DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \
\
SyncronizationObject->IsOnWaitingState = FALSE; \
SetEvent(SyncronizationObject->EventHandle); \
} while (FALSE);
#define FALSE
Definition BasicTypes.h:54
In debugger holds the state of events.
Definition debugger.h:110
HANDLE EventHandle
Definition debugger.h:111
BOOLEAN IsOnWaitingState
Definition debugger.h:112
DEBUGGER_SYNCRONIZATION_EVENTS_STATE g_UserSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS]
In debugger (not debuggee), we save the handle of the user-mode listening thread for pauses here for ...
Definition globals.h:176
28#define DbgReceivedUserResponse(UserSyncObjectId) \
29 do \
30 { \
31 DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \
32 &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \
33 \
34 SyncronizationObject->IsOnWaitingState = FALSE; \
35 SetEvent(SyncronizationObject->EventHandle); \
36 } while (FALSE);

◆ DbgWaitForUserResponse

#define DbgWaitForUserResponse ( UserSyncObjectId)
Value:
do \
{ \
DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \
\
SyncronizationObject->IsOnWaitingState = TRUE; \
WaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \
} while (FALSE);
#define TRUE
Definition BasicTypes.h:55
18#define DbgWaitForUserResponse(UserSyncObjectId) \
19 do \
20 { \
21 DEBUGGER_SYNCRONIZATION_EVENTS_STATE * SyncronizationObject = \
22 &g_UserSyncronizationObjectsHandleTable[UserSyncObjectId]; \
23 \
24 SyncronizationObject->IsOnWaitingState = TRUE; \
25 WaitForSingleObject(SyncronizationObject->EventHandle, INFINITE); \
26 } while (FALSE);

Typedef Documentation

◆ ACTIVE_DEBUGGING_PROCESS

structures related to current thread debugging state

◆ PACTIVE_DEBUGGING_PROCESS

Function Documentation

◆ UdAttachToProcess()

BOOLEAN UdAttachToProcess ( UINT32 TargetPid,
const WCHAR * TargetFileAddress,
const WCHAR * CommandLine,
BOOLEAN RunCallbackAtTheFirstInstruction )

Attach to target process.

this function will not check whether the process id is valid or not

Parameters
TargetPid
TargetFileAddress
CommandLine
RunCallbackAtTheFirstInstruction
Returns
BOOLEAN
353{
354 BOOLEAN Status;
355 ULONG ReturnedLength;
357 PROCESS_INFORMATION ProcInfo = {0};
358
359 //
360 // Check to initialize the user-debugger
361 //
363
364 //
365 // Check if debugger is loaded or not
366 //
368
369 //
370 // Check whether it's starting a new process or not
371 //
372 if (TargetFileAddress == NULL)
373 {
374 AttachRequest.IsStartingNewProcess = FALSE;
375 }
376 else
377 {
378 AttachRequest.IsStartingNewProcess = TRUE;
379 }
380
381 //
382 // Set the state of the debugger for getting the callback at the first instruction
383 //
384 AttachRequest.CheckCallbackAtFirstInstruction = RunCallbackAtTheFirstInstruction;
385
386 //
387 // We wanna attach to a remote process
388 //
390
391 if (AttachRequest.IsStartingNewProcess)
392 {
393 //
394 // Check if file exists or not
395 //
396 if (!IsFileExistW(TargetFileAddress))
397 {
398 ShowMessages("err, unable to start (file not found)\n");
399 return FALSE;
400 }
401
402 //
403 // Start the process in suspended state
404 //
405 UdCreateSuspendedProcess(TargetFileAddress, CommandLine, &ProcInfo);
406
407 //
408 // Set the process id and thread id
409 //
410 AttachRequest.ProcessId = ProcInfo.dwProcessId;
411 AttachRequest.ThreadId = ProcInfo.dwThreadId;
412 }
413 else
414 {
415 //
416 // Set the process id
417 //
418 AttachRequest.ProcessId = TargetPid;
419 }
420
421 //
422 // Send the request to the kernel
423 //
424 Status = DeviceIoControl(
425 g_DeviceHandle, // Handle to device
427 // code
428 &AttachRequest, // Input Buffer to driver.
430 &AttachRequest, // Output Buffer from driver.
432 // buffer in bytes.
433 &ReturnedLength, // Bytes placed in buffer.
434 NULL // synchronous call
435 );
436
437 if (!Status)
438 {
439 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
440 return FALSE;
441 }
442
443 //
444 // Check if attaching was successful then we can set the attached to true
445 //
446 if (AttachRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
447 {
448 if (!AttachRequest.IsStartingNewProcess)
449 {
450 //
451 // it's a .attach command, no need for further action
452 //
453 ShowMessages("successfully attached to the target process!\n"
454 "please keep interacting with the process until all the "
455 "threads are intercepted and halted; whenever you execute "
456 "the first command, the thread interception will be stopped\n");
457 return TRUE;
458 }
459
460 // ShowMessages("Base Address : %llx\n", AttachRequest.BaseAddressOfMainModule);
461 // ShowMessages("Entrypoint Address : %llx\n", AttachRequest.EntrypoinOfMainModule);
462
463 //
464 // Resume the suspended process
465 //
466 if (ProcInfo.hThread != NULL64_ZERO)
467 {
468 ResumeThread(ProcInfo.hThread);
469 }
470 else
471 {
472 //
473 // The handle of the target thread is empty
474 //
475 return FALSE;
476 }
477
478 //
479 // *** Remove the hooks ***
480 //
481
482 while (TRUE)
483 {
484 //
485 // Send the previous request with removing hook as the action
486 //
488
489 //
490 // Send the request to the kernel
491 //
492 Status = DeviceIoControl(
493 g_DeviceHandle, // Handle to device
495 // code
496 &AttachRequest, // Input Buffer to driver.
498 &AttachRequest, // Output Buffer from driver.
500 // buffer in bytes.
501 &ReturnedLength, // Bytes placed in buffer.
502 NULL // synchronous call
503 );
504
505 if (!Status)
506 {
507 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
508 return FALSE;
509 }
510
511 //
512 // Check whether the result of removing hooks was successful or we should
513 // re-send the request
514 //
515 if (AttachRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
516 {
517 //
518 // The hook is remove successfully
519 //
520 break;
521 }
523 {
524 //
525 // Wait for a while until the Windows call the entrypoint
526 //
527 // ShowMessages("entrypoint is not reached, continue sending the request...\n");
528
529 Sleep(1000);
530 continue;
531 }
532 else
533 {
534 //
535 // An error happened, we should not continue
536 //
537 ShowErrorMessage((UINT32)AttachRequest.Result);
538 return FALSE;
539 }
540 }
541
542 //
543 // Store the process id and handle of the latest process
544 //
545 g_ProcessIdOfLatestStartingProcess = ProcInfo.dwProcessId;
546
547 //
548 // The operation of attaching was successful
549 //
550 return TRUE;
551 }
552 else
553 {
554 ShowErrorMessage((UINT32)AttachRequest.Result);
555 return FALSE;
556 }
557
558 return FALSE;
559}
UCHAR BOOLEAN
Definition BasicTypes.h:39
#define NULL64_ZERO
Definition BasicTypes.h:52
unsigned int UINT32
Definition BasicTypes.h:48
unsigned long ULONG
Definition BasicTypes.h:37
#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
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
#define IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS
ioctl, attach or detach user-mode processes
Definition Ioctls.h:162
#define SIZEOF_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS
Definition RequestStructures.h:607
@ 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 IsFileExistW(const wchar_t *FileName)
check if a file exist or not (wide-char)
Definition common.cpp:632
BOOLEAN ShowErrorMessage(UINT32 Error)
shows the error message
Definition debugger.cpp:38
#define AssertShowMessageReturnStmt(expr, message, rc)
Definition common.h:51
#define ASSERT_MESSAGE_DRIVER_NOT_LOADED
Definition common.h:25
#define AssertReturnFalse
Definition common.h:21
HANDLE g_DeviceHandle
Holds the global handle of device which is used to send the request to the kernel by IOCTL,...
Definition globals.h:471
VOID ShowMessages(const char *Fmt,...)
Show messages.
Definition libhyperdbg.cpp:96
request for attaching user-mode process
Definition RequestStructures.h:631
BOOLEAN CheckCallbackAtFirstInstruction
Definition RequestStructures.h:635
DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_TYPE Action
Definition RequestStructures.h:638
BOOLEAN IsStartingNewProcess
Definition RequestStructures.h:632
UINT32 ProcessId
Definition RequestStructures.h:633
UINT64 Result
Definition RequestStructures.h:641
UINT32 ThreadId
Definition RequestStructures.h:634
VOID UdInitializeUserDebugger()
Initialize the user debugger in user mode.
Definition ud.cpp:29
UINT32 g_ProcessIdOfLatestStartingProcess
The process id of the latest starting process.
Definition globals.h:368
BOOLEAN UdCreateSuspendedProcess(const WCHAR *FileName, const WCHAR *CommandLine, PPROCESS_INFORMATION ProcessInformation)
Attach to a target process.
Definition ud.cpp:306

◆ UdCheckThreadByProcessId()

BOOLEAN UdCheckThreadByProcessId ( DWORD Pid,
DWORD Tid )

Check if a thread belongs to special process.

Parameters
PidProcess id
TidThread id
Returns
BOOLEAN if the thread belongs to process then return true; otherwise returns false
244{
245 HANDLE ThreadSnap = INVALID_HANDLE_VALUE;
246 THREADENTRY32 Te32;
247 BOOLEAN Result = FALSE;
248
249 //
250 // Take a snapshot of all running threads
251 //
252 ThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
253 if (ThreadSnap == INVALID_HANDLE_VALUE)
254 return FALSE;
255
256 //
257 // Fill in the size of the structure before using it
258 //
259 Te32.dwSize = sizeof(THREADENTRY32);
260
261 //
262 // Retrieve information about the first thread and exit if unsuccessful
263 //
264 if (!Thread32First(ThreadSnap, &Te32))
265 {
266 UdPrintError(); // Show cause of failure
267 CloseHandle(ThreadSnap); // Must clean up the snapshot object!
268 return FALSE;
269 }
270
271 //
272 // Now walk the thread list of the system, and display information
273 // about each thread associated with the specified process
274 //
275 do
276 {
277 if (Te32.th32OwnerProcessID == Pid)
278 {
279 if (Te32.th32ThreadID == Tid)
280 {
281 //
282 // The thread found in target process
283 //
284 Result = TRUE;
285 break;
286 }
287 }
288 } while (Thread32Next(ThreadSnap, &Te32));
289
290 //
291 // Don't forget to clean up the snapshot object
292 //
293 CloseHandle(ThreadSnap);
294 return Result;
295}
VOID UdPrintError()
print error messages relating to the finding thread id
Definition ud.cpp:144

◆ UdContinueDebuggee()

VOID UdContinueDebuggee ( UINT64 ProcessDetailToken)

Continue the target user debugger.

Parameters
ProcessDetailToken
Returns
VOID
977{
978 //
979 // Send the 'continue' command
980 //
981 UdSendCommand(ProcessDetailToken,
982 NULL,
984 TRUE,
985 NULL,
986 NULL,
987 NULL,
988 NULL);
989}
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_CONTINUE
Definition RequestStructures.h:869
VOID UdSendCommand(UINT64 ProcessDetailToken, UINT32 ThreadId, DEBUGGER_UD_COMMAND_ACTION_TYPE ActionType, BOOLEAN ApplyToAllPausedThreads, UINT64 OptionalParam1, UINT64 OptionalParam2, UINT64 OptionalParam3, UINT64 OptionalParam4)
Send the command to the user debugger.
Definition ud.cpp:917

◆ UdDetachProcess()

BOOLEAN UdDetachProcess ( UINT32 TargetPid,
UINT64 ProcessDetailToken )

Detach the target process.

this function will not check whether the process id and thread id is valid or not

Parameters
TargetPid
ProcessDetailToken
Returns
BOOLEAN
765{
766 BOOLEAN Status;
767 ULONG ReturnedLength;
769
770 //
771 // Check if debugger is loaded or not
772 //
774
775 //
776 // Send the continue command to the target process as we
777 // want to continue the debuggee process before detaching
778 //
779 UdContinueDebuggee(ProcessDetailToken);
780
781 //
782 // We wanna detach a process
783 //
785
786 //
787 // Set the process id
788 //
789 DetachRequest.ProcessId = TargetPid;
790
791 //
792 // Send the request to the kernel
793 //
794 Status = DeviceIoControl(
795 g_DeviceHandle, // Handle to device
797 // code
798 &DetachRequest, // Input Buffer to driver.
800 &DetachRequest, // Output Buffer from driver.
802 // buffer in bytes.
803 &ReturnedLength, // Bytes placed in buffer.
804 NULL // synchronous call
805 );
806
807 if (!Status)
808 {
809 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
810 return FALSE;
811 }
812
813 //
814 // Check if detaching was successful or not
815 //
816 if (DetachRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
817 {
818 //
819 // Remove the current active debugging process (thread)
820 //
822
823 //
824 // The operation of attaching was successful
825 //
826 return TRUE;
827 }
828 else
829 {
830 ShowErrorMessage((UINT32)DetachRequest.Result);
831 return FALSE;
832 }
833}
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_DETACH
Definition RequestStructures.h:617
VOID UdRemoveActiveDebuggingProcess(BOOLEAN DontSwitchToNewProcess)
Remove the current active debugging process (thread)
Definition ud.cpp:129
VOID UdContinueDebuggee(UINT64 ProcessDetailToken)
Continue the target user debugger.
Definition ud.cpp:976

◆ UdHandleUserDebuggerPausing()

VOID UdHandleUserDebuggerPausing ( PDEBUGGEE_UD_PAUSED_PACKET PausePacket)

Handle pause packets from user debugger.

Parameters
PausePacket
Returns
VOID
30{
31 //
32 // Set the current active debugging process (thread)
33 //
35 PausePacket->ProcessId,
36 PausePacket->ThreadId,
37 PausePacket->Is32Bit,
38 TRUE);
39
40 //
41 // Perform extra tasks for pausing reasons
42 //
43 switch (PausePacket->PausingReason)
44 {
46
47 ShowMessages("the target module is loaded and a breakpoint is set to the entrypoint\n"
48 "press 'g' to reach to the entrypoint of the main module...\n");
49
50 break;
52
53 ShowMessages("\nthread: %x from process: %x intercepted\n",
54 PausePacket->ThreadId,
55 PausePacket->ProcessId);
56
57 break;
58
59 default:
60 break;
61 }
62
63 //
64 // Check if the instruction is received completely or not
65 //
66 if (PausePacket->ReadInstructionLen != MAXIMUM_INSTR_SIZE)
67 {
68 //
69 // We check if the disassembled buffer has greater size
70 // than what is retrieved
71 //
74 PausePacket->Is32Bit ? FALSE : TRUE) > PausePacket->ReadInstructionLen)
75 {
76 ShowMessages("oOh, no! there might be a misinterpretation in disassembling the current instruction\n");
77 }
78 }
79
80 if (!PausePacket->Is32Bit)
81 {
82 //
83 // Show diassembles
84 //
86 PausePacket->Rip,
88 1,
89 TRUE,
90 (PRFLAGS)&PausePacket->Rflags);
91 }
92 else
93 {
94 //
95 // Show diassembles
96 //
98 PausePacket->Rip,
100 1,
101 TRUE,
102 (PRFLAGS)&PausePacket->Rflags);
103 }
104
105 //
106 // Unpause the user debugger to get commands
107 //
110 .IsOnWaitingState == TRUE)
111 {
113 }
114}
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_GENERAL_THREAD_INTERCEPTED
Definition Connection.h:42
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_STARTING_MODULE_LOADED
Definition Connection.h:36
#define MAXIMUM_INSTR_SIZE
maximum instruction size in Intel
Definition Constants.h:468
int HyperDbgDisassembler32(unsigned char *BufferToDisassemble, UINT64 BaseAddress, UINT64 Size, UINT32 MaximumInstrDecoded, BOOLEAN ShowBranchIsTakenOrNot, PRFLAGS Rflags)
Disassemble 32 bit assemblies.
Definition disassembler.cpp:373
int HyperDbgDisassembler64(unsigned char *BufferToDisassemble, UINT64 BaseAddress, UINT64 Size, UINT32 MaximumInstrDecoded, BOOLEAN ShowBranchIsTakenOrNot, PRFLAGS Rflags)
Disassemble x64 assemblies.
Definition disassembler.cpp:333
UINT32 HyperDbgLengthDisassemblerEngine(unsigned char *BufferToDisassemble, UINT64 BuffLength, BOOLEAN Isx86_64)
Length Disassembler engine based on Zydis.
Definition disassembler.cpp:856
#define DEBUGGER_SYNCRONIZATION_OBJECT_USER_DEBUGGER_IS_DEBUGGER_RUNNING
An event to show whether the debugger is running or not in user-debugger.
Definition debugger.h:99
#define DbgReceivedUserResponse(UserSyncObjectId)
Definition ud.h:28
RFLAGS * PRFLAGS
Definition pch.h:34
DEBUGGEE_PAUSING_REASON PausingReason
Definition DataTypes.h:233
UINT16 ReadInstructionLen
Definition DataTypes.h:240
UINT64 Rip
Definition DataTypes.h:230
BOOLEAN Is32Bit
Definition DataTypes.h:232
UINT64 ProcessDebuggingToken
Definition DataTypes.h:231
UINT64 Rflags
Definition DataTypes.h:236
UINT32 ThreadId
Definition DataTypes.h:235
UINT32 ProcessId
Definition DataTypes.h:234
BYTE InstructionBytesOnRip[MAXIMUM_INSTR_SIZE]
Definition DataTypes.h:239
VOID UdSetActiveDebuggingProcess(UINT64 DebuggingId, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, BOOLEAN IsPaused)
set the current active debugging process (thread)
Definition ud.cpp:100
DEBUGGER_SYNCRONIZATION_EVENTS_STATE g_UserSyncronizationObjectsHandleTable[DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS]
In debugger (not debuggee), we save the handle of the user-mode listening thread for pauses here for ...
Definition globals.h:176

◆ UdInitializeUserDebugger()

VOID UdInitializeUserDebugger ( )

initialize user debugger

this function should be called on vmx non-root

Returns
BOOLEAN

initialize user debugger

Returns
VOID
22{
23 //
24 // Check if it's already initialized or not, we'll ignore it if it's
25 // previously initialized
26 //
28 {
29 return TRUE;
30 }
31
32 //
33 // Check if we have functions we need for attaching mechanism
34 //
36 {
37 LogError("Err, unable to find needed functions for user-debugger");
38 // return FALSE;
39 }
40
41 //
42 // Start the seed of user-mode debugging thread
43 //
45
46 //
47 // Initialize the thread debugging details list
48 //
50
51 //
52 // Enable vm-exit on Hardware debug exceptions and breakpoints
53 // so, intercept #DBs and #BP by changing exception bitmap (one core)
54 //
56
57 //
58 // Request to allocate buffers for thread holder of threads
59 //
61
62 //
63 // Indicate that the user debugger is active
64 //
66
67 return TRUE;
68}
VOID BroadcastEnableDbAndBpExitingAllCores()
routines to set vm-exit on all #DBs and #BP on all cores
Definition Broadcast.c:35
#define DebuggerThreadDebuggingTagStartSeed
The seeds that user-mode thread detail token start with it.
Definition Constants.h:229
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
VOID ThreadHolderAllocateThreadHoldingBuffers()
Pre allocate buffer for thread holder.
Definition ThreadHolder.c:21
ZwQueryInformationProcess g_ZwQueryInformationProcess
Address of ZwQueryInformationProcess.
Definition UserAccess.h:187
PsGetProcessPeb g_PsGetProcessPeb
Address of PsGetProcessPeb.
Definition UserAccess.h:193
PsGetProcessWow64Process g_PsGetProcessWow64Process
Address of PsGetProcessWow64Process.
Definition UserAccess.h:199
FORCEINLINE VOID InitializeListHead(_Out_ PLIST_ENTRY ListHead)
Definition Windows.h:41
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
BOOLEAN g_UserDebuggerState
shows whether the user debugger is enabled or disabled
Definition Global.h:109

◆ UdKillProcess()

BOOLEAN UdKillProcess ( UINT32 TargetPid)

Kill the target process from kernel.

this function will not check whether the process id and thread id is valid or not

Parameters
TargetPid
Returns
BOOLEAN
667{
668 BOOLEAN Status;
669 ULONG ReturnedLength;
671
672 //
673 // Check if debugger is loaded or not
674 //
676
677 //
678 // Check if the process exists
679 //
680 if (!UdDoesProcessExistByPid(TargetPid))
681 {
682 return FALSE;
683 }
684
685 //
686 // First, we try to kill the process in user-mode, if not successful,
687 // we try to kill it from kernel-mode
688 //
689 UdTerminateProcessByPid(TargetPid);
690
691 //
692 // Check again to see if the process exists
693 //
694 if (!UdDoesProcessExistByPid(TargetPid))
695 {
696 return TRUE;
697 }
698
699 //
700 // We wanna kill a process
701 //
703
704 //
705 // Set the process id
706 //
707 KillRequest.ProcessId = TargetPid;
708
709 //
710 // Send the request to the kernel
711 //
712 Status = DeviceIoControl(
713 g_DeviceHandle, // Handle to device
715 // code
716 &KillRequest, // Input Buffer to driver.
718 &KillRequest, // Output Buffer from driver.
720 // buffer in bytes.
721 &ReturnedLength, // Bytes placed in buffer.
722 NULL // synchronous call
723 );
724
725 if (!Status)
726 {
727 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
728 return FALSE;
729 }
730
731 //
732 // Check if killing was successful or not
733 //
734 if (KillRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
735 {
736 //
737 // Remove the current active debugging process (thread)
738 //
740
741 //
742 // The operation of attaching was successful
743 //
744 return TRUE;
745 }
746 else
747 {
748 ShowErrorMessage((UINT32)KillRequest.Result);
749 return FALSE;
750 }
751}
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_KILL_PROCESS
Definition RequestStructures.h:619
BOOLEAN UdTerminateProcessByPid(DWORD TargetPid)
Check if process exists or not.
Definition ud.cpp:569
BOOLEAN UdDoesProcessExistByPid(DWORD TargetPid)
Check if process exists or not by process id.
Definition ud.cpp:606

◆ UdListProcessThreads()

BOOL UdListProcessThreads ( DWORD OwnerPID)

List of threads by owner process id.

Parameters
OwnerPID
Returns
BOOL if there was an error then returns false, otherwise return true
184{
185 HANDLE ThreadSnap = INVALID_HANDLE_VALUE;
186 THREADENTRY32 Te32;
187
188 //
189 // Take a snapshot of all running threads
190 //
191 ThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
192 if (ThreadSnap == INVALID_HANDLE_VALUE)
193 return FALSE;
194
195 //
196 // Fill in the size of the structure before using it
197 //
198 Te32.dwSize = sizeof(THREADENTRY32);
199
200 //
201 // Retrieve information about the first thread and exit if unsuccessful
202 //
203 if (!Thread32First(ThreadSnap, &Te32))
204 {
205 UdPrintError(); // Show cause of failure
206 CloseHandle(ThreadSnap); // Must clean up the snapshot object!
207 return FALSE;
208 }
209 ShowMessages("\nThread's of pid\t= 0x%08X\n", OwnerPID);
210
211 //
212 // Now walk the thread list of the system, and display information
213 // about each thread associated with the specified process
214 //
215 do
216 {
217 if (Te32.th32OwnerProcessID == OwnerPID)
218 {
219 ShowMessages("\n Thread Id\t= 0x%08X", Te32.th32ThreadID);
220 // ShowMessages("\n base priority = %x", Te32.tpBasePri);
221 // ShowMessages("\n delta priority = %x", Te32.tpDeltaPri);
222 }
223 } while (Thread32Next(ThreadSnap, &Te32));
224
225 ShowMessages("\n");
226
227 //
228 // Don't forget to clean up the snapshot object
229 //
230 CloseHandle(ThreadSnap);
231 return TRUE;
232}

◆ UdPauseProcess()

BOOLEAN UdPauseProcess ( UINT64 ProcessDebuggingToken)

Pause the target process.

Parameters
ProcessDebuggingToken
Returns
BOOLEAN
844{
845 BOOLEAN Status;
846 ULONG ReturnedLength;
848
849 //
850 // Check if debugger is loaded or not
851 //
853
854 //
855 // We wanna pause a process
856 //
858
859 //
860 // Set the process debugging token
861 //
862 PauseRequest.Token = ProcessDebuggingToken;
863
864 //
865 // Send the request to the kernel
866 //
867 Status = DeviceIoControl(
868 g_DeviceHandle, // Handle to device
870 // code
871 &PauseRequest, // Input Buffer to driver.
873 &PauseRequest, // Output Buffer from driver.
875 // buffer in bytes.
876 &ReturnedLength, // Bytes placed in buffer.
877 NULL // synchronous call
878 );
879
880 if (!Status)
881 {
882 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
883 return FALSE;
884 }
885
886 //
887 // Check if killing was successful or not
888 //
889 if (PauseRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
890 {
891 //
892 // The operation of attaching was successful
893 //
894 return TRUE;
895 }
896 else
897 {
898 ShowErrorMessage((UINT32)PauseRequest.Result);
899 return FALSE;
900 }
901}
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_PAUSE_PROCESS
Definition RequestStructures.h:620
UINT64 Token
Definition RequestStructures.h:640

◆ UdRemoveActiveDebuggingProcess()

VOID UdRemoveActiveDebuggingProcess ( BOOLEAN DontSwitchToNewProcess)

Remove the current active debugging process (thread)

Parameters
DontSwitchToNewProcess
Returns
VOID
130{
131 //
132 // Activate the debugging
133 //
135}
BOOLEAN IsActive
Definition ud.h:49
ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState
State of active debugging thread.
Definition globals.h:362

◆ UdSendStepPacketToDebuggee()

VOID UdSendStepPacketToDebuggee ( UINT64 ProcessDetailToken,
UINT32 TargetThreadId,
DEBUGGER_REMOTE_STEPPING_REQUEST StepType )

Send stepping instructions packet to user debugger.

Parameters
ProcessDetailToken
TargetThreadId
StepType
Returns
VOID
1001{
1002 //
1003 // Wait until the result of user-input received
1004 //
1008
1009 //
1010 // Send the 'continue' command
1011 //
1012 UdSendCommand(ProcessDetailToken,
1013 TargetThreadId,
1015 FALSE,
1016 StepType,
1017 NULL,
1018 NULL,
1019 NULL);
1020
1021 WaitForSingleObject(
1024 .EventHandle,
1025 INFINITE);
1026}
@ DEBUGGER_UD_COMMAND_ACTION_TYPE_REGULAR_STEP
Definition RequestStructures.h:870

◆ UdSetActiveDebuggingProcess()

VOID UdSetActiveDebuggingProcess ( UINT64 DebuggingId,
UINT32 ProcessId,
UINT32 ThreadId,
BOOLEAN Is32Bit,
BOOLEAN IsPaused )

set the current active debugging process (thread)

Parameters
DebuggingId
ProcessId
ThreadId
Is32Bit
Returns
VOID
105{
110
111 //
112 // Set pausing state
113 //
115
116 //
117 // Activate the debugging
118 //
120}
UINT32 ProcessId
Definition ud.h:51
UINT32 ThreadId
Definition ud.h:52
UINT64 ProcessDebuggingToken
Definition ud.h:50
BOOLEAN Is32Bit
Definition ud.h:56
BOOLEAN IsPaused
Definition ud.h:53

◆ UdSetActiveDebuggingThreadByPidOrTid()

BOOLEAN UdSetActiveDebuggingThreadByPidOrTid ( UINT32 TargetPidOrTid,
BOOLEAN IsTid )

Set the active debugging thread by process id or thread id.

Parameters
TargetPidOrTid
IsTid
Returns
BOOLEAN
1038{
1039 BOOLEAN Status;
1040 ULONG ReturnedLength;
1041 DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS SwitchRequest = {0};
1042
1043 //
1044 // Check if debugger is loaded or not
1045 //
1047
1048 //
1049 // We wanna switch to a process or thread
1050 //
1052
1053 //
1054 // Set the process id or thread id
1055 //
1056 if (IsTid)
1057 {
1058 SwitchRequest.ThreadId = TargetPidOrTid;
1059 }
1060 else
1061 {
1062 SwitchRequest.ProcessId = TargetPidOrTid;
1063 }
1064
1065 //
1066 // Send the request to the kernel
1067 //
1068 Status = DeviceIoControl(
1069 g_DeviceHandle, // Handle to device
1071 // code
1072 &SwitchRequest, // Input Buffer to driver.
1074 &SwitchRequest, // Output Buffer from driver.
1076 // buffer in bytes.
1077 &ReturnedLength, // Bytes placed in buffer.
1078 NULL // synchronous call
1079 );
1080
1081 if (!Status)
1082 {
1083 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
1084 return FALSE;
1085 }
1086
1087 //
1088 // Check if killing was successful or not
1089 //
1090 if (SwitchRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
1091 {
1092 //
1093 // Set the current active debugging process (thread)
1094 //
1095 UdSetActiveDebuggingProcess(SwitchRequest.Token,
1096 SwitchRequest.ProcessId,
1097 SwitchRequest.ThreadId,
1098 SwitchRequest.Is32Bit,
1099 SwitchRequest.IsPaused);
1100
1101 //
1102 // The operation of attaching was successful
1103 //
1104 return TRUE;
1105 }
1106 else
1107 {
1108 ShowErrorMessage((UINT32)SwitchRequest.Result);
1109 return FALSE;
1110 }
1111}
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_SWITCH_BY_PROCESS_OR_THREAD
Definition RequestStructures.h:621
BOOLEAN IsPaused
Definition RequestStructures.h:637
BOOLEAN Is32Bit
Definition RequestStructures.h:636

◆ UdShowListActiveDebuggingProcessesAndThreads()

BOOLEAN UdShowListActiveDebuggingProcessesAndThreads ( )

Show list of active debugging processes and threads.

Returns
BOOLEAN
1120{
1121 BOOLEAN Status;
1122 BOOLEAN CheckCurrentProcessOrThread;
1123 ULONG ReturnedLength;
1124 DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS QueryCountOfActiveThreadsRequest = {0};
1125 USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS * AddressOfThreadsAndProcessDetails = NULL;
1126 UINT32 SizeOfBufferForThreadsAndProcessDetails = NULL;
1127
1128 //
1129 // Check if debugger is loaded or not
1130 //
1132
1133 //
1134 // Check if user debugger is active or not
1135 //
1137 {
1138 ShowMessages("user debugger is not initialized. Did you use the '.attach' or the '.start' "
1139 "command before?\n");
1140 return FALSE;
1141 }
1142
1143 //
1144 // We wanna query the count of active debugging threads
1145 //
1147
1148 //
1149 // Send the request to the kernel
1150 //
1151 Status = DeviceIoControl(
1152 g_DeviceHandle, // Handle to device
1154 // code
1155 &QueryCountOfActiveThreadsRequest, // Input Buffer to driver.
1157 &QueryCountOfActiveThreadsRequest, // Output Buffer from driver.
1159 // buffer in bytes.
1160 &ReturnedLength, // Bytes placed in buffer.
1161 NULL // synchronous call
1162 );
1163
1164 if (!Status)
1165 {
1166 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
1167 return FALSE;
1168 }
1169
1170 //
1171 // Query was successful
1172 //
1173 if (QueryCountOfActiveThreadsRequest.Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
1174 {
1175 if (QueryCountOfActiveThreadsRequest.CountOfActiveDebuggingThreadsAndProcesses == 0)
1176 {
1177 ShowMessages("no active debugging threads!\n");
1178 }
1179 else
1180 {
1181 //
1182 // *** We should send another IOCTL and get the list of threads ***
1183 //
1184
1185 //
1186 // Allocate the storage for the pull details of threads and processes
1187 //
1188 SizeOfBufferForThreadsAndProcessDetails =
1190
1191 AddressOfThreadsAndProcessDetails = (USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS *)malloc(SizeOfBufferForThreadsAndProcessDetails);
1192
1193 if (AddressOfThreadsAndProcessDetails == NULL64_ZERO)
1194 {
1195 ShowMessages("insufficient space\n");
1196 return FALSE;
1197 }
1198
1199 RtlZeroMemory(AddressOfThreadsAndProcessDetails, SizeOfBufferForThreadsAndProcessDetails);
1200
1201 //
1202 // Send the request to the kernel
1203 //
1204 Status = DeviceIoControl(
1205 g_DeviceHandle, // Handle to device
1207 // code
1208 NULL, // Input Buffer to driver.
1209 0, // Input buffer length.
1210 AddressOfThreadsAndProcessDetails, // Output Buffer from driver.
1211 SizeOfBufferForThreadsAndProcessDetails, // Length of output buffer in bytes.
1212 &ReturnedLength, // Bytes placed in buffer.
1213 NULL // synchronous call
1214 );
1215
1216 if (!Status)
1217 {
1218 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
1219 return FALSE;
1220 }
1221
1222 //
1223 // Show list of active processes and threads
1224 //
1225 for (size_t i = 0; i < QueryCountOfActiveThreadsRequest.CountOfActiveDebuggingThreadsAndProcesses; i++)
1226 {
1227 if (AddressOfThreadsAndProcessDetails[i].IsProcess)
1228 {
1229 CheckCurrentProcessOrThread = FALSE;
1230
1231 if (g_ActiveProcessDebuggingState.IsActive && AddressOfThreadsAndProcessDetails[i].ProcessId == g_ActiveProcessDebuggingState.ProcessId)
1232 {
1233 CheckCurrentProcessOrThread = TRUE;
1234 }
1235
1236 ShowMessages("%s%04x (process)\n",
1237 CheckCurrentProcessOrThread ? "*" : "",
1238 AddressOfThreadsAndProcessDetails[i].ProcessId);
1239 }
1240 else
1241 {
1242 CheckCurrentProcessOrThread = FALSE;
1243
1244 if (g_ActiveProcessDebuggingState.IsActive && AddressOfThreadsAndProcessDetails[i].ThreadId == g_ActiveProcessDebuggingState.ThreadId)
1245 {
1246 CheckCurrentProcessOrThread = TRUE;
1247 }
1248 ShowMessages("\t%s %04x (thread)\n",
1249 CheckCurrentProcessOrThread ? "->" : " ",
1250 AddressOfThreadsAndProcessDetails[i].ThreadId);
1251 }
1252 }
1253 }
1254
1255 //
1256 // The operation of attaching was successful
1257 //
1258 return TRUE;
1259 }
1260 else
1261 {
1262 ShowErrorMessage((UINT32)QueryCountOfActiveThreadsRequest.Result);
1263 return FALSE;
1264 }
1265}
#define IOCTL_GET_DETAIL_OF_ACTIVE_THREADS_AND_PROCESSES
ioctl, to get active threads/processes that are debugging
Definition Ioctls.h:233
#define SIZEOF_USERMODE_DEBUGGING_THREAD_OR_PROCESS_STATE_DETAILS
Definition RequestStructures.h:806
@ DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS_ACTION_QUERY_COUNT_OF_ACTIVE_DEBUGGING_THREADS
Definition RequestStructures.h:622
NULL()
Definition test-case-generator.py:530
UINT32 CountOfActiveDebuggingThreadsAndProcesses
Definition RequestStructures.h:639
Definition RequestStructures.h:810
BOOLEAN g_IsUserDebuggerInitialized
Whether the user debugger is initialized or not.
Definition globals.h:167

◆ UdUninitializeUserDebugger()

VOID UdUninitializeUserDebugger ( )

uninitialize user debugger

this function should be called on vmx non-root

Returns
VOID

uninitialize user debugger

Returns
VOID
78{
80 {
81 //
82 // Indicate that the user debugger is not active
83 //
85
86 //
87 // Free and deallocate all the buffers (pools) relating to
88 // thread debugging details
89 //
91 }
92}
VOID AttachingRemoveAndFreeAllProcessDebuggingDetails()
Remove and deallocate all thread debuggig details.
Definition Attaching.c:229