调试实战 | 谁“锁”住了我的 SpaceSniffer?一次由 Shell 扩展引发的 Windows 死锁侦探之旅

摘要

在一次使用 SpaceSniffer 分析磁盘占用时,我遇到了一个非常容易复现的界面卡死问题。为查明原因,我首先通过 procdump 周期性保存完整转储文件,并使用 WinDbg 对调用栈进行对比分析,确认程序确实陷入阻塞而非假死。逐层追踪后,我最终将问题定位到第三方 Shell 扩展在 COM 激活过程中的异常阻塞,并由此引发死锁。

保存现场

遇到卡死问题,可以先使用 process explorer 观察一下线程运行情况,看看是假死,还是真的卡死了。还可以隔一段时间抓取一个转储文件,如果几次转储文件的调用栈都一样,大概率是真的卡死了。

procdump 有一个非常方便的功能,可以每隔一段时间自动保存转储文件,语法如下:

1
procdump.exe -ma -n 3 -s 5 SpaceSniffer.exe

以上命令可以每隔 5 秒(-s 5)为 SpaceSniffer.exe 保存一份完整-ma)转储文件,一共保存 3 次(-n 3)。效果如下:

save-dump-files-by-procdump

简单查看保存的三份转储文件,发现调用栈是一样的,大概率是真卡死了。用 windbg 打开其中一份转储文件,进行分析。

初步分析

执行 ~* kn 命令查看所有线程的调用栈。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
0:000> ~* kvn

