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

Implementation of kernel debugger functions for threads. More...

#include "pch.h"

Functions

BOOLEAN ThreadHandleThreadChange (PROCESSOR_DEBUGGING_STATE *DbgState)
 handle thread changes
BOOLEAN ThreadSwitch (PROCESSOR_DEBUGGING_STATE *DbgState, UINT32 ThreadId, PETHREAD EThread, BOOLEAN CheckByClockInterrupt)
 make evnvironment ready to change the thread
BOOLEAN ThreadShowList (PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListSymbolInfo, DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTIONS QueryAction, UINT32 *CountOfThreads, PVOID ListSaveBuffer, UINT64 ListSaveBuffSize)
 shows the threads list
BOOLEAN ThreadInterpretThread (PROCESSOR_DEBUGGING_STATE *DbgState, PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET TidRequest)
 change the current thread
VOID ThreadDetectChangeByDebugRegisterOnGs (PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN Enable)
 Enable or disable the thread change monitoring detection on the running core based on putting a HW breakpoint on the gs:[188].
BOOLEAN ThreadQueryDebugRegisterInterceptionStateByCoreId (UINT32 CoreId)
 Query for deubg register interception state.
VOID ThreadDetectChangeByInterceptingClockInterrupts (PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN Enable)
 Enable or disable the thread change monitoring detection on the running core based on intercepting clock interrupts.
VOID ThreadEnableOrDisableThreadChangeMonitor (PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN Enable, BOOLEAN IsSwitchByClockIntrrupt)
 Enable or disable the thread change monitoring detection on the running core.
BOOLEAN ThreadQueryCount (PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest)
 Query thread details (count).
BOOLEAN ThreadQueryList (PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest, PVOID AddressToSaveDetail, UINT32 BufferSize)
 Query thread details (list).
BOOLEAN ThreadQueryDetails (PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET GetInformationThreadRequest)
 Query thread details.

Detailed Description

Implementation of kernel debugger functions for threads.

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

Function Documentation

◆ ThreadDetectChangeByDebugRegisterOnGs()

VOID ThreadDetectChangeByDebugRegisterOnGs ( PROCESSOR_DEBUGGING_STATE * DbgState,
BOOLEAN Enable )

Enable or disable the thread change monitoring detection on the running core based on putting a HW breakpoint on the gs:[188].

should be called on vmx root

