Taxonomy of Windows Threads (Part 1)

Dmitry Vostokov, 12th of March, 2010
http://www.dumpanalysis.org

What kinds of threads are in a typical Windows system? The usual answer is kernel and user space threads[4]. The former originate in the kernel space and the latter originate in the user space. User thread stack trace can span both spaces with separate stacks (we highlight kernel space stack trace addresses in red, user space stack trace addresses in blue and taxonomic features in bold green):

THREAD fffffa8003bf1bb0  Cid 0004.0008  Teb: 0000000000000000 Win32Thread: 0000000000000000 
GATEWAIT
Not impersonating
DeviceMap                 fffff88000007310
Owning Process            fffffa8003bf1040       Image:         System
Attached Process          N/A            Image:         N/A
Wait Start TickCount      18550          Ticks: 17 (0:00:00:00.265)
Context Switch Count      905             
UserTime                  00:00:00.000
KernelTime                00:00:01.076
Win32 Start Address nt!Phase1Initialization (0xfffff80001c5f060)
Stack Init fffffa60005afdb0 Current fffffa60005afa20
Base fffffa60005b0000 Limit fffffa60005aa000 Call 0
Priority 1 BasePriority 0 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`005afa60 fffff800`0187a6fa nt!KiSwapContext+0x7f
fffffa60`005afba0 fffff800`0189e43e nt!KiSwapThread+0x13a
fffffa60`005afc10 fffff800`018a9c70 nt!KeWaitForGate+0x14e
fffffa60`005afc80 fffff800`01c5f06e nt!MmZeroPageThread+0x160
fffffa60`005afd20 fffff800`01a82ec7 nt!Phase1Initialization+0xe
fffffa60`005afd50 fffff800`018b5616 nt!PspSystemThreadStartup+0x57
fffffa60`005afd80 00000000`00000000 nt!KiStartSystemThread+0x16

THREAD fffffa8003bb5060  Cid 01a4.0528  Teb: 000007fffffda000 Win32Thread: 0000000000000000 
WAIT: (WrQueue) UserMode Non-Alertable
    fffffa80052eba90  QueueObject
    fffffa8003bb5118  NotificationTimer
Not impersonating
DeviceMap                 fffff880080d8f30
Owning Process            fffffa80052d5370       Image:         svchost.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      15394          Ticks: 3173 (0:00:00:49.499)
Context Switch Count      65             
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address RPCRT4!ThreadStartRoutine (0x000007fefeb07780)
Stack Init fffffa6004a53db0 Current fffffa6004a537e0
Base fffffa6004a54000 Limit fffffa6004a4e000 Call 0
Priority 10 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`04a53820 fffff800`0187a6fa nt!KiSwapContext+0x7f
fffffa60`04a53960 fffff800`0187dba4 nt!KiSwapThread+0x13a
fffffa60`04a539d0 fffff800`01ada157 nt!KeRemoveQueueEx+0x4b4
fffffa60`04a53a80 fffff800`01ab012d nt!IoRemoveIoCompletion+0x47
fffffa60`04a53b00 fffff800`01877ef3 nt!NtRemoveIoCompletion+0x13d
fffffa60`04a53bb0 00000000`77476daa nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`04a53c20)
00000000`01b9f838 00000000`7731f65c ntdll!NtRemoveIoCompletion+0xa
00000000`01b9f840 000007fe`feb25d0d kernel32!GetQueuedCompletionStatus+0x48
00000000`01b9f8a0 000007fe`feb25b93 RPCRT4!COMMON_ProcessCalls+0x7d
00000000`01b9f930 000007fe`feb07769 RPCRT4!LOADABLE_TRANSPORT::ProcessIOEvents+0x133
00000000`01b9f9e0 000007fe`feb07714 RPCRT4!ProcessIOEventsWrapper+0x9
00000000`01b9fa10 000007fe`feb077a4 RPCRT4!BaseCachedThreadRoutine+0x94
00000000`01b9fa50 00000000`7731be3d RPCRT4!ThreadStartRoutine+0x24
00000000`01b9fa80 00000000`77456a51 kernel32!BaseThreadInitThunk+0xd
00000000`01b9fab0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