. 0 Id: 2620.5e4 Suspend: 0 Teb: 00383000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0019bb38 764f2839 00000730 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 0019bbac 764f2792 00000730 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x99 (FPO: [SEH])
02 0019bbc0 76d5a11a 00000730 ffffffff 0019bc7c KERNELBASE!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
03 0019bc28 76d5a008 00000208 756d1cc0 00000000 SHCore!_CreateThreadWorker+0x10e (FPO: [Non-Fpo])
04 0019bc3c 756d20ee 756d2170 0019bc60 00000208 SHCore!SHCreateThread+0x18 (FPO: [Non-Fpo])
05 0019bc68 756d25f4 0019bc7c 752f79f0 00000000 windows_storage!GetItemHandlerCache+0x7e (FPO: [Non-Fpo])
06 0019bc94 756d1fa4 0019bcc0 00000000 00000000 windows_storage!SyncGetItemHandlerThreadProc+0x44 (FPO: [Non-Fpo])
07 0019bce8 75459c0f 00000000 7522d51c 7523651c windows_storage!GetHandlerFromCache+0xe3 (FPO: [Non-Fpo])
08 0019bdb0 752d9374 00000000 7522d5e4 00000000 windows_storage!CFileSysItemString::LoadHandler+0x15dbfe
09 0019c074 752d6a56 00948878 00948882 00000000 windows_storage!CFSFolder::_CreatePerInstanceDefExtIcon+0x96 (FPO: [Non-Fpo])
0a 0019c340 752d696e 00948878 00948882 00000000 windows_storage!CFSFolder::_CreateDefExtIcon+0xe4 (FPO: [Non-Fpo])
0b 0019c35c 752fba08 008b6e10 00000000 00000000 windows_storage!CFSFolder::s_GetExtractIcon+0x1e (FPO: [Non-Fpo])
0c 0019c63c 752d43ac 00000000 00000001 0019c66c windows_storage!CFSFolder::_BindHandler+0xcd8 (FPO: [Non-Fpo])
0d 0019c674 7544e680 008b6e6c 00948878 00000000 windows_storage!CFSFolder::GetThumbnailHandler+0x4c (FPO: [Non-Fpo])
0e 0019c6d4 752b351b 0778b88c 00948878 00000000 windows_storage!CRegFolder::GetThumbnailHandler+0x17a4b0
0f 0019c764 75344f04 078a63fc 00000000 752365ac windows_storage!_CreateThumbnailHandler+0x9b (FPO: [Non-Fpo])
10 0019ca34 752d5831 078a63fc 00000000 752365ac windows_storage!CShellItem::BindToHandler+0x864 (FPO: [Non-Fpo])
11 0019ca88 752d577f 00000002 0019caa8 0019cbb8 windows_storage!GetExtractIconW+0x73 (FPO: [Non-Fpo])
12 0019cad0 75291084 00000000 0019cb20 7fb7eb65 windows_storage!_GetILIndexFromItem+0x5d (FPO: [Non-Fpo])
13 0019cb70 752db5de 20000004 00000000 0019cbb8 windows_storage!CShellItem::_GetIcon+0x72 (FPO: [Non-Fpo])
14 0019cbec 7529427b 078a5800 00000000 00000000 windows_storage!CShellItem::GetSharedBitmap+0xfe (FPO: [Non-Fpo])
15 0019cc3c 76b0ea6a 078a5800 00000000 00000000 windows_storage!CShellItem::GetImage+0x6b (FPO: [Non-Fpo])
16 0019ccf8 76b0dbed 0093a1c8 00000007 76b0dba0 shell32!CIncludeInLibraryContextMenuHelper::_PopulateSubMenu+0x15e (FPO: [2,37,4])
17 0019cd1c 7673417b 07877568 008bbd70 00000002 shell32!CIncludeInLibraryContextMenuHelper::OnSetChanged+0x4d (FPO: [Non-Fpo])
18 0019cd74 76141c0b 000208d6 00000402 00000000 shell32!CShellFolderSet::s_WndProc+0x8b (FPO: [Non-Fpo])
19 0019cda0 761382ca 767340f0 000208d6 00000402 user32!_InternalCallWinProc+0x2b
1a 0019ce88 76137ee0 767340f0 00000000 00000402 user32!UserCallWinProcCheckWow+0x33a (FPO: [SEH])
1b 0019ceec 7613c3af 0112fe40 00000000 00000402 user32!DispatchClientMessage+0x190 (FPO: [Non-Fpo])
1c 0019cf28 77c356cd 0019cf44 00000020 0019d530 user32!__fnDWORD+0x3f (FPO: [Non-Fpo])
1d 0019cf60 7630174c 76130ae4 00000000 0000c2da ntdll!KiUserCallbackDispatcher+0x4d (FPO: [0,0,0])
1e 0019cf64 76130ae4 00000000 0000c2da 0000c2da win32u!NtUserCreateWindowEx+0xc (FPO: [17,0,0])
1f 0019d244 761303f7 00000000 56000000 80000000 user32!VerNtUserCreateWindowEx+0x229 (FPO: [Non-Fpo])
20 0019d32c 761302c8 00000000 56000000 80000000 user32!CreateWindowInternal+0x12b (FPO: [Non-Fpo])
21 0019d36c 69d2e92a 00000000 0000c2da 00000000 user32!CreateWindowExW+0x38 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
22 0019d3ac 69d5dc8e fffffffd 69dd583c 00000000 YunShellExtV1+0xae92a
23 0019d4f4 69d62663 00000001 0019d540 69d6766f YunShellExtV1+0xddc8e
24 0019d500 69d6766f 69c80000 00000001 00000000 YunShellExtV1!DllGetClassObject+0x63
25 0019d540 69d67741 69c80000 00000001 00000000 YunShellExtV1!DllUnregisterServer+0x4faf
26 0019d554 77c331a6 69c80000 00000001 00000000 YunShellExtV1!DllUnregisterServer+0x5081
27 0019d574 77c0e012 69d67725 69c80000 00000001 ntdll!LdrxCallInitRoutine+0x16
28 0019d5c0 77c11d43 00000001 00000000 eb259821 ntdll!LdrpCallInitRoutine+0x51 (FPO: [Non-Fpo])
29 0019d650 77c11eb1 0783d7f8 00000000 0019d70c ntdll!LdrpInitializeNode+0x135 (FPO: [Non-Fpo])
2a 0019d674 77c12785 0019d68f 0019d718 0019d70c ntdll!LdrpInitializeGraphRecurse+0x5d (FPO: [Non-Fpo])
2b 0019d690 77c0e542 eb2598a9 00002009 0019d8b0 ntdll!LdrpPrepareModuleForExecution+0x8f (FPO: [Non-Fpo])
2c 0019d6d8 77c0e186 00000600 00000004 00000000 ntdll!LdrpLoadDllInternal+0x11e (FPO: [SEH])
2d 0019d878 764f1de6 00002009 0019d8a0 0019d8b0 ntdll!LdrLoadDll+0xf6 (FPO: [Non-Fpo])
2e 0019d8bc 75efd18f 0019d990 00000000 00002008 KERNELBASE!LoadLibraryExW+0x156 (FPO: [Non-Fpo])
2f 0019d8e0 75efd118 00002008 0019d958 0019d990 combase!LoadLibraryWithLogging+0x1b (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\common\internal\loadfree.cxx @ 160]
30 0019d904 75efcf2d 0019d950 0019d954 0019d958 combase!CClassCache::CDllPathEntry::LoadDll+0x45 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\dllcache.cxx @ 2341]
31 0019d964 75efdf8a 0019d988 07792c10 00000000 combase!CClassCache::CDllPathEntry::Create+0x32 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\dllcache.cxx @ 2170]
32 0019dbbc 75eda06e 00000001 0019df90 0019dbfc combase!CClassCache::CClassEntry::CreateDllClassEntry+0xf3 (FPO: [Non-Fpo]) (CONV: thiscall) [onecore\com\combase\objact\dllcache.cxx @ 1103]
33 0019df14 75eab44c 0019df3c 75ee0cb0 0019e684 combase!CClassCache::GetClassObjectActivator+0x73e (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\dllcache.cxx @ 5398]
34 0019df48 75ea8c65 0019e684 75ea8b00 00000000 combase!CClassCache::GetClassObject+0x30 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\dllcache.cxx @ 5155]
35 (Inline) -------- -------- -------- -------- combase!CCGetClassObject+0x42 (Inline Function @ 75ea8c65) (CONV: stdcall) [onecore\com\combase\objact\dllcache.cxx @ 8366]
36 0019e038 75eb23b5 7605f168 00000000 0019e684 combase!CServerContextActivator::CreateInstance+0x165 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 856]
37 0019e084 75ea832f 0019e684 00000000 0019ed14 combase!ActivationPropertiesIn::DelegateCreateInstance+0xf5 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\actprops\actprops.cxx @ 1931]
38 0019e0e4 75ea7aba 7605f16c 00000000 0019e684 combase!CApartmentActivator::CreateInstance+0xbf (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 2189]
39 0019e110 75f40c55 7605f164 00000001 00000000 combase!CProcessActivator::CCICallback+0x5a (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 1645]
3a 0019e130 75f40b0d 7605f164 0019e4b0 00000000 combase!CProcessActivator::AttemptActivation+0x35 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 1527]
3b 0019e170 75f40a91 7605f164 0019e4b0 00000000 combase!CProcessActivator::ActivateByContext+0x6d (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 1393]
3c 0019e1a0 75eb237d 7605f164 00000000 0019e684 combase!CProcessActivator::CreateInstance+0x61 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 1271]
3d 0019e1ec 75eb2b5d 0019e684 00000000 0019ed14 combase!ActivationPropertiesIn::DelegateCreateInstance+0xbd (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\actprops\actprops.cxx @ 1931]
3e 0019e450 75eb2384 7605f160 00000000 0019e684 combase!CClientContextActivator::CreateInstance+0xfd (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actvator.cxx @ 570]
3f 0019e49c 75edbde2 0019e684 00000000 0019ed14 combase!ActivationPropertiesIn::DelegateCreateInstance+0xc4 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\actprops\actprops.cxx @ 1983]
40 0019efe0 75edb051 00000401 00000000 00000001 combase!ICoCreateInstanceEx+0xc12 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\objact.cxx @ 2032]
41 0019f0d4 75edadbe 00000401 00000000 00000001 combase!CComActivator::DoCreateInstance+0x231 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\immact.hxx @ 401]
42 (Inline) -------- -------- -------- -------- combase!CoCreateInstanceEx+0xa2 (Inline Function @ 75edadbe) (CONV: stdcall) [onecore\com\combase\objact\actapi.cxx @ 177]
43 0019f110 767730f0 07835f60 00000000 00000401 combase!CoCreateInstance+0xbe (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\objact\actapi.cxx @ 121]
44 0019f3b8 7677ebce 00000401 00000001 00000002 shell32!_SHCoCreateInstance+0x15e (FPO: [Non-Fpo])
45 0019f598 767a0f77 00000003 0787bcc4 0787bdc4 shell32!HDXA_QueryContextMenu+0x251 (FPO: [Non-Fpo])
46 0019f64c 00432b6e 0787bc38 07e108b7 00000000 shell32!CDefFolderMenu::QueryContextMenu+0x487 (FPO: [Non-Fpo])
47 0019f6b4 0043305f 03294260 00886b48 0c8b281c SpaceSniffer!Ntfs_sourceFinalize+0x262
48 0019f718 0042636b 03294260 074d8bfc 0c8b281c SpaceSniffer!Ntfs_sourceFinalize+0x753
49 0019f778 00423d62 031c8f50 0056b58c 031c8f50 SpaceSniffer!Frmstart_sourceFinalize+0x3953
4a 0019f7cc 004bd382 00000081 000002ae 00000010 SpaceSniffer!Frmstart_sourceFinalize+0x134a
4b 0019f7e8 0056b5d2 00000081 000002ae 0019f9f0 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x74ac6
4c 0019f808 004bd419 00000081 000002ae 00000204 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x122d16
4d 0019f82c 004bd5a2 00000000 031c8f50 0019f9f0 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x74b5d
4e 0019f96c 004c1685 000706c4 031c8f50 0091dd18 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x74ce6
4f 0019f9b8 004c0d23 0019f9cc 004c0d3b 0019f9e8 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x78dc9
50 0019f9e8 0051a9aa 00000204 00000002 008102ae SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x78467
51 0019fa00 76141c0b 000706c4 00000204 00000002 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0xd20ee
52 0019fa2c 761382ca 02cb097c 000706c4 00000204 user32!_InternalCallWinProc+0x2b
53 0019fb14 76136b70 02cb097c 00000000 00000204 user32!UserCallWinProcCheckWow+0x33a (FPO: [SEH])
54 0019fb90 761366a0 00000104 000706c4 0049e8c8 user32!DispatchMessageWorker+0x4c0 (FPO: [Non-Fpo])
55 0019fb9c 0049e8c8 0019fbc0 00190100 0019fc0c user32!DispatchMessageW+0x10 (FPO: [Non-Fpo])
56 0019fbb8 0049e90b 000706c4 00000204 00000002 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x5600c
57 0019fbdc 0049ec36 0019fbf0 0049ec40 0019fc0c SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x5604f
58 0019fc0c 0043ce2b 00000000 005ba048 00884354 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x5637a
59 0019ff38 005b4443 00400000 00000000 00884354 SpaceSniffer!showCommandLineHelp$qv+0x268b
5a 0019ff70 76fcfcc9 00380000 76fcfcb0 0019ffdc SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x16bb87
5b 0019ff80 77c282ae 00380000 eb25b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
5c 0019ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
5d 0019ffec 00000000 0040187c 00380000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