Parameters
DbgStateThe state of the debugger on the current core
Enable
Returns
VOID
426{
427 UINT64 MsrGsBase;
428
429 if (Enable)
430 {
431 //
432 // Enable Thread Change Detection
433 // *** Read the address of GS:188 to g_CurrentThreadLocation ***
434 //
435
436 //
437 // We are in kernel, so we should read MSR GS_BASE
438 // IA32_GS_BASE 0xC0000101
439 // IA32_KERNEL_GS_BASE 0xC0000102
440 // IA32_KERNEL_GS_BASE is currently user's gs as
441 // we are in the kernel-mode, if we need to intercept
442 // from user-mode then IA32_KERNEL_GS_BASE should be used
443 // but it's not for our case
444 //
445 MsrGsBase = CpuReadMsr(IA32_GS_BASE);
446
447 //
448 // Now, we have the gs base on MSR
449 // while in Windows gs:188 has the address
450 // of where the store current _ETHREAD, so
451 // we have to 188 to the gs base
452 //
453 MsrGsBase += 0x188;
454
455 //
456 // Set the global value for current thread of this processor
457 //
459
460 //
461 // Set interception state
462 //
464
465 //
466 // Enable load debug controls and save debug controls because we don't
467 // want dr7 and dr0 remove their configuration on vm-exits and also
468 // we'll be able to change the dr7 of the guest on VMCS
469 //
472
473 //
474 // Intercept #DBs by changing exception bitmap (one core)
475 //
477
478 //
479 // Note, this function is running as a DPC routines, means that
480 // we're currently on DISPATCH_LEVEL so after modifying debug
481 // registers and after disabling mov to dr (using vmcall),
482 // nothing is able to change debug registers so it's safe
483 //
484
485 //
486 // Set debug register to fire an exception in the case of
487 // read/write on the gs:188 as we intercept it on
488 // hypervisor side by exception bitmap on #DBs
489 // However, this call is somehow useless because I also set it
490 // on Mov 2 Debug regs handler (vm-exit), but we set from here
491 // to make sure that the vm-exit handler set this break on access
492 //
496 TRUE,
498
499 //
500 // Enables mov to debug registers exitings in primary cpu-based controls
501 // it is because I realized that some other routines in Windows like
502 // KiSaveProcessorControlState and KiRestoreProcessorControlState and
503 // other functions directly change the debug registers, probably
504 // because we should not modify debug registers directly, by the way, we
505 // are hypervisor and we can easily ignore mov to debug register (0 in
506 // this case), however we should somehow hide this process in the future
507 //
509 }
510 else
511 {
512 //
513 // Disable Thread Change Detection
514 // *** Remove side changes ***
515 //
516
517 //
518 // We should not ignore debug registers change anymore
519 //
521
522 //
523 // Disable mov to debug regs vm-exit
524 //
526
527 //
528 // Disable load debug controls and save debug controls because
529 // no longer needed
530 //
533
534 //
535 // Disable intercepting #DBs
536 //
538
539 //
540 // No longer need to store such gs:188 value
541 //
543 }
544}
UINT64 CpuReadMsr(ULONG MsrAddress)
Read an MSR.
Definition PlatformIntrinsics.c:213
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
@ BREAK_ON_WRITE_ONLY
Definition DataTypes.h:104
@ EXCEPTION_VECTOR_DEBUG_BREAKPOINT
Definition Events.h:25
IMPORT_EXPORT_VMM VOID VmFuncUnsetExceptionBitmap(UINT32 CoreId, UINT32 IdtIndex)
Unset exception bitmap in VMCS.
Definition Export.c:312
IMPORT_EXPORT_VMM BOOLEAN SetDebugRegisters(UINT32 DebugRegNum, DEBUG_REGISTER_TYPE ActionType, BOOLEAN ApplyToVmcs, UINT64 TargetAddress)
Configure hardware debug register for access, write and fetch breakpoints.
Definition DebugRegisters.c:37
IMPORT_EXPORT_VMM VOID VmFuncSetMovDebugRegsExiting(UINT32 CoreId, BOOLEAN Set)
Set or unset the Mov to Debug Registers Exiting.
Definition Export.c:351
IMPORT_EXPORT_VMM VOID VmFuncSetSaveDebugControls(UINT32 CoreId, BOOLEAN Set)
Set SAVE DEBUG CONTROLS on Vm-exit controls.
Definition Export.c:165
IMPORT_EXPORT_VMM VOID VmFuncSetLoadDebugControls(UINT32 CoreId, BOOLEAN Set)
Set LOAD DEBUG CONTROLS on Vm-entry controls.
Definition Export.c:137
IMPORT_EXPORT_VMM VOID VmFuncSetExceptionBitmap(UINT32 CoreId, UINT32 IdtIndex)
Set exception bitmap in VMCS.
Definition Export.c:298
#define DEBUGGER_DEBUG_REGISTER_FOR_THREAD_MANAGEMENT
debug register to monitor thread changes
Definition Debugger.h:26
UINT64 CurrentThreadLocationOnGs
Definition State.h:55
BOOLEAN DebugRegisterInterceptionState
Definition State.h:56
UINT32 CoreId
Definition State.h:168
DEBUGGEE_PROCESS_OR_THREAD_TRACING_DETAILS ThreadOrProcessTracingDetails
Definition State.h:179

◆ ThreadDetectChangeByInterceptingClockInterrupts()

VOID ThreadDetectChangeByInterceptingClockInterrupts ( PROCESSOR_DEBUGGING_STATE * DbgState,
BOOLEAN Enable )

Enable or disable the thread change monitoring detection on the running core based on intercepting clock interrupts.

should be called on vmx root

Parameters
DbgStateThe state of the debugger on the current core
Enable
Returns
VOID
575{
576 if (Enable)
577 {
578 //
579 // We should get the clock interrupts
580 //
582
583 //
584 // Intercept external interrupts (for monitoring clock interrupts)
585 //
587 }
588 else
589 {
590 //
591 // We should ignore intercepting any further clock interrupts
592 //
594
595 //
596 // Undo intercepting external interrupts
597 //
599 }
600}
IMPORT_EXPORT_VMM VOID VmFuncSetExternalInterruptExiting(UINT32 CoreId, BOOLEAN Set)
Set the External Interrupt Exiting.
Definition Export.c:325
BOOLEAN InterceptClockInterruptsForThreadChange
Definition State.h:57

