本帖最后由 海南岛 于 2009-12-10 00:45 编辑
http://www.debugman.com/read.php?tid=4021
1. 分析并解决某安全产品的驱动程序在windows 7 上安装后,发生的启动时锁死系统的BUG
提供锁死时的DUMP文件,要求分析出详细的问题原因,并提供修补程序或方法。修补程序只能修改BUG,不能使该产品的功能或任何正常逻辑受到影响
DUMP文件下载:http://mdl.360safe.com/win7_DeadLock.7z
满分 :100分
*************************************************************************
下面来简单分析一下这道题。
*************************************************************************
主要原因是两个线程:
线程(855a6020)占用PERESOURCE(863b1800)两次,在等待另一个PERESOURCE(87e18180)
线程(862fcd48)占用PERESOURCE(87e18180)一次,在等待另一个PERESOURCE(863b1800)
导致死锁。
被锁死的线程855a6020还独占打开了nt!IopDriverLoadResource (0x83db3820),导致系统的问题。
************************************************************************************************
第一个线程分析:
1: kd> .thread 855a6020
Implicit thread is now 855a6020
1: kd> kvn 30
*** Stack trace for last set context - .thread/.cxr resets it
# ChildEBP RetAddr Args to Child
00 80785c68 83cbbb15 855a6020 00000000 83d76d20 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
01 80785ca0 83cba403 855a60e0 855a6020 863822d0 nt!KiSwapThread+0x266
02 80785cc8 83cb42cf 855a6020 855a60e0 00000015 nt!KiCommitThreadWait+0x1df
03 80785d44 83cec193 863822d0 0000001b 00000000 nt!KeWaitForSingleObject+0x393
04 80785d9c 83cb76ae 863822d0 863bb800 88f01338 nt!ExpWaitForResource+0x16f
05 80785de8 87e163f9 87e18180 00000001 83c197a0 nt!ExAcquireResourceExclusiveLite+0x1cf
06 80785e04 83c1992d 80000080 002a0028 88fa2918 klbg+0x53f9
07 80785e48 87e14cb5 863069f0 86306a50 863bb800 hal!KeReleaseQueuedSpinLock+0x2d
08 80785ec8 8439f9f0 80785f0c 863bc6b8 00000000 klbg+0x3cb5
09 80785ee0 843b31fe 80785f0c 843b6f3c 00000000 fltmgr!FltGetIrpName+0xc5c
0a 80785ef4 843b38b7 80785f0c 863bc6b8 863bc630 fltmgr!FltProcessFileLock+0x18b2
0b 80785f38 83c894bc 8637de30 863b13e8 863bc68c fltmgr!FltProcessFileLock+0x1f6b
0c 80785f50 83e8d62d cc22eec8 807860f8 00000000 nt!IofCallDriver+0x63
0d 80786028 83e6e1d7 862e7e20 875bb650 86309d20 nt!IopParseDevice+0xed7
0e 807860a4 83e9424d 00000000 807860f8 00000240 nt!ObpLookupObjectName+0x4fa
0f 80786104 83e8c5ab 807862b0 855bb650 8e044500 nt!ObOpenObjectByName+0x159
10 80786180 83ec3d99 807862f0 00100180 807862b0 nt!IopCreateFile+0x673
11 807861dc 843b5b62 807862f0 00100180 807862b0 nt!IoCreateFileEx+0x9e
12 80786268 843be866 8637eaa8 863bb3c0 807862f0 fltmgr!FltCreateFileEx2+0xba
13 807862d0 843bee92 863bb3c0 807862f0 00000000 fltmgr!FltOpenVolume+0x66
14 807862e8 8e06ba45 863bb3c0 80786340 80786354 fltmgr!FltQueryVolumeInformation+0x14
15 80786398 843b4bf5 807863b4 00000005 00000008 klif+0x36a45
16 807863cc 843b5417 863bb3c0 00000005 0442dd87 fltmgr!FltCompareInstanceAltitudes+0xe1
17 80786418 843b57d1 8637eaa8 863b13e8 00000005 fltmgr!FltCompareInstanceAltitudes+0x903
18 80786488 843b58d7 8637eaa8 863b13e8 00000005 fltmgr!FltCompareInstanceAltitudes+0xcbd
19 807864f4 843becde 8637eaa8 863b13e8 00000005 fltmgr!FltCompareInstanceAltitudes+0xdc3
1a 80786544 843b37f4 863b13e8 863b57d0 863b61c8 fltmgr!FltGetFileSystemType+0x436
1b 80786588 83c894bc 8637de30 863b13e8 863b6224 fltmgr!FltProcessFileLock+0x1ea8
1c 807865a0 83e8d62d cc22e898 80786748 00000000 nt!IofCallDriver+0x63
1d 80786678 83e6e1d7 862e7e20 855bb650 8630d200 nt!IopParseDevice+0xed7
1e 807866f4 83e9424d 00000000 80786748 00000240 nt!ObpLookupObjectName+0x4fa
1f 80786754 83e8c5ab 807868d4 855bb650 80786700 nt!ObOpenObjectByName+0x159
20 807867d0 83ec75ee 807868fc 00000020 807868d4 nt!IopCreateFile+0x673
21 80786818 83c9042a 807868fc 00000020 807868d4 nt!NtOpenFile+0x2a
22 80786818 83c8e7a1 807868fc 00000020 807868d4 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 80786838)
23 807868a8 83e115f7 807868fc 00000020 807868d4 nt!ZwOpenFile+0x11 (FPO: [6,0,0])
24 80786904 83e11411 80786b30 00000000 80786928 nt!MiCreateSectionForDriver+0x7f
25 8078692c 83e10de6 80786998 80786b30 00000000 nt!MiObtainSectionForDriver+0x96
26 807869a8 83df02c0 80786b30 00000000 00000000 nt!MmLoadSystemImage+0x1db
27 80786b9c 83ffe853 00000001 00000000 80786bd4 nt!IopLoadDriver+0x386
28 80786be8 83ffa87b 80813bc8 8080bd48 00000000 nt!IopInitializeSystemDrivers+0x163
29 80786c6c 83fffe6f 0080bd48 85523208 855a6020 nt!IoInitSystem+0x6de
2a 80786d48 83dd847c 80786d90 83e5b66d 8080bd48 nt!Phase1InitializationDiscard+0xce4
2b 80786d50 83e5b66d 8080bd48 cc22e370 00000000 nt!Phase1Initialization+0xd
2c 80786d90 83d0d0d9 83dd846f 8080bd48 00000000 nt!PspSystemThreadStartup+0x9e
2d 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19
可以看到#05在等待PERESOURCE(87e18180)。
下面看PERESOURCE(863b1800)在哪里被占用:
#1a 80786544 843b37f4 863b13e8 863b57d0 863b61c8 fltmgr!FltGetFileSystemType+0x436的第一个参数是863b13e8,这是一个线索,
1: kd> u fltmgr!FltpDoFilterNotificationForNewVolume l 12
fltmgr!FltpDoFilterNotificationForNewVolume:
843bebfe 6a1c push 1Ch
843bec00 6820ac3a84 push offset fltmgr!__safe_se_handler_table+0x7e0 (843aac20)
843bec05 e8e264feff call fltmgr!_SEH_prolog4 (843a50ec)
843bec0a 33ff xor edi,edi
843bec0c 897de0 mov dword ptr [ebp-20h],edi
843bec0f c645e700 mov byte ptr [ebp-19h],0
843bec13 897dd8 mov dword ptr [ebp-28h],edi
843bec16 8b4508 mov eax,dword ptr [ebp+8]
843bec19 8b582c mov ebx,dword ptr [eax+2Ch]
843bec1c 895dd4 mov dword ptr [ebp-2Ch],ebx
843bec1f 8b3578603a84 mov esi,dword ptr [fltmgr!_imp__KeEnterCriticalRegion (843a6078)]
843bec25 ffd6 call esi
843bec27 8b4508 mov eax,dword ptr [ebp+8] //eax等于第一个参数863b13e8
843bec2a 0518040000 add eax,418h //eax=863b1800,我们要找的东西
843bec2f 8945dc mov dword ptr [ebp-24h],eax
843bec32 6a01 push 1
843bec34 50 push eax
843bec35 ff1578613a84 call dword ptr [fltmgr!_imp__ExAcquireResourceExclusiveLite (843a6178)]
这里ERESOURCE(863b1800)被打开了,从函数入口过来,中间没有任何分支,接下去就走到了#19中的843becde,再走到#05的地方就死锁了。
第二次打开应该是在#0b的附近,具体分析略过。
************************************************************************************************
第二个线程分析:
1: kd> .thread 862fcd48
Implicit thread is now 862fcd48
1: kd> kvn 30
# ChildEBP RetAddr Args to Child
00 8d3682c8 83cbbb15 862fcd48 00000000 807c5120 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
01 8d368300 83cba403 862fce08 862fcd48 8637f580 nt!KiSwapThread+0x266
02 8d368328 83cb42cf 862fcd48 862fce08 00000015 nt!KiCommitThreadWait+0x1df
03 8d3683a4 83cec193 8637f580 0000001b 00000000 nt!KeWaitForSingleObject+0x393
04 8d3683fc 83cb76ae 8637f580 00000000 83c895bd nt!ExpWaitForResource+0x16f
05 8d368448 843bec3b 863b1800 00000001 090c3d0b nt!ExAcquireResourceExclusiveLite+0x1cf
06 8d368494 843b37f4 863b13e8 864545f8 864513a8 fltmgr!FltpDoFilterNotificationForNewVolume+0x3d (FPO: [Non-Fpo])
07 8d3684d8 83c894bc 8637de30 863b13e8 86451404 fltmgr!FltpCreate+0x206 (FPO: [Non-Fpo])
08 8d3684f0 83e8d62d c16c0b28 8d368698 00000000 nt!IofCallDriver+0x63
09 8d3685c8 83e6e1d7 862e7e20 855bb650 86419318 nt!IopParseDevice+0xed7
0a 8d368644 83e9424d 00000000 8d368698 00000240 nt!ObpLookupObjectName+0x4fa
0b 8d3686a4 83e8c5ab 8d368870 855bb650 00000700 nt!ObOpenObjectByName+0x159
0c 8d368720 83e97eb6 8d36885c 00100000 8d368870 nt!IopCreateFile+0x673
0d 8d36876c 83c9042a 8d36885c 00100000 8d368870 nt!NtCreateFile+0x34
0e 8d36876c 83c8decd 8d36885c 00100000 8d368870 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 8d3687a0)
0f 8d368810 87e14846 8d36885c 00100000 8d368870 nt!ZwCreateFile+0x11 (FPO: [11,0,0])
10 00000000 00000000 00000000 00000000 00000000 klbg+0x3846
1: kd> dds 8d368810
8d368810 00200203
8d368814 87e14846 klbg+0x3846
8d368818 8d36885c
8d36881c 00100000
8d368820 8d368870
8d368824 8d368868
8d368828 00000000
8d36882c 00000080
8d368830 00000000
8d368834 00000001
8d368838 00000000
8d36883c 00000000
8d368840 00000000
8d368844 88f0136d
8d368848 88f01338
8d36884c 88ee9440
8d368850 00000000
8d368854 88ee9440
8d368858 88ee9440
8d36885c 88f0136d
8d368860 0010000e
8d368864 88f9a270
8d368868 00000000
8d36886c 88f0136d
8d368870 00000018
8d368874 00000000
8d368878 8d368860
8d36887c 00000240
8d368880 00000000
8d368884 00000000
8d368888 87e16361 klbg+0x5361
8d36888c 8d3688a8
可以看到#05在等待ERESOURCE(863b1800)。
下面看ERESOURCE(87e18180)在哪里被占用:
看栈中第二个关键地址87e16361 klbg+0x5361是落在函数卡巴的函数87e162c0内
1: kd> u 87e162c0 l2e
klbg+0x52c0:
87e162c0 55 push ebp
87e162c1 8bec mov ebp,esp
87e162c3 83e4f8 and esp,0FFFFFFF8h
87e162c6 83ec40 sub esp,40h
87e162c9 53 push ebx
87e162ca 55 push ebp
87e162cb 56 push esi
87e162cc 57 push edi
87e162cd ff15b470e187 call dword ptr [klbg+0x60b4 (87e170b4)]
87e162d3 6a01 push 1
87e162d5 688081e187 push offset klbg+0x7180 (87e18180)
87e162da ff15b070e187 call dword ptr [klbg+0x60b0 (87e170b0)]
***这里是我们要找的地方:*(87e170b0)=83c8a6a8=nt!ExAcquireResourceSharedLite,ERESOURCE(87e18180)被打开了。***
87e162e0 8b356881e187 mov esi,dword ptr [klbg+0x7168 (87e18168)]
87e162e6 81fe6881e187 cmp esi,offset klbg+0x7168 (87e18168)
87e162ec 0f8458010000 je klbg+0x544a (87e1644a)
87e162f2 33db xor ebx,ebx
87e162f4 385e10 cmp byte ptr [esi+10h],bl
87e162f7 8b4625 mov eax,dword ptr [esi+25h]
87e162fa 8d7c3029 lea edi,[eax+esi+29h]
87e162fe 0f8538010000 jne klbg+0x543c (87e1643c)
87e16304 66391f cmp word ptr [edi],bx
87e16307 0f842f010000 je klbg+0x543c (87e1643c)
87e1630d 837e08ff cmp dword ptr [esi+8],0FFFFFFFFh
87e16311 0f8425010000 je klbg+0x543c (87e1643c)
87e16317 6867725442 push 42547267h
87e1631c 6800030000 push 300h
87e16321 6a01 push 1
87e16323 ff157470e187 call dword ptr [klbg+0x6074 (87e17074)]
87e16329 8be8 mov ebp,eax
87e1632b 3beb cmp ebp,ebx
87e1632d 0f8409010000 je klbg+0x543c (87e1643c)
87e16333 8b4e08 mov ecx,dword ptr [esi+8]
87e16336 6880010000 push 180h
87e1633b 55 push ebp
87e1633c 57 push edi
87e1633d 51 push ecx
87e1633e e80dffffff call klbg+0x5250 (87e16250)
87e16343 84c0 test al,al
87e16345 0f84e9000000 je klbg+0x5434 (87e16434)
87e1634b 55 push ebp
87e1634c 8d54241c lea edx,[esp+1Ch]
87e16350 52 push edx
87e16351 ff151471e187 call dword ptr [klbg+0x6114 (87e17114)]
87e16357 8d442418 lea eax,[esp+18h]
87e1635b 50 push eax
87e1635c e82fe4ffff call klbg+0x3790 (87e14790)
这里就走到了上一层栈的87e14846(klbg+0x3846)的函数入口点87e14790。
1: kd> u 87e14790 l43
可以看到卡巴的这个函数没有标准的函数头,导致上面的栈乱了,不过这不是什么大问题,继续看。
klbg+0x3790:
87e14790 83ec34 sub esp,34h
87e14793 53 push ebx
87e14794 55 push ebp
87e14795 56 push esi
87e14796 57 push edi
87e14797 8b7c2448 mov edi,dword ptr [esp+48h]
87e1479b 0fb707 movzx eax,word ptr [edi]
87e1479e 687a62504e push 4E50627Ah
87e147a3 83c002 add eax,2
87e147a6 50 push eax
87e147a7 6a01 push 1
87e147a9 33ed xor ebp,ebp
87e147ab 33db xor ebx,ebx
87e147ad ff157470e187 call dword ptr [klbg+0x6074 (87e17074)]
87e147b3 8bf0 mov esi,eax
87e147b5 3bf5 cmp esi,ebp
87e147b7 750c jne klbg+0x37c5 (87e147c5)
87e147b9 5f pop edi
87e147ba 5e pop esi
87e147bb 5d pop ebp
87e147bc 33c0 xor eax,eax
87e147be 5b pop ebx
87e147bf 83c434 add esp,34h
87e147c2 c20400 ret 4
87e147c5 0fb70f movzx ecx,word ptr [edi]
87e147c8 8b5704 mov edx,dword ptr [edi+4]
87e147cb 51 push ecx
87e147cc 52 push edx
87e147cd 56 push esi
87e147ce e8a31c0000 call klbg+0x5476 (87e16476)
87e147d3 0fb707 movzx eax,word ptr [edi]
87e147d6 d1e8 shr eax,1
87e147d8 6a5c push 5Ch
87e147da 56 push esi
87e147db 66892c46 mov word ptr [esi+eax*2],bp
87e147df ff154471e187 call dword ptr [klbg+0x6144 (87e17144)]
87e147e5 83c414 add esp,14h
87e147e8 3bc5 cmp eax,ebp
87e147ea 7404 je klbg+0x37f0 (87e147f0)
87e147ec 66896802 mov word ptr [eax+2],bp
87e147f0 56 push esi
87e147f1 8d4c2420 lea ecx,[esp+20h]
87e147f5 51 push ecx
87e147f6 ff151471e187 call dword ptr [klbg+0x6114 (87e17114)]
87e147fc 55 push ebp
87e147fd 55 push ebp
87e147fe 55 push ebp
87e147ff 6a01 push 1
87e14801 55 push ebp
87e14802 6880000000 push 80h
87e14807 55 push ebp
87e14808 8d442440 lea eax,[esp+40h]
87e1480c 50 push eax
87e1480d 8d4c244c lea ecx,[esp+4Ch]
87e14811 8d54243c lea edx,[esp+3Ch]
87e14815 51 push ecx
87e14816 89542458 mov dword ptr [esp+58h],edx
87e1481a 6800001000 push 100000h
87e1481f 8d542440 lea edx,[esp+40h]
87e14823 52 push edx
87e14824 c744245818000000 mov dword ptr [esp+58h],18h
87e1482c 896c245c mov dword ptr [esp+5Ch],ebp
87e14830 c744246440020000 mov dword ptr [esp+64h],240h
87e14838 896c2468 mov dword ptr [esp+68h],ebp
87e1483c 896c246c mov dword ptr [esp+6Ch],ebp
87e14840 ff15a070e187 call dword ptr [klbg+0x60a0 (87e170a0)]
87e14846 85c0 test eax,eax
这里的地址87e14846(klbg+0x3846)就可以接上面的栈#0f了,再到#05的地方就死锁了。
以上只是一个普通的bug,问题不是太复杂。 |