1 Id: 2620.13cc Suspend: 0 Teb: 0038f000 Unfrozen
# ChildEBP RetAddr Args to Child
00 02c6f38c 7650bc33 00000002 02c6f560 00000001 ntdll!NtWaitForMultipleObjects+0xc (FPO: [5,0,0])
01 02c6f520 7650bb18 00000002 02c6f560 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x103 (FPO: [SEH])
02 02c6f53c 73f9266e 00000002 02c6f560 00000000 KERNELBASE!WaitForMultipleObjects+0x18 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
03 02c6fa9c 73fa002a fb52e036 73f9fa10 73f9fa10 cpbgrd+0x1266e
04 02c6ff68 76fcfcc9 000002b0 76fcfcc9 000002b0 cpbgrd!X64Call+0xd79a
05 02c6ff80 77c282ae 000002b0 e9fab1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
06 02c6ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
07 02c6ffec 00000000 73f9fa10 000002b0 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

2 Id: 2620.1044 Suspend: 0 Teb: 00392000 Unfrozen
# ChildEBP RetAddr Args to Child
00 041afecc 764f2839 000002b0 00000000 041aff14 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 041aff40 764f2792 000002b0 000003e8 00000000 KERNELBASE!WaitForSingleObjectEx+0x99 (FPO: [SEH])
02 041aff54 73f95bd8 000002b0 000003e8 73f95b80 KERNELBASE!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
03 041aff70 76fcfcc9 000002b0 76fcfcb0 041affdc cpbgrd!X64Call+0x3348
04 041aff80 77c282ae 000002b0 ef26b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
05 041affdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
06 041affec 00000000 73f95b80 000002b0 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

