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

control the user-mode debugging affairs More...

#include "pch.h"

Functions

VOID UdInitializeUserDebugger ()
 Initialize the user debugger in user mode.
 
VOID UdUninitializeUserDebugger ()
 Uninitialize the user debugger in user mode.
 
VOID UdSetActiveDebuggingProcess (UINT64 DebuggingId, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, BOOLEAN IsPaused)
 set the current active debugging process (thread)
 
VOID UdRemoveActiveDebuggingProcess (BOOLEAN DontSwitchToNewProcess)
 Remove the current active debugging process (thread)
 
VOID UdPrintError ()
 print error messages relating to the finding thread id
 
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 UdCreateSuspendedProcess (const WCHAR *FileName, const WCHAR *CommandLine, PPROCESS_INFORMATION ProcessInformation)
 Attach to a target process.
 
BOOLEAN UdAttachToProcess (UINT32 TargetPid, const WCHAR *TargetFileAddress, const WCHAR *CommandLine, BOOLEAN RunCallbackAtTheFirstInstruction)
 Attach to target process.
 
BOOLEAN UdTerminateProcessByPid (DWORD TargetPid)
 Check if process exists or not.
 
BOOLEAN UdDoesProcessExistByPid (DWORD TargetPid)
 Check if process exists or not by process id.
 
BOOLEAN UdDoesProcessExistByHandle (HANDLE TargetHandle)
 Check if process exists or not by handle.
 
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.
 
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.
 
VOID UdContinueDebuggee (UINT64 ProcessDetailToken)
 Continue the target user debugger.
 
VOID UdSendStepPacketToDebuggee (UINT64 ProcessDetailToken, UINT32 TargetThreadId, DEBUGGER_REMOTE_STEPPING_REQUEST StepType)
 Send stepping instructions packet to user debugger.
 
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.
 

Variables

UINT32 g_ProcessIdOfLatestStartingProcess
 The process id of the latest starting process.
 
ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState
 State of active debugging thread.
 
BOOLEAN g_IsUserDebuggerInitialized
 Whether the user debugger is initialized or not.
 
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 user debugger.
 

Detailed Description

control the user-mode debugging affairs

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

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
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
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

◆ UdCreateSuspendedProcess()

BOOLEAN UdCreateSuspendedProcess ( const WCHAR * FileName,
const WCHAR * CommandLine,
PPROCESS_INFORMATION ProcessInformation )

Attach to a target process.

Parameters
FileName
CommandLine
ProcessInformation
Returns
BOOLEAN
307{
308 STARTUPINFOW StartupInfo;
309 BOOL CreateProcessResult;
310
311 memset(&StartupInfo, 0, sizeof(StartupInfo));
312 StartupInfo.cb = sizeof(STARTUPINFOA);
313
314 //
315 // Create process suspended
316 //
317 CreateProcessResult = CreateProcessW(FileName,
318 (WCHAR *)CommandLine,
319 NULL,
320 NULL,
321 FALSE,
322 CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
323 NULL,
324 NULL,
325 &StartupInfo,
326 ProcessInformation);
327
328 if (!CreateProcessResult)
329 {
330 ShowMessages("err, start process failed (%x)", GetLastError());
331 return FALSE;
332 }
333
334 return TRUE;
335}
int BOOL
Definition BasicTypes.h:23
wchar_t WCHAR
Definition BasicTypes.h:32

◆ 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

◆ UdDoesProcessExistByHandle()

BOOLEAN UdDoesProcessExistByHandle ( HANDLE TargetHandle)

Check if process exists or not by handle.

Parameters
TargetHandle
Returns
BOOLEAN
635{
636 DWORD exitCodeOut;
637
638 //
639 // GetExitCodeProcess returns zero on failure
640 //
641 if (GetExitCodeProcess(TargetHandle, &exitCodeOut) == 0)
642 {
643 //
644 // Optionally get the error
645 //
646 // DWORD error = GetLastError();
647 return FALSE;
648 }
649
650 //
651 // Return if the process is still active
652 //
653 return exitCodeOut == STILL_ACTIVE;
654}
unsigned long DWORD
Definition BasicTypes.h:22

