首页
论坛
课程
招聘
[原创]dll注入死锁问题的探究
2020-5-22 11:32 4494

[原创]dll注入死锁问题的探究

2020-5-22 11:32
4494

                                                                                                   Dll注入死锁问题的探究

   Dll注入的方法很多,可以参考https://bbs.pediy.com/thread-253918.htmhttps://bbs.pediy.com/thread-75887.htm这里不再说明。

笔者是在进程里创建一条线程,线程里调用LdrLoadDll函数加载的dll。代码在附件里,采用的是内核注入,适应windows7、win10所有版本,应用层注入原理也一样。

注入成功后会弹出对话框:

                                    


   但注入时有时候会卡死,被注入进程和我是注入的dll界面显示不出来。

上调试器,我是往计算器(calc.exe)里注入一个名为Test.dll的dll。!Process 0 0遍历所有进程后,记录下calc.exe的Eprocess。


                                            

使用.process /i 命令切换到计算器进程

                                            

使用!process fffffa80039aeb30 7观察计算器进程详细信息。

                



发现计算器有两个线程,两个线程最后一个栈帧符号没有显示出来。于是加载应用层符号:


再敲入命令 !process fffffa80039aeb30 7



  于是应用层符号显示出来了。

  观察两条线程,都调用了ntdll!RtlEnterCriticalSection进入nt!KeWaitForSingleObject进行等待。

  分别观察两个线程调用RtlpWaitOnCriticalSection的第四个参数,是个锁对象:

                                                   

第一个锁对象0x76f07490的OwningThread是0xce4,也就是这个锁的拥有者是0xce4号线程。

第二个锁对象0x76c43520 的OwningThread是0x744,也就是这个锁的拥有者是0x744号线程。

0xce4、0x744是calc.exe的两条线程。可能是发生了死锁,继续分析。

我们在wrk和Reactos中分别搜素上图中的LdrpLoaderLock、gcsUserApiHook。

                                  


    LdrpLoadDll中对LdrpLoaderLock上了锁,而LdrpLoadDll又是LdrLoadDll调用的。再看gcsUserApiHook的引用:

                                

InitUserApiHook中对gcsUserApiHook上了锁。

我们知道进行注入dll时,会在calc.exe开一条线程(0xce4线程)去调用LdrLoadDll,此时上了LdrpLoaderLock锁。观察0xce4线程的栈,Test!DllMain调用了一些函数后到USER32!InitUserApiHook,此时上了gcsUserApiHook锁。

0x744号线程时calc.exe进程的界面线程,从calc!WinMain调用到USER32!InitUserApiHook上了gcsUserApiHook,接着调用LdrpLoadDll上了LdrpLoaderLock锁。我们可以看一下LdrLoadDll的第四个参数,加载了什么dll:

                                          

  原来是在加载C:\Windows\system32\UxTheme.dll。

 

这显然是死锁了。

我们再来看下Test.dll的源代码:


           


        

0xce4号线程的调用流程一样,DllMain调用了MessageBox弹窗。至此死锁分析完毕。

死锁的原因是由于DllMain中直接调用了窗体有关的函数,解决方法是在DllMain中开一条线程去调用窗体有关的函数。如下:

                                       

        

  这样DllMain中就不会调用窗口函数从而上gcsUserApiHook锁。


  



【看雪培训】《Adroid高级研修班》2022年春季班招生中!

最后于 2020-5-22 11:42 被yirucandy编辑 ,原因:
上传的附件:
收藏
点赞4
打赏
分享
最新回复 (1)
雪    币: 3217
活跃值: 活跃值 (164)
能力值: (RANK:20 )
在线值:
发帖
回帖
粉丝
blowfish 活跃值 2020-6-4 10:09
2
1
分析得很好

DllMain(或者严格点说,在DLL_PROCESS_ATTACH/DLL_PROCESS_DETACH的执行路径中)中很多操作/API是不能执行的,非常容易出现交叉加锁导致死锁,因为此时持有loader锁。

交叉加锁的情况:

线程1:
在DllMain中,所以此时已经持有loader锁;
请求某个别的锁(比如调用某个COM API而去请求COM锁);

线程2:
持有某个锁(比如COM锁)
请求loader锁(因为执行了LoadLibrary/GetProcAddress/GetModuleHandle等API去加载/释放COM DLL,这些API内部会请求loader锁)
游客
登录 | 注册 方可回帖
返回