3 Id: 2620.2bdc Suspend: 0 Teb: 00395000 Unfrozen
# ChildEBP RetAddr Args to Child
00 06d5fd94 77c1204e 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 06d5fdb8 77c0f9ae ede9b029 00000000 00000000 ntdll!LdrpDrainWorkQueue+0x14f (FPO: [Non-Fpo])
02 06d5fe58 77c2bd0c 0055a428 00000000 00000000 ntdll!LdrShutdownThread+0x7e (FPO: [SEH])
03 06d5ff34 0055a4f6 00000000 00000000 00518378 ntdll!RtlExitUserThread+0x4c (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
04 06d5ff5c 0055a452 06d5ffcc 00559f28 06d5ff70 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x111c3a
05 06d5ff70 76fcfcc9 03294250 76fcfcb0 06d5ffdc SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x111b96
06 06d5ff80 77c282ae 03294250 ede9b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
07 06d5ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
08 06d5ffec 00000000 0055a428 03294250 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

4 Id: 2620.3a34 Suspend: 0 Teb: 00398000 Unfrozen
# ChildEBP RetAddr Args to Child
00 06e9fe2c 76558b20 000003d4 00000000 00000000 ntdll!NtNotifyChangeDirectoryFileEx+0xc (FPO: [10,0,0])
01 06e9fe7c 76558b84 000003d4 0427eb80 00007fff KERNELBASE!ReadDirectoryChangesExW+0x100 (FPO: [Non-Fpo])
02 06e9fea8 0043dda8 000003d4 0427eb80 00007fff KERNELBASE!ReadDirectoryChangesW+0x24 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
03 06e9ff2c 00518319 06e9ff40 00518323 06e9ff5c SpaceSniffer!Snifthread_sourceFinalize+0x198
04 06e9ff5c 0055a452 06e9ffcc 00559f28 06e9ff70 SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0xcfa5d
05 06e9ff70 76fcfcc9 03294260 76fcfcb0 06e9ffdc SpaceSniffer!Unknownspacetreemapnode_sourceFinalize+0x111b96
06 06e9ff80 77c282ae 03294260 edd5b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
07 06e9ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
08 06e9ffec 00000000 0055a428 03294260 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

5 Id: 2620.2900 Suspend: 0 Teb: 003ad000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f29fb3c 7613934a 000208d6 00000402 00000000 win32u!NtUserMessageCall+0xc (FPO: [7,0,0])
01 0f29fba0 7613653f 0112fe40 00000000 0353c320 user32!SendMessageWorker+0x97a (FPO: [4,13,4])
02 0f29fc00 766fd52f 000208d6 00000402 00000000 user32!SendMessageW+0x6f (FPO: [Non-Fpo])
03 0f29fc74 767867d4 078a7f48 0789fa90 767866b0 shell32!CShellFolderSetEnumTask::InternalResumeRT+0xdf (FPO: [Non-Fpo])
04 0f29fc9c 752de338 078a7f48 00000000 008bd1d0 shell32!CRunnableTask::Run+0x124 (FPO: [Non-Fpo])
05 0f29fcb4 752ddf5c 0f29fcd0 00cedc98 008bd1d0 windows_storage!CShellTask::TT_Run+0x3d (FPO: [Non-Fpo])
06 0f29fcf8 752ddd1e 752ddce0 0789fb28 003adf60 windows_storage!CShellTaskThread::ThreadProc+0x9b (FPO: [Non-Fpo])
07 0f29fd20 76d5c4f9 008bd1d0 76d5c4e0 7ffe0386 windows_storage!CShellTaskThread::s_ThreadProc+0x3e (FPO: [Non-Fpo])
08 0f29fd34 77c29cc0 00cedc98 e415b3cd 008807c0 SHCore!ExecuteWorkItemThreadProc+0x19 (FPO: [Non-Fpo])
09 0f29fdbc 77bf612a 0f29fe9c 0789fb28 e415b101 ntdll!RtlpTpWorkCallback+0x120 (FPO: [SEH])
0a 0f29ff70 76fcfcc9 008807c0 76fcfcb0 0f29ffdc ntdll!TppWorkerThread+0x6ea (FPO: [SEH])
0b 0f29ff80 77c282ae 008807c0 e415b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
0c 0f29ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
0d 0f29ffec 00000000 77bf5a40 008807c0 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

6 Id: 2620.3840 Suspend: 0 Teb: 003b0000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f39fdb0 77bf5ce0 00000058 07840048 00000010 ntdll!NtWaitForWorkViaWorkerFactory+0xc (FPO: [5,0,0])
01 0f39ff70 76fcfcc9 008807c0 76fcfcb0 0f39ffdc ntdll!TppWorkerThread+0x2a0 (FPO: [Non-Fpo])
02 0f39ff80 77c282ae 008807c0 e405b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
03 0f39ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
04 0f39ffec 00000000 77bf5a40 008807c0 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

7 Id: 2620.584 Suspend: 0 Teb: 003b3000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f49ee98 7613d01a 00000001 0f49efe8 ffffffff win32u!NtUserMsgWaitForMultipleObjectsEx+0xc (FPO: [5,0,0])
01 0f49ef0c 7613cf4c 00000001 0f49efe8 ffffffff user32!RealMsgWaitForMultipleObjectsEx+0x7a (FPO: [Non-Fpo])
02 0f49ef2c 75eb51c2 00000001 0f49efe8 ffffffff user32!MsgWaitForMultipleObjectsEx+0x4c (FPO: [Non-Fpo])
03 0f49efac 75eb53a0 0f49efe8 00000001 0f49efd0 combase!CCliModalLoop::BlockFn+0x14b (FPO: [Non-Fpo]) (CONV: thiscall) [onecore\com\combase\dcomrem\callctrl.cxx @ 2156]
04 0f49eff4 75eb3718 75eb36d0 07841a98 078a2c00 combase!ModalLoop+0xa1 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\chancont.cxx @ 166]
05 0f49f010 75ecf229 0f49f4e8 0356f8f0 078a2c00 combase!ClassicSTAThreadDispatchCrossApartmentCall+0x48 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\chancont.cxx @ 319]
06 (Inline) -------- -------- -------- -------- combase!CSyncClientCall::SwitchAptAndDispatchCall+0xa5a (Inline Function @ 75ecf229) (CONV: thiscall) [onecore\com\combase\dcomrem\channelb.cxx @ 5856]
07 0f49f1f0 75eb40a8 0f49f4e8 0f49f4c4 0f49f4c4 combase!CSyncClientCall::SendReceive2+0xb49 (FPO: [Non-Fpo]) (CONV: thiscall) [onecore\com\combase\dcomrem\channelb.cxx @ 5459]
08 (Inline) -------- -------- -------- -------- combase!SyncClientCallRetryContext::SendReceiveWithRetry+0x29 (Inline Function @ 75eb40a8) (CONV: thiscall) [onecore\com\combase\dcomrem\callctrl.cxx @ 1542]
09 (Inline) -------- -------- -------- -------- combase!CSyncClientCall::SendReceiveInRetryContext+0x29 (Inline Function @ 75eb40a8) (CONV: thiscall) [onecore\com\combase\dcomrem\callctrl.cxx @ 565]
0a 0f49f2b4 75ed1638 078a2c00 0f49f4e8 0f49f4c4 combase!ClassicSTAThreadSendReceive+0x98 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\callctrl.cxx @ 547]
0b 0f49f4a0 75e9a1f8 0f49f4e8 0f49f4c4 0f49f4e8 combase!CSyncClientCall::SendReceive+0x538 (FPO: [Non-Fpo]) (CONV: thiscall) [onecore\com\combase\dcomrem\ctxchnl.cxx @ 722]
0c (Inline) -------- -------- -------- -------- combase!CClientChannel::SendReceive+0x79 (Inline Function @ 75e9a1f8) (CONV: stdcall) [onecore\com\combase\dcomrem\ctxchnl.cxx @ 655]
0d 0f49f4c8 770a60e3 00933784 0f49f53c f4410821 combase!NdrExtpProxySendReceive+0xc8 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\ndr\ndrole\proxy.cxx @ 1998]
0e 0f49f918 75f6ff80 75e2a860 75e4cad0 0f49f950 rpcrt4!NdrClientCall2+0x9e3 (FPO: [Non-Fpo])
0f 0f49f938 75f67f1f 0f49f950 00000009 0f49f9e4 combase!ObjectStublessClient+0x70 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\ndr\ndrole\i386\stblsclt.cxx @ 227]
10 0f49f948 75f00bb3 00933784 0f49f990 0357d700 combase!ObjectStubless+0xf [onecore\com\combase\ndr\ndrole\i386\stubless.asm @ 171]
11 0f49f9e4 75ea6161 035344c8 75f24e70 00000902 combase!CObjectContext::InternalContextCallback+0x273 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\context.cxx @ 4328]
12 0f49fa54 767a1859 7605f1e8 00000902 7669699c combase!CGIPTable::GetInterfaceFromGlobal+0x371 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\giptbl.cxx @ 1683]
13 0f49fa88 76ae136e 0f49faa0 0091a7f0 0787a3dc shell32!UnMarshalFromGIT+0x76 (FPO: [Non-Fpo])
14 0f49fab4 76ae09da 0787a3dc 00000000 0091a804 shell32!CSendToMenu::_IsDropTarget+0x8a (FPO: [Non-Fpo])
15 0f49fb10 76adff3e 0787a3dc 00000000 76adfef0 shell32!CSendToMenu::_AddSendToItem+0x2e (FPO: [Non-Fpo])
16 0f49fb30 7543e29b 0091a804 0783fe10 07834678 shell32!CSendToMenu::FoundItem+0x4e (FPO: [Non-Fpo])
17 0f49fb5c 752d2905 0783fe10 07834678 70e7db81 windows_storage!CNamespaceWalk::_AddItem+0x186471
18 0f49fb94 7566f0a2 0783fe10 00000000 00000000 windows_storage!CNamespaceWalk::_WalkFolder+0x8c (FPO: [Non-Fpo])
19 0f49fde8 7566f1a7 0783fbf0 07831410 00000000 windows_storage!CNamespaceWalk::_WalkFolderItem+0x180 (FPO: [4,141,4])
1a 0f49fe1c 7566f245 0783fbf0 07831410 00000000 windows_storage!CNamespaceWalk::_WalkIDList+0xa2 (FPO: [Non-Fpo])
1b 0f49fe4c 75447b54 0787a45c 00000001 70e7deb1 windows_storage!CNamespaceWalk::_WalkShellItem+0x76 (FPO: [Non-Fpo])
1c 0f49fea4 7566f660 0090f858 03570e8c 00000404 windows_storage!CNamespaceWalk::Walk+0x1755d4
1d 0f49feec 76d58e10 07835a28 76d58d50 76d58d50 windows_storage!CNamespaceWalk::s_AsyncWalkThreadProc+0xa0 (FPO: [Non-Fpo])
1e 0f49ff70 76fcfcc9 0019f198 76fcfcb0 0f49ffdc SHCore!_WrapperThreadProc+0xc0 (FPO: [Non-Fpo])
1f 0f49ff80 77c282ae 0019f198 e475b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
20 0f49ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
21 0f49ffec 00000000 76d58d50 0019f198 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

