ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Windows10的DllMain中CreateThread并WaitforSingleObject造成死锁

2022-02-04 23:31:43  阅读:392  来源: 互联网

标签:CreateThread Windows10 DLL break 死锁 线程 printf NULL DllMain


本文分两种情况讨论,即在CreateThread之后是否调用WaitForSingleObject. 先看:
static DWORD WINAPI ThreadCreateInDllMain(LPVOID) {
    printf("ThreadCreateInDllMain start");
    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    printf("DllMain start.\n");
    HMODULE hMod = NULL;
    HANDLE hThread = NULL;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        printf("DLL_PROCESS_ATTACH\n");
        hThread = CreateThread(NULL, 0, ThreadCreateInDllMain, NULL, 0, NULL);
        WaitForSingleObject(hThread, INFINITE);
   
        break;
    case DLL_THREAD_ATTACH:
        printf("DLL_THREAD_ATTACH\n");
        break;
    case DLL_THREAD_DETACH:
        printf("DLL_THREAD_DETACH\n");
        break;
    case DLL_PROCESS_DETACH:
        printf("DLL_PROCESS_DETACH\n");

        break;
    }
    return TRUE;
}
我们看看这个NtWaitforSingleObject在等待什么(其实我们自己写的代码我们肯定知道是在等待一个线程对象):

 

 

查看句柄对应的详细信息:

 

 

等待3号线程:

 

 

我们看3号线程在干啥,3号线程也在等待(3号线程的等待是关键):

 

 

它在等待一个事件:

 

 

IDA看它等的是什么,它在等待LdrpWorkCompleteEvent事件:

 

 

设置这个Event的线程不是在等待,就是已经退出了。所以我们要找哪里能SetEvent(LdrpWorkCompleteEvent),找到是在LdrpProcessWork中:

 

 

我没有具体去追踪调用ZwSetEvent(LdrpWorkCompleteEvent)的调用关系,但是,总之,我们知道DllMain中的线程会负责ZwSetEvent(LdrpWorkCompleteEvent),但是它在等待线程完成,而线程又在等待DllMain的ZwSetEvent(LdrpWorkCompleteEvent),所以会死锁。     如果代码是这样,就不会死锁:

static DWORD WINAPI ThreadCreateInDllMain(LPVOID) {
    printf("ThreadCreateInDllMain start");
    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    printf("DllMain start.\n");
    HMODULE hMod = NULL;
    HANDLE hThread = NULL;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        printf("DLL_PROCESS_ATTACH\n");
        hThread = CreateThread(NULL, 0, ThreadCreateInDllMain, NULL, 0, NULL);
   
        break;
    case DLL_THREAD_ATTACH:
        printf("DLL_THREAD_ATTACH\n");
        break;
    case DLL_THREAD_DETACH:
        printf("DLL_THREAD_DETACH\n");
        break;
    case DLL_PROCESS_DETACH:
        printf("DLL_PROCESS_DETACH\n");

        break;
    }
    return TRUE;
}
我单步跟踪了LdrpDrainWorkQueue,即线程的NtWaitForsingleobject的调用者,如果DllMain中没有WaitForSingleObject的流程,LdrpDrainWorkQueue从这里就break掉了:

 

 

如果DllMain中有WaitForsingleobject,那么这里直接跳转:

 

 

跳转到这里等待:

 

 

其实LdrpDrainWorkQueue中会走到NtWaitforSingleObject进行等待的根本原因就在于上边判断了是否有WorkInProcess:

 

 

所以我们可以推断LdrpWorkInProgress表示是否还有DllMain在处理。创建线程的时候,如果还有DllMain没有执行完,那么会等待这个DllMain执行完才创建线程。而此时Thread在等待DllMain完,而DllMain又在等待Thread则必然死锁。

 

 

标签:CreateThread,Windows10,DLL,break,死锁,线程,printf,NULL,DllMain
来源: https://www.cnblogs.com/predator-wang/p/15863638.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有