◆ UdDoesProcessExistByPid()

BOOLEAN UdDoesProcessExistByPid ( DWORD TargetPid)

Check if process exists or not by process id.

Parameters
TargetPid
Returns
BOOLEAN
607{
608 if (HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, TargetPid))
609 {
610 DWORD ExitCodeOut;
611
612 //
613 // GetExitCodeProcess returns zero on failure
614 //
615 if (GetExitCodeProcess(process, &ExitCodeOut) != 0)
616 {
617 //
618 // Return if the process is still active
619 //
620 return ExitCodeOut == STILL_ACTIVE;
621 }
622 }
623 return FALSE;
624}

◆ UdInitializeUserDebugger()

VOID UdInitializeUserDebugger ( )

Initialize the user debugger in user mode.

initialize user debugger

Returns
VOID
31{
33 {
34 //
35 // Initialize the handle table
36 //
38 {
41 }
42
43 //
44 // Indicate that it's initialized
45 //
47 }
48}
#define DEBUGGER_MAXIMUM_SYNCRONIZATION_USER_DEBUGGER_OBJECTS
Maximum number of event handles in user-debugger.
Definition debugger.h:88
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
BOOLEAN g_IsUserDebuggerInitialized
Whether the user debugger is initialized or not.
Definition globals.h:167

◆ 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

◆ UdPrintError()

VOID UdPrintError ( )

print error messages relating to the finding thread id

this function is used only in the scope of Thread32First

Returns
VOID
145{
146 DWORD ErrNum;
147 TCHAR SysMsg[256];
148 TCHAR * p;
149
150 ErrNum = GetLastError();
151 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
152 NULL,
153 ErrNum,
154 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
155 SysMsg,
156 256,
157 NULL);
158
159 //
160 // Trim the end of the line and terminate it with a null
161 //
162 p = SysMsg;
163 while ((*p > 31) || (*p == 9))
164 ++p;
165 do
166 {
167 *p-- = 0;
168 } while ((p >= SysMsg) && ((*p == '.') || (*p < 33)));
169
170 //
171 // Display the message
172 //
173 ShowMessages("\n WARNING: Thread32First failed with error (%x:%s)", ErrNum, SysMsg);
174}

◆ 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

◆ UdSendCommand()

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.

Parameters
ProcessDetailToken
ThreadId
ActionType
ApplyToAllPausedThreads
OptionalParam1
OptionalParam2
OptionalParam3
OptionalParam4
Returns
VOID
925{
926 BOOL Status;
927 ULONG ReturnedLength;
928 DEBUGGER_UD_COMMAND_PACKET CommandPacket;
929
931
932 //
933 // Zero the packet
934 //
935 RtlZeroMemory(&CommandPacket, sizeof(DEBUGGER_UD_COMMAND_PACKET));
936
937 //
938 // Set to the details
939 //
940 CommandPacket.ProcessDebuggingDetailToken = ProcessDetailToken;
941 CommandPacket.ApplyToAllPausedThreads = ApplyToAllPausedThreads;
942 CommandPacket.TargetThreadId = ThreadId;
943 CommandPacket.UdAction.ActionType = ActionType;
944 CommandPacket.UdAction.OptionalParam1 = OptionalParam1;
945 CommandPacket.UdAction.OptionalParam2 = OptionalParam2;
946 CommandPacket.UdAction.OptionalParam3 = OptionalParam3;
947 CommandPacket.UdAction.OptionalParam4 = OptionalParam4;
948
949 //
950 // Send IOCTL
951 //
952 Status = DeviceIoControl(g_DeviceHandle, // Handle to device
953 IOCTL_SEND_USER_DEBUGGER_COMMANDS, // IO Control Code (IOCTL)
954 &CommandPacket, // Input Buffer to driver.
955 sizeof(DEBUGGER_UD_COMMAND_PACKET), // Input buffer length
956 &CommandPacket, // Output Buffer from driver.
957 sizeof(DEBUGGER_UD_COMMAND_PACKET), // Length of output buffer in bytes.
958 &ReturnedLength, // Bytes placed in buffer.
959 NULL // synchronous call
960 );
961
962 if (!Status)
963 {
964 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
965 return;
966 }
967}
#define IOCTL_SEND_USER_DEBUGGER_COMMANDS
ioctl, to send user debugger commands
Definition Ioctls.h:226
#define AssertReturn
Definition common.h:19
DEBUGGER_UD_COMMAND_ACTION_TYPE ActionType
Definition RequestStructures.h:880
UINT64 OptionalParam1
Definition RequestStructures.h:881
UINT64 OptionalParam3
Definition RequestStructures.h:883
UINT64 OptionalParam4
Definition RequestStructures.h:884
UINT64 OptionalParam2
Definition RequestStructures.h:882
The structure of command packet in uHyperDbg.
Definition RequestStructures.h:893
DEBUGGER_UD_COMMAND_ACTION UdAction
Definition RequestStructures.h:894
UINT32 TargetThreadId
Definition RequestStructures.h:896
BOOLEAN ApplyToAllPausedThreads
Definition RequestStructures.h:897
UINT64 ProcessDebuggingDetailToken
Definition RequestStructures.h:895