8 Id: 2620.2bd0 Suspend: 0 Teb: 003b6000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f5dfc54 7650bc33 00000002 0f5dfe20 00000001 ntdll!NtWaitForMultipleObjects+0xc (FPO: [5,0,0])
01 0f5dfde8 75eb3543 00000002 0f5dfe20 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x103 (FPO: [SEH])
02 0f5dff24 75eb33c7 0090fad8 00007530 00007530 combase!WaitCoalesced+0xb5 (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\published\comutils\coalescedwait.cxx @ 72]
03 0f5dff60 75ea33bf 75ea33a0 75ea33a0 0f5dff80 combase!CRpcThread::WorkerLoop+0xd6 (FPO: [Non-Fpo]) (CONV: thiscall) [onecore\com\combase\dcomrem\threads.cxx @ 329]
04 0f5dff70 76fcfcc9 0090fad8 76fcfcb0 0f5dffdc combase!CRpcThreadCache::RpcWorkerThreadEntry+0x1f (FPO: [Non-Fpo]) (CONV: stdcall) [onecore\com\combase\dcomrem\threads.cxx @ 77]
05 0f5dff80 77c282ae 0090fad8 e461b1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
06 0f5dffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
07 0f5dffec 00000000 75ea33a0 0090fad8 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

9 Id: 2620.1f14 Suspend: 0 Teb: 003b9000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f80fdac 77c1204e 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 0f80fdd0 77c0f9ae e4bcb001 00000000 76d3c650 ntdll!LdrpDrainWorkQueue+0x14f (FPO: [Non-Fpo])
02 0f80fe70 77c2bd0c 76d3c650 76d3c650 76d20000 ntdll!LdrShutdownThread+0x7e (FPO: [SEH])
03 0f80ff48 7651b694 00000000 76d3c650 00cedf18 ntdll!RtlExitUserThread+0x4c (FPO: [Non-Fpo])
04 0f80ff5c 76d3c66c 76d20000 00000000 76d20000 KERNELBASE!FreeLibraryAndExitThread+0x34 (FPO: [Non-Fpo])
05 0f80ff70 76fcfcc9 00cedf18 76fcfcb0 0f80ffdc SHCore!<lambda_19624ae0f12adae645db6df842454482>::<lambda_invoker_stdcall>+0x1c (FPO: [Non-Fpo])
06 0f80ff80 77c282ae 00cedf18 e4bcb1ad 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
07 0f80ffdc 77c2827e ffffffff 77c493c6 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
08 0f80ffec 00000000 76d3c650 00cedf18 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