◆ ThreadEnableOrDisableThreadChangeMonitor()

VOID ThreadEnableOrDisableThreadChangeMonitor ( PROCESSOR_DEBUGGING_STATE * DbgState,
BOOLEAN Enable,
BOOLEAN IsSwitchByClockIntrrupt )

Enable or disable the thread change monitoring detection on the running core.

should be called on vmx root

Parameters
DbgStateThe state of the debugger on the current core
Enable
IsSwitchByClockIntrrupt
Returns
VOID
617{
618 if (Enable)
619 {
621 DbgState->ThreadOrProcessTracingDetails.InitialSetByClockInterrupt = IsSwitchByClockIntrrupt;
622 }
623 else
624 {
625 //
626 // Avoid future sets/unsets
627 //
630 }
631
632 //
633 // Check if it's a HW breakpoint on gs:[188] or a clock interception
634 //
635 if (!IsSwitchByClockIntrrupt)
636 {
638 }
639 else
640 {
642 }
643}
VOID ThreadDetectChangeByDebugRegisterOnGs(PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN Enable)
Enable or disable the thread change monitoring detection on the running core based on putting a HW br...
Definition Thread.c:424
VOID ThreadDetectChangeByInterceptingClockInterrupts(PROCESSOR_DEBUGGING_STATE *DbgState, BOOLEAN Enable)
Enable or disable the thread change monitoring detection on the running core based on intercepting cl...
Definition Thread.c:573
BOOLEAN InitialSetByClockInterrupt
Definition State.h:50
BOOLEAN InitialSetThreadChangeEvent
Definition State.h:48

◆ ThreadHandleThreadChange()

BOOLEAN ThreadHandleThreadChange ( PROCESSOR_DEBUGGING_STATE * DbgState)

handle thread changes

Parameters
DbgStateThe state of the debugger on the current core
Returns
BOOLEAN
23{
24 //
25 // Check if we reached to the target thread or not
26 //
27 if ((g_ThreadSwitch.ThreadId != NULL_ZERO && g_ThreadSwitch.ThreadId == HANDLE_TO_UINT32(PsGetCurrentThreadId())) ||
28 (g_ThreadSwitch.Thread != NULL64_ZERO && g_ThreadSwitch.Thread == PsGetCurrentThread()))
29 {
30 //
31 // Halt the debuggee, we have found the target thread
32 //
34
35 //
36 // Found
37 //
38 return TRUE;
39 }
40
41 //
42 // Not found
43 //
44 return FALSE;
45}
_Use_decl_annotations_ VOID KdHandleBreakpointAndDebugBreakpoints(PROCESSOR_DEBUGGING_STATE *DbgState, DEBUGGEE_PAUSING_REASON Reason, PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails)
Handle DBs and BPs for kernel debugger.
Definition Kd.c:1291
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
#define NULL_ZERO
Definition BasicTypes.h:110
#define NULL64_ZERO
Definition BasicTypes.h:111
@ DEBUGGEE_PAUSING_REASON_DEBUGGEE_THREAD_SWITCHED
Definition Connection.h:33
DEBUGGEE_REQUEST_TO_CHANGE_THREAD g_ThreadSwitch
Thread switch to ETHREAD or Thread ID.
Definition Global.h:121

◆ ThreadInterpretThread()

BOOLEAN ThreadInterpretThread ( PROCESSOR_DEBUGGING_STATE * DbgState,
PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET TidRequest )

change the current thread