◆ 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
#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

◆ 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
VOID UdSetActiveDebuggingProcess(UINT64 DebuggingId, UINT32 ProcessId, UINT32 ThreadId, BOOLEAN Is32Bit, BOOLEAN IsPaused)
set the current active debugging process (thread)
Definition ud.cpp:100

◆ 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

◆ UdTerminateProcessByPid()

BOOLEAN UdTerminateProcessByPid ( DWORD TargetPid)

Check if process exists or not.

Parameters
TargetPid
Returns
BOOLEAN
570{
571 BOOL Terminated = FALSE;
572
573 //
574 // Attempt to open a handle to the process with PROCESS_TERMINATE access rights
575 //
576 HANDLE Handle = OpenProcess(PROCESS_TERMINATE, FALSE, TargetPid);
577 if (Handle == NULL)
578 {
579 //
580 // Failed to open the process, which likely means it does not exist or access is denied
581 //
582 return FALSE;
583 }
584
585 //
586 // Terminate the process
587 //
588 Terminated = TerminateProcess(Handle, 0);
589
590 //
591 // Close the process handle
592 //
593 CloseHandle(Handle);
594
595 return Terminated;
596}

◆ UdUninitializeUserDebugger()

VOID UdUninitializeUserDebugger ( )

Uninitialize the user debugger in user mode.

uninitialize user debugger

Returns
VOID
58{
60 {
61 //
62 // Remove the active process
63 //
65
66 //
67 // Initialize the handle table
68 //
70 {
71 if (g_UserSyncronizationObjectsHandleTable[i].EventHandle != NULL)
72 {
73 if (g_UserSyncronizationObjectsHandleTable[i].IsOnWaitingState)
74 {
76 }
77
78 CloseHandle(g_UserSyncronizationObjectsHandleTable[i].EventHandle);
80 }
81 }
82
83 //
84 // Indicate that user debugger is not initialized
85 //
87 }
88}
#define DbgReceivedUserResponse(UserSyncObjectId)
Definition ud.h:28

Variable Documentation

◆ g_ActiveProcessDebuggingState

ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState
extern

State of active debugging thread.

362{0};

◆ g_IsUserDebuggerInitialized

BOOLEAN g_IsUserDebuggerInitialized
extern

Whether the user debugger is initialized or not.

◆ g_ProcessIdOfLatestStartingProcess

UINT32 g_ProcessIdOfLatestStartingProcess
extern

The process id of the latest starting process.

◆ g_UserSyncronizationObjectsHandleTable

In debugger (not debuggee), we save the handle of the user-mode listening thread for pauses here for user debugger.

176{0};