Other classification partitions threads into native platform and virtualized (WOW64):

THREAD fffffa800515b060  Cid 0af0.0b34  Teb: 000000007efd8000 Win32Thread: 0000000000000000 
WAIT: (UserRequest) UserMode Non-Alertable
    fffffa80051007d0  NotificationEvent
    fffffa800515b118  NotificationTimer
Not impersonating
DeviceMap                 fffff88008479c90
Owning Process            fffffa8005145820       Image:         reader_sl.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      18516          Ticks: 51 (0:00:00:00.795)
Context Switch Count      1883             
UserTime                  00:00:00.015
KernelTime                00:00:00.000
Win32 Start Address reader_sl (0x0000000000401390)
Stack Init fffffa6003da2db0 Current fffffa6003da2940
Base fffffa6003da3000 Limit fffffa6003d9d000 Call 0
Priority 8 BasePriority 7 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`03da2980 fffff800`0187a6fa nt!KiSwapContext+0x7f
fffffa60`03da2ac0 fffff800`0186f35b nt!KiSwapThread+0x13a
fffffa60`03da2b30 fffff800`01ad8628 nt!KeWaitForSingleObject+0x2cb
fffffa60`03da2bc0 fffff800`01877ef3 nt!NtWaitForSingleObject+0x98
fffffa60`03da2c20 00000000`75543d09 nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`03da2c20)
00000000`003bf118 00000000`75543b06 wow64cpu!CpupSyscallStub+0x9
00000000`003bf120 00000000`7555ab46 wow64cpu!Thunk0ArgReloadState+0x1a
00000000`003bf190 00000000`7555a14c wow64!RunCpuSimulation+0xa
00000000`003bf1c0 00000000`774a05a8 wow64!Wow64LdrpInitialize+0x4b4
00000000`003bf720 00000000`774568de ntdll! ?? ::FNODOBFM::`string'+0x20aa1
00000000`003bf7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

We can also partition threads into non-GUI and GUI (having a message loop):

THREAD fffffa800511c4d0  Cid 09ec.0a84  Teb: 000007fffffa0000 Win32Thread: fffff900c2950a20 
WAIT: (WrUserRequest) UserMode Non-Alertable
    fffffa8004e27a50  SynchronizationEvent
Not impersonating
DeviceMap                 fffff88008479c90
Owning Process            fffffa8004e22c10       Image:         explorer.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      9695           Ticks: 8872 (0:00:02:18.404)
Context Switch Count      14                 LargeStack
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address SHLWAPI!WrapperThreadProc (0x000007fefeee3eac)
Stack Init fffffa600516ddb0 Current fffffa600516d720
Base fffffa600516e000 Limit fffffa6005167000 Call 0
Priority 10 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`0516d760 fffff800`0187a6fa nt!KiSwapContext+0x7f
fffffa60`0516d8a0 fffff800`0186f35b nt!KiSwapThread+0x13a
fffffa60`0516d910 fffff960`0014c503 nt!KeWaitForSingleObject+0x2cb
fffffa60`0516d9a0 fffff960`0014c59a win32k!xxxRealSleepThread+0x25f
fffffa60`0516da40 fffff960`0014bfea win32k!xxxSleepThread+0x56
fffffa60`0516da70 fffff960`0014c0e9 win32k!xxxRealInternalGetMessage+0x72e
fffffa60`0516db50 fffff960`0014d589 win32k!xxxInternalGetMessage+0x35
fffffa60`0516db90 fffff800`01877ef3 win32k!NtUserGetMessage+0x79
fffffa60`0516dc20 00000000`7724d58a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`0516dc20)
00000000`042df7b8 00000000`7724d5be USER32!ZwUserGetMessage+0xa
00000000`042df7c0 00000000`ff556cf1 USER32!GetMessageW+0x34
00000000`042df7f0 000007fe`feee3f75 Explorer!CSoundWnd::s_ThreadProc+0x3b
00000000`042df850 00000000`7731be3d SHLWAPI!WrapperThreadProc+0x116
00000000`042df940 00000000`77456a51 kernel32!BaseThreadInitThunk+0xd
00000000`042df970 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

Some threads belong to different groups simultaneously, for example WOW64 and GUI:

THREAD fffffa800512cbb0  Cid 0af0.0af4  Teb: 000000007efdb000 Win32Thread: fffff900c0763b30 
WAIT: (WrUserRequest) UserMode Non-Alertable
    fffffa8005138bf0  SynchronizationEvent
Not impersonating
DeviceMap                 fffff88008479c90
Owning Process            fffffa8005145820       Image:         reader_sl.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      18560          Ticks: 7 (0:00:00:00.109)
Context Switch Count      664                 LargeStack
UserTime                  00:00:00.000
KernelTime                00:00:00.000
Win32 Start Address reader_sl (0x0000000000403e34)
Stack Init fffffa60039b7db0 Current fffffa60039b7720
Base fffffa60039b8000 Limit fffffa60039b0000 Call 0
Priority 10 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           Call Site
fffffa60`039b7760 fffff800`0187a6fa nt!KiSwapContext+0x7f
fffffa60`039b78a0 fffff800`0186f35b nt!KiSwapThread+0x13a
fffffa60`039b7910 fffff960`0014c503 nt!KeWaitForSingleObject+0x2cb
fffffa60`039b79a0 fffff960`0014c59a win32k!xxxRealSleepThread+0x25f
fffffa60`039b7a40 fffff960`0014bfea win32k!xxxSleepThread+0x56
fffffa60`039b7a70 fffff960`0014c0e9 win32k!xxxRealInternalGetMessage+0x72e
fffffa60`039b7b50 fffff960`0014d589 win32k!xxxInternalGetMessage+0x35
fffffa60`039b7b90 fffff800`01877ef3 win32k!NtUserGetMessage+0x79
fffffa60`039b7c20 00000000`7545a0ba nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffffa60`039b7c20)
00000000`0007e528 00000000`75443178 wow64win!ZwUserGetMessage+0xa
00000000`0007e530 00000000`7555a996 wow64win!whNtUserGetMessage+0x30
00000000`0007e590 00000000`75543688 wow64!Wow64SystemServiceEx+0xca
00000000`0007ee40 00000000`7555ab46 wow64cpu!ServiceNoTurbo+0x28
00000000`0007eed0 00000000`7555a14c wow64!RunCpuSimulation+0xa
00000000`0007ef00 00000000`7746bf9d wow64!Wow64LdrpInitialize+0x4b4
0000000`0007f460 00000000`7746bb9c ntdll!LdrpInitializeProcess+0x1568
00000000`0007f720 00000000`774568de ntdll! ?? ::FNODOBFM::`string'+0x20959
00000000`0007f7d0 00000000`00000000 ntdll!LdrInitializeThunk+0xe

We can double check that the thread has the real message loop by showing its x86 stack trace:

0: kd> .process /r /p fffffa8005145820
Implicit process is now fffffa80`05145820
Loading User Symbols

0: kd> .load wow64exts

0: kd> .thread /w fffffa800512cbb0
Implicit thread is now fffffa80`0512cbb0
The context is partially valid. Only x86 user-mode context is available.
x86 context set

0: kd:x86> .reload
Loading Kernel Symbols
Loading User Symbols
Loading unloaded module list
Loading Wow64 Symbols

0: kd:x86> k
  *** Stack trace for last set context - .thread/.cxr resets it
ChildEBP          RetAddr           
0017fe8c 77185c7c USER32!NtUserGetMessage+0x15
0017feb0 004017e0 USER32!GetMessageA+0xa2
WARNING: Stack unwind information not available. Following frames may be wrong.
0017fef8 00403cb3 reader_sl+0x17e0
0017ff88 7602eccb reader_sl+0x3cb3
0017ff94 7766d24d kernel32!BaseThreadInitThunk+0xe
0017ffd4 7766d45f ntdll_775f0000!__RtlUserThreadStart+0x23
0017ffec 00000000 ntdll_775f0000!_RtlUserThreadStart+0x1b

We continue our taxonomic efforts in the next issue.

[4] In this part we confine our inverstigation to x64 Windows Server 2008 R2.