Parameters
DbgStateThe state of the debugger on the current core
TidRequest
Returns
BOOLEAN
327{
328 switch (TidRequest->ActionType)
329 {
331
332 //
333 // Debugger wants to know current tid, nt!_ETHREAD and process name, etc.
334 //
335 TidRequest->ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
336 TidRequest->ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId());
337 TidRequest->Process = (UINT64)PsGetCurrentProcess();
338 TidRequest->Thread = (UINT64)PsGetCurrentThread();
339 MemoryMapperReadMemorySafe((UINT64)CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()), &TidRequest->ProcessName, 16);
340
341 //
342 // Operation was successful
343 //
345
346 break;
347
349
350 //
351 // Perform the thread switch
352 //
353 if (!ThreadSwitch(DbgState,
354 TidRequest->ThreadId,
355 (PETHREAD)TidRequest->Thread,
356 TidRequest->CheckByClockInterrupt))
357 {
359 break;
360 }
361
362 //
363 // Operation was successful
364 //
366
367 break;
368
370
371 //
372 // Show the threads list
373 //
374 if (!ThreadShowList(&TidRequest->ThreadListSymDetails,
376 NULL,
377 NULL,
378 (UINT64)NULL))
379 {
381 break;
382 }
383
384 //
385 // Operation was successful
386 //
388
389 break;
390
391 default:
392
393 //
394 // Invalid type of action
395 //
397
398 break;
399 }
400
401 //
402 // Check if the above operation contains error
403 //
404 if (TidRequest->Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
405 {
406 return TRUE;
407 }
408 else
409 {
410 return FALSE;
411 }
412}
BOOLEAN ThreadShowList(PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListSymbolInfo, DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTIONS QueryAction, UINT32 *CountOfThreads, PVOID ListSaveBuffer, UINT64 ListSaveBuffSize)
shows the threads list
Definition Thread.c:122
BOOLEAN ThreadSwitch(PROCESSOR_DEBUGGING_STATE *DbgState, UINT32 ThreadId, PETHREAD EThread, BOOLEAN CheckByClockInterrupt)
make evnvironment ready to change the thread
Definition Thread.c:58
#define DEBUGGER_ERROR_DETAILS_OR_SWITCH_THREAD_INVALID_PARAMETER
error, for thread switch or thread details, invalid parameter
Definition ErrorCodes.h:239
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
@ DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_LIST
Definition RequestStructures.h:1009
@ DEBUGGEE_DETAILS_AND_SWITCH_THREAD_PERFORM_SWITCH
Definition RequestStructures.h:1007
@ DEBUGGEE_DETAILS_AND_SWITCH_THREAD_GET_THREAD_DETAILS
Definition RequestStructures.h:1008
@ DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTION_SHOW_INSTANTLY
Definition RequestStructures.h:724
IMPORT_EXPORT_VMM BOOLEAN MemoryMapperReadMemorySafe(_In_ UINT64 VaAddressToRead, _Inout_ PVOID BufferToSaveMemory, _In_ SIZE_T SizeToRead)
PCHAR CommonGetProcessNameFromProcessControlBlock(PEPROCESS Eprocess)
Get process name by eprocess.
Definition Common.c:48
UCHAR ProcessName[16]
Definition RequestStructures.h:1025
DEBUGGEE_DETAILS_AND_SWITCH_THREAD_TYPE ActionType
Definition RequestStructures.h:1019
UINT64 Thread
Definition RequestStructures.h:1022
DEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListSymDetails
Definition RequestStructures.h:1026
UINT64 Process
Definition RequestStructures.h:1023
UINT32 ProcessId
Definition RequestStructures.h:1021
UINT32 ThreadId
Definition RequestStructures.h:1020
BOOLEAN CheckByClockInterrupt
Definition RequestStructures.h:1024
UINT32 Result
Definition RequestStructures.h:1027

◆ ThreadQueryCount()

BOOLEAN ThreadQueryCount ( PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest)

Query thread details (count).

Parameters
DebuggerUsermodeProcessOrThreadQueryRequest
Returns
BOOLEAN
654{
655 BOOLEAN Result = FALSE;
656
657 //
658 // Getting the count results
659 //
660 Result = ThreadShowList(&DebuggerUsermodeProcessOrThreadQueryRequest->ThreadListNeededDetails,
662 &DebuggerUsermodeProcessOrThreadQueryRequest->Count,
663 NULL,
664 (UINT64)NULL);
665
666 if (Result && DebuggerUsermodeProcessOrThreadQueryRequest->Count != 0)
667 {
668 DebuggerUsermodeProcessOrThreadQueryRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
669 return TRUE;
670 }
671
672 DebuggerUsermodeProcessOrThreadQueryRequest->Result = DEBUGGER_ERROR_UNABLE_TO_QUERY_COUNT_OF_PROCESSES_OR_THREADS;
673 return FALSE;
674}
UCHAR BOOLEAN
Definition BasicTypes.h:35
#define DEBUGGER_ERROR_UNABLE_TO_QUERY_COUNT_OF_PROCESSES_OR_THREADS
error, unable to query count of processes or threads
Definition ErrorCodes.h:386
@ DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTION_QUERY_COUNT
Definition RequestStructures.h:725
UINT32 Count
Definition RequestStructures.h:799
DEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListNeededDetails
Definition RequestStructures.h:796
UINT64 Result
Definition RequestStructures.h:800

