首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

DllMain中不当操作导致死锁有关问题的分析-加载卸载DLL与DllMain死锁的关系

2012-11-14 
DllMain中不当操作导致死锁问题的分析--加载卸载DLL与DllMain死锁的关系前几篇文章一直没有在源码级证明:D

DllMain中不当操作导致死锁问题的分析--加载卸载DLL与DllMain死锁的关系

        前几篇文章一直没有在源码级证明:DllMain在收到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH时会进入临界区。这个论证非常重要,因为它是使其他线程不能进入临界区从而导致死锁的关键。我构造了在DLL被映射到进程地址空间的场景,请看死锁时加载DLL的线程的堆栈(转载请指明出于breaksoftware的csdn博客)

DllMain中不当操作导致死锁有关问题的分析-加载卸载DLL与DllMain死锁的关系

        如果仔细看过《DllMain中不当操作导致死锁问题的分析--导致DllMain中死锁的关键隐藏因子2》,应该得知第14步就是进入临界区的点。

DllMain中不当操作导致死锁有关问题的分析-加载卸载DLL与DllMain死锁的关系

        我们可以看到LdrLoadDll内部调用了LdrLockLoaderLock。LdrLockLoaderLock内部进入临界区,我们用IDA查看LdrLoadDll函数


        我们将关注FreeLibrary和LdrpCallInitRoutine之间的代码逻辑。我们用IDA查看LdrUnLoadDll

int __stdcall LdrUnloadDll(int a1){    ……        v73 = 0;    v70 = *(_DWORD *)(*MK_FP(__FS__, 24) + 48);    v71 = 0;    ms_exc.disabled = 0;    if ( !LdrpInLdrInit )        RtlEnterCriticalSection(&LdrpLoaderLock);    ++LdrpActiveUnloadCount;    if ( !LdrpShutdownInProgress )    {        if ( LdrpCheckForLoadedDllHandle(a1, (int)&v78) )        {            if ( *(_WORD *)(v78 + 56) != -1 )            {                ……                if ( (unsigned __int8)LdrpActiveUnloadCount <= 1u )                {                    ……                    v15 = (int *)LdrpUnloadHead;                    v77 = (int *)LdrpUnloadHead;                    while ( v15 != &LdrpUnloadHead )                    {                        ……                        LdrpCallInitRoutine((int (__stdcall *)(_DWORD, _DWORD, _DWORD))v20, *(_DWORD *)(v78 + 24), 0, 0);                        ……                        v15 = (int *)LdrpUnloadHead;                        v77 = (int *)LdrpUnloadHead;                        ms_exc.disabled = 0;                        v3 = 0;                    }                   ……                }            }        }        else        {            v71 = 0xC0000135u;        }    }    ms_exc.disabled = -1;    sub_7C937424();……    return v71;}int __cdecl sub_7C937424(){    int result; // eax@3    --LdrpActiveUnloadCount;    if ( !LdrpInLdrInit )        result = RtlLeaveCriticalSection(&LdrpLoaderLock);    return result;}
        我们看到LdrUnloadDll几乎所有操作都是在临界区执行的。

        以上两段从源码级证明了加载和卸载DLL导致的DllMain的调用(以及不调用)都是在临界区中完成的。




热点排行