10 Id: 2620.df8 Suspend: 0 Teb: 003bc000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0ff6fbf4 77c1204e 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 0ff6fc18 77c0ddc1 e4cab2dd 00380000 00000000 ntdll!LdrpDrainWorkQueue+0x14f (FPO: [Non-Fpo])
02 0ff6fcac 77c26c0b e4cab375 00000000 00000000 ntdll!LdrpInitializeThread+0x78 (FPO: [SEH])
03 0ff6fd04 77c26b31 00000000 00000000 00000000 ntdll!_LdrpInitialize+0x84 (FPO: [Non-Fpo])
04 0ff6fd10 00000000 0ff6fd24 77bc0000 00000000 ntdll!LdrInitializeThunk+0x11 (FPO: [Non-Fpo])

11 Id: 2620.393c Suspend: 0 Teb: 003bf000 Unfrozen
# ChildEBP RetAddr Args to Child
00 10cefbf4 77c1204e 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 10cefc18 77c0ddc1 fbf2b2dd 00380000 00000000 ntdll!LdrpDrainWorkQueue+0x14f (FPO: [Non-Fpo])
02 10cefcac 77c26c0b fbf2b375 00000000 00000000 ntdll!LdrpInitializeThread+0x78 (FPO: [SEH])
03 10cefd04 77c26b31 00000000 00000000 00000000 ntdll!_LdrpInitialize+0x84 (FPO: [Non-Fpo])
04 10cefd10 00000000 10cefd24 77bc0000 00000000 ntdll!LdrInitializeThunk+0x11 (FPO: [Non-Fpo])

