結論:
Dwm.exe進程初始化LdrInitializeThunk內部先映射dll,在一塊兒調用這些dll的dllmain,在調用user32的dllmain時,加載英偉達的nvinitx.dll這個模塊使用SHGetShellFolder,該函數使用了rpcrt4.dll中的一些數據,但是鎖相關數據還沒有被初始化(因為按調用順序先后還沒有調用到rpcrt4.dl它的dllmain)就使用,之后導致異常,出現死鎖情況。最終導致黑屏或者卡在系統歡迎界面。
分析的簡要過程:1.從卡時獲取的dump上看explorer卡在ConnectPort到dwm.exe的一個port。
2.查看dwm.exe中的線程,發現其中一個線程卡在調用SHGetShellFolder函數內部。這個卡之后就導致explorer.exe工作異常,一直卡在鏈接dwm.exe中的port。
3. 查看鎖sechost!SddlSidLookupCritical的狀態,發現此鎖被dwm.exe主線程占用,沒有釋放。 仔細分析發現主線程正常情況下不應該釋放不了這個臨界區。
4.猜測只可能出現什么異常導致沒有釋放這個臨界區。
(上雙機調試)調試發現dwm.exe的主線程中英偉達nvinitx.dll的dllmain會調用SHGetFoldPathW函數,這個函數調用的時候,已經占用了鎖SddlSidLookupCritical,這個時候在去調用RPCRT4.dll中相關函數,卻在調用EnterCriticalSection獲取rpcrt4的臨界區GlobalMutex出現異常,跳出到shell32中的異常處理函數_GSHandlerCheck_EH,這個時候導致沒有釋放SddlSidLookupCritical鎖,SHGetFoldPathW就返回了。查看了下異常,發現rpcrt4中的臨界區該臨界區GlobalMutex沒有初始化,dllmain 內部很多其它變量值也沒有初始化,可以確定是dllmain沒有被調用到。
5. ida分析可以知道GlobalMutex的初始化在rpcrt4.dll的dllmain內部 。所以可以知道出問題的原因就是rpcrt4.dll的dllmain沒有調用到,那么為什么會導致這個dllmain沒有調用掉呢?
6. 分析發現這個SHGetFoldPathW的調用是在nvinitx.dll的dllmain中。
ntdll!LdrpInitializeProcess函數先映射導入表中的dll在調用這些dll中的dllmain函數。
這個出問題環境調試發現rpcr4.dll中dllmain并沒有調用到,這個時候gdi32的dllmain函數內部調用loadlibrary加載nvinitx.dll,并調用nvinitx.dll的dllmain函數,但是這個時候調用LdrpLoadDll加載rpcr4.dll的時候,(之前剛映射,這個時候LdrpLoadDll發現rpcr4.dll已經被映射了,所以就不會調用這個rpcr4.dll的dllmain函數)
Loadlibrary調用LdrpLoadDll(這個函數先檢查模塊rpcr4.dll是否映射,發現已經映射就不會調用這個的dllmain,接下來調用其它函數使用臨界區GlobalMutex就出現異常崩潰)這個rpcr4.dll的dllmain會在接下來的ntdll!LdrpRunInitalizeroutines函數內部調用 。
7.更新了英偉達顯卡驅動372.54及372.70版本后,開機啟動過程中,經過上面一系列的異常調用,最終系統會被卡在歡迎界面或個別電腦出現黑屏的情況。
新聞熱點
疑難解答