Search This Blog

Monday 22 September 2014

WinDbg : Parsing Dispatcher Object Queues & the !exqueue Command Extension


WinDbg : Parsing Dispatcher Object Queues & the !exqueue Command Extension

Windows maintains several differ net work queues for different objects. Depending on the priority of the object it is pushed into the respective queue. The !exqueue command can be used to view the different queues and the threads which are part of it.

kd> !exqueue
**** Critical WorkQueue ( Threads: 6/512, Concurrency: 0/1 )
THREAD 83a379e8  Cid 0004.0018  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a37710  Cid 0004.001c  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a37438  Cid 0004.0020  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a37160  Cid 0004.0024  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a25020  Cid 0004.0028  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 84fedd48  Cid 0004.0750  Teb: 00000000 Win32Thread: 00000000 WAIT


**** Delayed WorkQueue ( Threads: 7/512, Concurrency: 0/1 )
THREAD 83a25d48  Cid 0004.002c  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a25a70  Cid 0004.0030  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a25798  Cid 0004.0034  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a254c0  Cid 0004.0038  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a26020  Cid 0004.003c  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a26d48  Cid 0004.0040  Teb: 00000000 Win32Thread: 00000000 WAIT
THREAD 83a26a70  Cid 0004.0044  Teb: 00000000 Win32Thread: 00000000 WAIT


**** HyperCritical WorkQueue ( Threads: 1/512, Concurrency: 0/1 )
THREAD 83a26798  Cid 0004.0048  Teb: 00000000 Win32Thread: 00000000 WAIT


To parse the list of waiting threads on an object, first find the queue type of object (it is easier with that, else use any process in your mind, but then those might not have waiters). 

In this example we are using _EPROCESS but the command !exqueue, shown above, will give a list of all executable queues, and also can be used to chose one such queue with multiple waiters.

NOTE : To run this experiment in a better fashion on process type objects, we should create a process and make another process open a handle on it and wait on it (WaitForSingleObject). An example is the Winlogon process which has multiple waiters if multiple sessions are running.

kd> !process 0 0 lsass.exe
PROCESS 848b0720  SessionId: 0  Cid: 0200    Peb: 7ffd8000  ParentCid: 018c
    DirBase: 1ee780e0  ObjectTable: 8781e0e8  HandleCount: 560.
    Image: lsass.exe

kd> dt nt!_EPROCESS 848b0720  Pcb.Header.
   +0x000 Pcb         : 
      +0x000 Header      : 
         +0x000 Type        : 0x3 ''
         +0x001 TimerControlFlags : 0 ''
         +0x001 Absolute    : 0y0
         +0x001 Coalescable : 0y0
         +0x001 KeepShifting : 0y0
         +0x001 EncodedTolerableDelay : 0y00000 (0)
         +0x001 Abandoned   : 0 ''
         +0x001 Signalling  : 0 ''
         +0x002 ThreadControlFlags : 0x26 '&'
         +0x002 CpuThrottled : 0y0
         +0x002 CycleProfiling : 0y1
         +0x002 CounterProfiling : 0y1
         +0x002 Reserved    : 0y00100 (0x4)
         +0x002 Hand        : 0x26 '&'
         +0x002 Size        : 0x26 '&'
         +0x003 TimerMiscFlags : 0 ''
         +0x003 Index       : 0y0
         +0x003 Processor   : 0y00000 (0)
         +0x003 Inserted    : 0y0
         +0x003 Expired     : 0y0
         +0x003 DebugActive : 0 ''
         +0x003 ActiveDR7   : 0y0
         +0x003 Instrumented : 0y0
         +0x003 Reserved2   : 0y0000
         +0x003 UmsScheduled : 0y0
         +0x003 UmsPrimary  : 0y0
         +0x003 DpcActive   : 0 ''
         +0x000 Lock        : 0n2490371
         +0x004 SignalState : 0n0
         +0x008 WaitListHead : _LIST_ENTRY [ 0x84fda4b0 - 0x83b39d20 ]

Now, the WaitListhead is actually of type KWAIT_BLOCK with the first element as LIST_ENTRY, so...

kd> dt nt!_KWAIT_BLOCK 0x84fda4b0 
   +0x000 WaitListEntry    : _LIST_ENTRY [ 0x83b39d20 - 0x848b0728 ]
   +0x008 Thread           : 0x84f9caf8 _KTHREAD
   +0x00c Object           : 0x848b0720 Void
   +0x010 NextWaitBlock    : 0x84fda4c8 _KWAIT_BLOCK
   +0x014 WaitKey          : 0x10
   +0x016 WaitType         : 0x1 ''
   +0x017 BlockState       : 0x2 ''

To parse the list of threads waiting, we use the inbuilt ability of the dt command to parse lists. To read more about this, please refer to this blog post.

kd> dt nt!_KWAIT_BLOCK 0x84fda4b0 -l WaitlistEntry.Flink -y Thread
WaitlistEntry.Flink at 0x84fda4b0
---------------------------------------------
   +0x000 WaitListEntry :  [ 0x83b39d20 - 0x848b0728 ]
   +0x008 Thread : 0x84f9caf8 _KTHREAD

WaitlistEntry.Flink at 0x83b39d20
---------------------------------------------
   +0x000 WaitListEntry :  [ 0x848b0728 - 0x84fda4b0 ]
   +0x008 Thread : 0x848e5430 _KTHREAD



No comments:

Post a Comment