12 Id: 2620.1894 Suspend: 0 Teb: 003c2000 Unfrozen
# ChildEBP RetAddr Args to Child
00 137cfbf4 77c1204e 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
01 137cfc18 77c0ddc1 f840b2dd 00380000 00000000 ntdll!LdrpDrainWorkQueue+0x14f (FPO: [Non-Fpo])
02 137cfcac 77c26c0b f840b375 00000000 00000000 ntdll!LdrpInitializeThread+0x78 (FPO: [SEH])
03 137cfd04 77c26b31 00000000 00000000 00000000 ntdll!_LdrpInitialize+0x84 (FPO: [Non-Fpo])
04 137cfd10 00000000 137cfd24 77bc0000 00000000 ntdll!LdrInitializeThunk+0x11 (FPO: [Non-Fpo])

可以看到底部的几个线程都在等待同一个句柄 0x7c,而且都是由 LdrpDrainWorkQueue() 发起的。由上篇文章——《调试实战 | DllMain 的陷阱:当 Windows 10 并行加载遇上线程等待引发的死锁》可知,这个句柄大概率是 ntdll!LdrpLoadCompleteEvent。在 windbg 中输入 dd ntdll!LdrpLoadCompleteEvent L1 可以查看其值,果然是 0x7c

1
2
0:000> dd ntdll!LdrpLoadCompleteEvent L1
77ce5cc8 0000007c

