1

Topic: Problem with obtaining backtrace system flows

All greetings! I need to receive backtrace all system flows in the driver. Went on a following way: 1. I enumerate all flows at System (PID=4) 2. I initialize APC and I put it in queue on handling (for each flow) 3. In APC I receive backtrace through RtlCaptureStackBackTrace (). 4. Well also I wait for end APC through KeWaitForSingleObject (). Peeped a method through APC here to whom it is interesting. There is a situation that there is a system flow to which I put in queue APC, but it is never executed also I  on KeWaitForSingleObject (). Schematically looks approximately so: NTSTATUS VOID CaptureStackBackTraceThreadSpecialApc (IN PRKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2) {PCAPTURE_BACKTRACE_THREAD_CONTEXT Context = *SystemArgument1;//__ debugbreak (); Context-> CapturedFrames = CaptureStackBackTrace (Context-> FramesToSkip, Context-> FramesToCapture, 0, Context-> BackTrace, &Context->BackTraceHash); if (! Context-> Local) KeSetEvent (&Context->CompletedEvent, 0, FALSE);//Here I signal} CaptureStackBackTraceThread (IN PETHREAD Thread, IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID *BackTrace, OUT PULONG CapturedFrames, OUT PULONG BackTraceHash) {...... Context. Local = FALSE; KeInitializeEvent (&Context.CompletedEvent, NotificationEvent, FALSE); KeInitializeApc (&Context.Apc, (PKTHREAD) Thread, OriginalApcEnvironment, CaptureStackBackTraceThreadSpecialApc, NULL, NULL, KernelMode, NULL); if (KeInsertQueueApc (&Context.Apc, &Context, NULL, 2)) {ntStatus = KeWaitForSingleObject (//I Hang up here &Context.CompletedEvent, Executive, KernelMode, FALSE, NULL);}......} When I hang up, I look in WinDBG inside KTHREAD and I see that KTHREAD-> ApcState-> KernelApcPending=1, ThreadState=5 (StateInitialized and StateRunning as I understand), but all hangs hopelessly. Looked also that all flows like Non-Alertable at the moment of KeInsertQueueApc (). Prompt, whether it is possible somehow more or less  methods to understand, what to a system flow to put APC it is not necessary, since it will not be fulfilled? I.e. to have possibility to eliminate such situations. Also I will in passing ask, there is also more or less transferable documentary method to receive backtrace system flows without APC? Though it would be desirable to leave the first method with APC.

2

Re: Problem with obtaining backtrace system flows

Hello, - prus - you wrote: P>... P> Prompt, whether it is possible somehow more or less  methods to understand, what to a system flow to put APC it is not necessary, since it will not be fulfilled? I.e. to have possibility to eliminate such situations. Critical Regions and Guarded Regions: A thread that is inside a critical region executes with user APCs and normal kernel APCs disabled. A thread inside a guarded region runs with all APCs disabled. We look the code KeEnterCriticalRegion/KeEnterGuardedRegion: 0:000> uf KeEnterCriticalRegion ntoskrnl! KeEnterCriticalRegion: 00000001 ` 400bbb00 65488b042588010000 mov rax, qword ptr gs: [188h] 00000001 ` 400bbb09 66ff88e4010000 dec word ptr [rax+1E4h] 00000001 ` 400bbb10 c3 ret 0:000> uf KeEnterGuardedRegion ntoskrnl! KeEnterGuardedRegion: 00000001 ` 400be2d0 65488b042588010000 mov rax, qword ptr gs: [188h] 00000001 ` 400be2d9 66ff88e6010000 dec word ptr [rax+1E6h] 00000001 ` 400be2e0 c3 ret That is to forbid the code to cause KeEnterCriticalRegion or KeEnterGuardedRegion without interception it is impossible. Hence, any check is not meaningful (race between time of check of a state and the beginning of execution APC).

3

Re: Problem with obtaining backtrace system flows

Hello, EreTIk, you wrote: ETI> That is to forbid the code to cause KeEnterCriticalRegion or KeEnterGuardedRegion without interception it is impossible. Hence, any check is not meaningful (race between time of check of a state and the beginning of execution APC). Yes, I already understood and  behavior KTHREAD-> SpecialApcDisable and KTHREAD-> KernelApcDisable. Just in my case at a flow it is watched: 1: kd> dt _KTHREAD 91FB5A40 nt! _KTHREAD... +0x13c KernelApcDisable: 0n0 +0x13e SpecialApcDisable: 0n-1... The Campaign the flow just also caused KeEnterGuardedRegion ()... And still more or less documentary method to receive backtrace a flow without APC is?

4

Re: Problem with obtaining backtrace system flows

Hello, - prus - you wrote: P> the Campaign the flow just also caused KeEnterGuardedRegion ()... P> And still more or less documentary method to receive backtrace a flow without APC is? At idea level: to look as it does a system debugger (kd), it will be possible possibility  the debug mechanism. If I do not confuse, the debugger is able to untwist stacks of threads, even at  characters. By the way, can try to be written off with wj32 (the author of a post on forum.sysinternals.com and ProcessHacker'), describing a problem.

5

Re: Problem with obtaining backtrace system flows

Hello, EreTIk, you wrote: ETI> At idea level: to look as it does a system debugger (kd), it will be possible possibility  the debug mechanism. If I do not confuse, the debugger is able to untwist stacks of threads, even at  characters. And it is possible here about it more in detail? How it is possible to look?

6

Re: Problem with obtaining backtrace system flows

Hello, - prus - you wrote: ETI>> At idea level: to look as it does a system debugger (kd), it will be possible possibility  the debug mechanism. If I do not confuse, the debugger is able to untwist stacks of threads, even at  characters. P> and it is possible here about it more in detail? How it is possible to look?  I mean something like PsActiveProcessHead from KdVersionBlock: How to find PsActiveProcessHead in memory on Windows. There is at me the strong suspicion that IDebugDataSpaces:: ReadDebuggerData reads from there: DEBUG_DATA_PsActiveProcessHeadAddr ULONG64 Returns the address of the kernel variable PsActiveProcessHead. DEBUG_DATA_OffsetKThreadKernelStack USHORT Returns the offset of the KernelStack field in the KTHREAD structure. This KdVersionBlock should be filled in  for correct operation of a debugger. Therefore I in the beginning would look as it receives and is filled LiveKD which successfully removes "mirror dump, which is a consistent view of kernel memory". Google is as LiveDump 1.0, which with source codes.