DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2
? ? ? ? 本文介紹使用Windbg去驗(yàn)證《DllMain中不當(dāng)操作導(dǎo)致死鎖問題的分析--導(dǎo)致DllMain中死鎖的關(guān)鍵隱藏因子》中的結(jié)論,調(diào)試對象是文中剛開始那個(gè)例子。(轉(zhuǎn)載請指明出于breaksoftware的csdn博客)
? ? ? ? 1 g 讓程序運(yùn)行起來
? ? ? ? 2 ctrl+break 中斷程序
? ? ? ? 3 ~ 查看線程數(shù)
? ? ? ? 其實(shí)該程序自己運(yùn)行起來的線程只有ID為0、TID為afc的線程。18c4線程是我們在windbg中輸入ctrl+break,導(dǎo)致windbg在我們調(diào)試的進(jìn)程中插入的一個(gè)中斷線程。以后我們看到是這個(gè)線程的操作,就可以忽略。
? ? ? ? 4 dd fs:[0] 尋找主線程TEB起始地址(7ffde000)
? ? ? 5 dt _TEB 7ffde000 查看主線程中PEB結(jié)構(gòu)指針(0x7ffdc000)
? ? ? ? 6 dt _PEB 0x7ffdc000 尋找LoaderLock的指針(0x7c99e0174)
? ? ? ? 7 ?dt_RTL_CRITICAL_SECTION 0x7c99e174 查看臨界區(qū)狀態(tài),我們看到看到LockCount值為-1,那么我們通過給它設(shè)置“寫”斷點(diǎn),從而在每次“關(guān)鍵”時(shí)刻予以監(jiān)控。
? ? ? ? 8?baw2 0x7c99e178 對LockCount設(shè)置寫斷點(diǎn)
? ? ? ? 9?g?
? ? ? ??10kb?我們看到線程號是1,即Windbg插入的線程導(dǎo)致的斷點(diǎn),我們忽略之(我們看到關(guān)閉線程時(shí)也會進(jìn)入臨界區(qū))
? ? ? ? 11 g
? ? ? ? 12 kb 同上,忽略之
? ? ? ? 13?g
? ? ? ? 14 kb 這次是主線程(0)觸發(fā)了斷點(diǎn),斷點(diǎn)原因是LdrLoadDll中要加鎖。
? ? ? ? 我們使用IDA反編譯LdrLoadDll,可以看到調(diào)用的位置
v4 = RtlDosApplyFileIsolationRedirection_Ustr(1, a3, &unk_7C99E214, &v11, &v14, &v17, 0, 0, 0);v5 = v4;if ( v4 >= 0 ){v9 = 1;}else{if ( v4 != -1072365560 )goto LABEL_6;}LdrLockLoaderLock(1, 0, &v10);ms_exc.disabled = 0;
? ? ? ? 15 g
? ? ? ? 16 kb 還是主線程(0)觸發(fā)了斷點(diǎn),原因是LdrLoadDll中調(diào)用了LdrpLoadDll,該函數(shù)中需要進(jìn)入臨界區(qū),這是第二次進(jìn)臨界區(qū)了。在《Best Practices for Creating DLLs》中有對這種現(xiàn)象允許的說明
The loader lock is recursive, which means that it can be acquired again by the same thread.
? ? ? ? 在LdrLoadDll中我們看到
LdrLockLoaderLock(1, 0, &v10);ms_exc.disabled = 0;if ( LdrpTopLevelDllBeingLoaded ){if ( ShowSnaps || LdrpShowRecursiveDllLoads || LdrpBreakOnRecursiveDllLoads ){DbgPrint("[%lx,%lx] LDR: Recursive DLL load\n");DbgPrint("[%lx,%lx] Previous DLL being loaded: \"%wZ\"\n");DbgPrint("[%lx,%lx] DLL being requested: \"%wZ\"\n");if ( LdrpCurrentDllInitializer )DbgPrint("[%lx,%lx] DLL whose initializer was currently running: \"%wZ\"\n");elseDbgPrint("[%lx,%lx] No DLL initializer was running\n");}}LdrpTopLevelDllBeingLoaded = v17;v6 = LdrpLoadDll(v9, a1, a2, v17, a4, 1);
? ? ? ? 在LdrpLoadDll中我們看到
? ? ? ? 17 g
? ? ? ? 18 kb 第三次進(jìn)入臨界區(qū)
? ? ? ? 19 g 主線程第一次退出臨界區(qū)
? ? ? ? 20 kb 主線程第四次進(jìn)入臨界區(qū)
? ? ? ? 21 g 主線程第二次退出臨界區(qū)
? ? ? ? 22?g 有線程要進(jìn)入臨界區(qū)
? ? ? ? 23 kb 這次是我們在代碼中啟動(dòng)的工作線程(1)要嘗試進(jìn)入臨界區(qū)
? ? ? ? 24?~ 查看線程 確定有兩個(gè)線程了
? ? ? ? 25?g?
? ? ? ? 26 kb?工作線程(1)要進(jìn)入臨界區(qū),可是它不會進(jìn)去的,因?yàn)樗鼤粧炱?/p>
? ? ? ? 27 g 死鎖了
? ? ? ? 28?control+break windbg要啟動(dòng)一個(gè)中斷線程,中斷線程觸發(fā)了斷點(diǎn)
? ? ? ? 29?~ 查看線程,ID為2的就是windbg插入的線程
? ? ? ?30?~0s 切換到主線程(0),發(fā)現(xiàn)主線程在內(nèi)核態(tài)中出不來了
? ? ? ? 31 kb 查看主線程調(diào)用堆棧,確實(shí)是在等工作線程結(jié)束
? ? ? ? 32 ~1s 切換到工作線程,發(fā)現(xiàn)它也在內(nèi)核態(tài)中出不來了
? ? ? ? 33 kb 查看工作線程調(diào)用堆棧
? ? ? ? 34?dt _RTL_CRITICAL_SECTION 0x7c99e174 ?查看臨界區(qū)所有權(quán),從線程TID中我們可以看到,臨界區(qū)的確是被主線程占著。
總結(jié)
以上是生活随笔為你收集整理的DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DllMain中不当操作导致死锁问题的分
- 下一篇: DllMain中不当操作导致死锁问题的分