大概率又是一个加载器相关的死锁!这些线程中,1 号线程和 7 号线程的调用栈比较值得怀疑,尤其是 1 号线程。先来看看 1 号线程在等待什么?由以上输出可知,1 号线程调用 ntdll!NtWaitForSingleObject() 时的参数是 0x730。执行 !handle 00000730 f 查看句柄信息,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
0:000> !handle 00000730 f
Handle 00000730
Type Event
Attributes 0
GrantedAccess 0x1f0003:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState,ModifyState
HandleCount 2
PointerCount 65538
Name <none>
Object specific information
Event Type Auto Reset
Event is Waiting

看来 1 号线程在等待一个 Event,接着看一下 7 号线程在等待什么?7 号线程调用 win32u!NtUserMsgWaitForMultipleObjectsEx() 进入的等待.

1
2
3
7  Id: 2620.584 Suspend: 0 Teb: 003b3000 Unfrozen
# ChildEBP RetAddr Args to Child
00 0f49ee98 7613d01a 00000001 0f49efe8 ffffffff win32u!NtUserMsgWaitForMultipleObjectsEx+0xc (FPO: [5,0,0])

第一个参数是句柄数组数量,第二个参数是句柄数组。执行 dd 0f49efe8 L1 查看句柄值,然后再使用 !handle 命令查看句柄信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0:000> dd 0f49efe8 L1
0f49efe8 000005c4
0:000> !handle 000005c4 f
Handle 000005c4
Type Event
Attributes 0
GrantedAccess 0x1f0003:
Delete,ReadControl,WriteDac,WriteOwner,Synch
QueryState,ModifyState
HandleCount 2
PointerCount 65536
Name <none>
Object specific information
Event Type Auto Reset
Event is Waiting

也在等待一个 Event,但是由于 7 号线程调用的是 NtUserMsgWaitForMultipleObjectsEx(),所以有消息的时候也会被唤醒,重点关注 1 号线程。

细看调用栈

如果仔细查看 1 号线程的调用栈,可以发现 1 号线程的等待是在 ntdll!LdrpCallInitRoutine() 内部,我们知道 LdrpCallInitRoutine() 内部会调用每个模块的 DllMain(),在执行到 YunShellExtV1.dll 对应的 DllMain()(由于没有对应的调试符号,所以不能直接从调用栈看出来在调用 DllMain() 函数)时,其内部调用了 user32!CreateWindowExW() 创建窗口,又间接调用到了 SHCore!_CreateThreadWorker(),而 SHCore!_CreateThreadWorker() 内部又会调用 KernalBase!WaitForSingleObject() 来永久等待一个事件。相当于间接的在 DllMain() 中执行了等待操作!这是一个非常危险的信号。关键调用栈帧可以参考下图红色高亮部分。

view-callstack-of-thread-1

SHCore!_CreateThreadWorker() 内部在等待什么事件呢?只能从反汇编代码中找答案了。

查看反汇编

打开 32 位的 IDA,加载 32 位的 SHCore.dll,找到 CreateThreadWorker(),使用 F5 查看伪代码,如下(有删减):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
BOOL __fastcall CreateThreadWorker(LPCWSTR lpModuleName, int a2, int a3, int a4, _DWORD *a5)
{
int Parameter[12]; // [esp+28h] [ebp-30h] BYREF

if ( (a3 & 2) == 0 || (v11 = (void *)SHGetThreadRef((IUnknown **)&Parameter[5]), (int)v11 >= 0) )
{
Parameter[2] = (int)CreateEventW(0, 0, 0, 0); //<----
if ( Parameter[2] )
{
v7 = CreateThread(0, 0, WrapperThreadProc, Parameter, 0, &ThreadId); //<----
if ( v7 )
{
v24 = 0;
if ( !Parameter[1] || (v6 & 0x200) != 0 )
{
WaitForSingleObject((HANDLE)Parameter[2], 0xFFFFFFFF); //<----
}
else if ( (v6 & 0x40) != 0 )
{
pHandles = (HANDLE)Parameter[2];
CoWaitForMultipleHandles(8u, 0xFFFFFFFF, 1u, &pHandles, &dwindex);
}
else
{
SHWaitForThreadWithWakeMask((HANDLE)Parameter[2], 0xFFFFFFFF, 0x40u);
}
}
}
}
return v8 >= 0;
}

可以很明显的看到关键代码(带有 //<---- 注释的行)。先创建一个 Event,然后创建线程,把带 Event 的参数传递给新线程,最后再无限等待 Event。猜测新线程执行完必要的操作后,会触发事件。

看到这段逻辑,我立刻就知道了原因:当前可是在 DllMain() 里啊,如果执行不完,新线程没有机会得到执行,也就没办法触发事件,DllMain() 也就会永远的等下去。

没想到这么容易就破案了!捡了个大漏!

总结

  • DllMain() 中不要做危险操作!尤其不要做等待操作!

参考资料

BianChengNan wechat
扫描左侧二维码关注公众号,扫描右侧二维码加我个人微信:)
0%