◆ ThreadQueryDebugRegisterInterceptionStateByCoreId()

BOOLEAN ThreadQueryDebugRegisterInterceptionStateByCoreId ( UINT32 CoreId)

Query for deubg register interception state.

Parameters
CoreId
Returns
BOOLEAN whether it's activated or not
554{
555 BOOLEAN Result = FALSE;
556 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
557
559
560 return Result;
561}
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
struct _PROCESSOR_DEBUGGING_STATE PROCESSOR_DEBUGGING_STATE
Saves the debugger state.

◆ ThreadQueryDetails()

BOOLEAN ThreadQueryDetails ( PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET GetInformationThreadRequest)

Query thread details.

Parameters
GetInformationThreadRequest
Returns
BOOLEAN
713{
714 GetInformationThreadRequest->ProcessId = HANDLE_TO_UINT32(PsGetCurrentProcessId());
715 GetInformationThreadRequest->Process = (UINT64)PsGetCurrentProcess();
716 GetInformationThreadRequest->Thread = (UINT64)PsGetCurrentThread();
717 GetInformationThreadRequest->ThreadId = HANDLE_TO_UINT32(PsGetCurrentThreadId());
718
719 RtlCopyMemory(&GetInformationThreadRequest->ProcessName,
720 CommonGetProcessNameFromProcessControlBlock(PsGetCurrentProcess()),
721 15);
722
723 GetInformationThreadRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
724
725 return TRUE;
726}

◆ ThreadQueryList()

BOOLEAN ThreadQueryList ( PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest,
PVOID AddressToSaveDetail,
UINT32 BufferSize )

Query thread details (list).

Parameters
DebuggerUsermodeProcessOrThreadQueryRequest
AddressToSaveDetail
BufferSize
Returns
BOOLEAN
689{
690 BOOLEAN Result = FALSE;
691
692 //
693 // Getting the list of threads
694 //
695 Result = ThreadShowList(&DebuggerUsermodeProcessOrThreadQueryRequest->ThreadListNeededDetails,
697 NULL,
698 AddressToSaveDetail,
699 BufferSize);
700
701 return Result;
702}
@ DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTION_QUERY_SAVE_DETAILS
Definition RequestStructures.h:726

◆ ThreadShowList()

BOOLEAN ThreadShowList ( PDEBUGGEE_THREAD_LIST_NEEDED_DETAILS ThreadListSymbolInfo,
DEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS_ACTIONS QueryAction,
UINT32 * CountOfThreads,
PVOID ListSaveBuffer,
UINT64 ListSaveBuffSize )

shows the threads list

Parameters
ThreadListSymbolInfo
QueryAction
CountOfThreads
ListSaveBuffer
ListSaveBuffSize
Returns
BOOLEAN
127{
128 UINT64 ThreadListHead;
129 UINT32 EnumerationCount = 0;
130 UINT64 Thread = (UINT64)NULL;
131 LIST_ENTRY ThreadLinks = {0};
132 CLIENT_ID ThreadCid = {0};
133 UINT32 MaximumBufferCount = 0;
134 PDEBUGGEE_THREAD_LIST_DETAILS_ENTRY SavingEntries = ListSaveBuffer;
135
136 //
137 // validate parameters
138 //
140 CountOfThreads == NULL)
141 {
142 return FALSE;
143 }
144
146 (ListSaveBuffer == NULL || ListSaveBuffSize == 0))
147 {
148 return FALSE;
149 }
150
151 //
152 // compute size to avoid overflow
153 //
155 {
156 MaximumBufferCount = (UINT32)(ListSaveBuffSize / sizeof(DEBUGGEE_THREAD_LIST_DETAILS_ENTRY));
157 }
158
159 UINT32 ThreadListHeadOffset = ThreadListSymbolInfo->ThreadListHeadOffset; // nt!_EPROCESS.ThreadListHead
160 UINT32 ThreadListEntryOffset = ThreadListSymbolInfo->ThreadListEntryOffset; // nt!_ETHREAD.ThreadListEntry
161 UINT32 CidOffset = ThreadListSymbolInfo->CidOffset; // nt!_ETHREAD.Cid
162 UINT32 ActiveProcessLinksOffset = ThreadListSymbolInfo->ActiveProcessLinksOffset; // nt!_EPROCESS.ActiveProcessLinks
163 UINT64 PsActiveProcessHeadAddress = ThreadListSymbolInfo->PsActiveProcessHead; // nt!PsActiveProcessHead
164
165 //
166 // Validate params
167 //
168 if (ThreadListHeadOffset == NULL_ZERO ||
169 ThreadListEntryOffset == NULL_ZERO ||
170 CidOffset == NULL_ZERO ||
171 ActiveProcessLinksOffset == NULL_ZERO ||
172 PsActiveProcessHeadAddress == NULL64_ZERO)
173 {
174 return FALSE;
175 }
176
177 //
178 // Set the target process
179 //
180 if (ThreadListSymbolInfo->Process == NULL64_ZERO)
181 {
182 //
183 // Means that it's for the current process
184 //
185 ThreadListSymbolInfo->Process = (UINT64)PsGetCurrentProcess();
186 ThreadListHead = (UINT64)PsGetCurrentProcess() + ThreadListHeadOffset;
187 }
188 else
189 {
190 //
191 // Means that the user specified a special process
192 //
193 ThreadListHead = (UINT64)ThreadListSymbolInfo->Process + ThreadListHeadOffset;
194 }
195
196 //
197 // Check if the process's thread list head is valid or not
198 //
199 if (!CheckAccessValidityAndSafety(ThreadListHead, sizeof(BYTE)))
200 {
201 return FALSE;
202 }
203
204 //
205 // Check if the nt!_EPROCESS is valid or not (available in the system or not)
206 //
207 if (!ProcessCheckIfEprocessIsValid(ThreadListSymbolInfo->Process,
208 PsActiveProcessHeadAddress,
209 ActiveProcessLinksOffset))
210 {
211 return FALSE;
212 }
213
215 {
216 //
217 // Show the message of show the process
218 //
219 Log("PROCESS\t%llx\tIMAGE\t%s\n",
220 ThreadListSymbolInfo->Process,
221 CommonGetProcessNameFromProcessControlBlock((PEPROCESS)ThreadListSymbolInfo->Process));
222 }
223
224 //
225 // Show thread list, we read everything from the view of system process
226 //
227 MemoryMapperReadMemorySafe(ThreadListHead, &ThreadLinks, sizeof(ThreadLinks));
228
229 //
230 // Find the top of ETHREAD from nt!_ETHREAD.ThreadListEntry
231 //
232 Thread = (UINT64)ThreadLinks.Flink - ThreadListEntryOffset;
233
234 do
235 {
236 //
237 // Show thread list, we read everything from the view of system process
238 //
239 MemoryMapperReadMemorySafe(Thread + CidOffset,
240 &ThreadCid,
241 sizeof(ThreadCid));
242
243 switch (QueryAction)
244 {
246
247 //
248 // Show the list of process
249 //
250 Log("\tTHREAD\t%llx (%llx.%llx)\n", Thread, ThreadCid.UniqueProcess, ThreadCid.UniqueThread);
251
252 break;
253
255
256 EnumerationCount++;
257
258 break;
259
261
262 EnumerationCount++;
263
264 //
265 // Check to avoid overflow
266 //
267 if (EnumerationCount == MaximumBufferCount - 1)
268 {
269 //
270 // buffer is full
271 //
272 goto ReturnEnd;
273 }
274
275 //
276 // Save the details
277 //
278 SavingEntries[EnumerationCount - 1].Eprocess = ThreadListSymbolInfo->Process;
279 SavingEntries[EnumerationCount - 1].ProcessId = HANDLE_TO_UINT32(ThreadCid.UniqueProcess);
280 SavingEntries[EnumerationCount - 1].ThreadId = HANDLE_TO_UINT32(ThreadCid.UniqueThread);
281 SavingEntries[EnumerationCount - 1].Ethread = Thread;
282
284 &SavingEntries[EnumerationCount - 1].ImageFileName,
285 15);
286
287 break;
288
289 default:
290 break;
291 }
292
293 MemoryMapperReadMemorySafe(Thread + ThreadListEntryOffset,
294 &ThreadLinks,
295 sizeof(ThreadLinks));
296
297 //
298 // Find the next process from the list of this process
299 //
300 Thread = (UINT64)ThreadLinks.Flink - ThreadListEntryOffset;
301
302 } while ((UINT64)ThreadLinks.Flink != ThreadListHead);
303
304ReturnEnd:
305 //
306 // In case of query count of Threads, we'll set this parameter
307 //
309 {
310 *CountOfThreads = EnumerationCount;
311 }
312
313 return TRUE;
314}
BOOLEAN ProcessCheckIfEprocessIsValid(UINT64 Eprocess, UINT64 ActiveProcessHead, ULONG ActiveProcessLinksOffset)
checks whether the given nt!_EPROCESS is valid or not
Definition Process.c:264
unsigned char BYTE
Definition BasicTypes.h:40
unsigned int UINT32
Definition BasicTypes.h:54
struct _DEBUGGEE_THREAD_LIST_DETAILS_ENTRY DEBUGGEE_THREAD_LIST_DETAILS_ENTRY
The structure showing list of threads (details of each entry).
struct _DEBUGGEE_THREAD_LIST_DETAILS_ENTRY * PDEBUGGEE_THREAD_LIST_DETAILS_ENTRY
#define Log(format,...)
Log without any prefix.
Definition HyperDbgHyperLogIntrinsics.h:129
IMPORT_EXPORT_VMM BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:318
UINT64 Ethread
Definition RequestStructures.h:782
UINT32 ThreadId
Definition RequestStructures.h:784
UINT64 Eprocess
Definition RequestStructures.h:781
UINT32 ProcessId
Definition RequestStructures.h:783
UINT32 ThreadListHeadOffset
Definition RequestStructures.h:751
UINT32 CidOffset
Definition RequestStructures.h:753
UINT32 ThreadListEntryOffset
Definition RequestStructures.h:752
UINT64 PsActiveProcessHead
Definition RequestStructures.h:754
UINT64 Process
Definition RequestStructures.h:756
ULONG ActiveProcessLinksOffset
Definition RequestStructures.h:755

◆ ThreadSwitch()

BOOLEAN ThreadSwitch ( PROCESSOR_DEBUGGING_STATE * DbgState,
UINT32 ThreadId,
PETHREAD EThread,
BOOLEAN CheckByClockInterrupt )

make evnvironment ready to change the thread

Parameters
DbgStateThe state of the debugger on the current core
ThreadId
EThread
CheckByClockInterrupt
Returns
BOOLEAN
62{
63 //
64 // Initialized with NULL
65 //
67 g_ThreadSwitch.ThreadId = NULL_ZERO;
68
69 //
70 // Check to avoid invalid switch
71 //
72 if (ThreadId == NULL_ZERO && EThread == NULL64_ZERO)
73 {
74 return FALSE;
75 }
76
77 //
78 // Set the target thread id, ethread to switch
79 //
80 if (EThread != NULL)
81 {
82 if (CheckAccessValidityAndSafety((UINT64)EThread, sizeof(BYTE)))
83 {
84 g_ThreadSwitch.Thread = EThread;
85 }
86 else
87 {
88 //
89 // An invalid address is specified by user
90 //
91 return FALSE;
92 }
93 }
94 else if (ThreadId != NULL_ZERO)
95 {
96 g_ThreadSwitch.ThreadId = ThreadId;
97 }
98
99 //
100 // Send request for the target task to the halted cores (synchronized)
101 //
104 TRUE,
105 TRUE,
106 (PVOID)CheckByClockInterrupt);
107
108 return TRUE;
109}
BOOLEAN HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE *DbgState, UINT64 TargetTask, BOOLEAN LockAgainAfterTask, BOOLEAN Synchronize, PVOID Context)
Broadcast tasks to halted cores.
Definition HaltedCore.c:399
#define DEBUGGER_HALTED_CORE_TASK_SET_THREAD_INTERCEPTION
Halted core task for setting thread interception.
Definition HaltedCore.h:40
void * PVOID
Definition BasicTypes.h:56