首页
社区
课程
招聘
[求助]关于LdrpLoaderLock锁的一个奇怪问题
发表于: 2016-7-1 10:42 7063

[求助]关于LdrpLoaderLock锁的一个奇怪问题

2016-7-1 10:42
7063
各位看雪前辈,最近遇到一个奇怪问题,希望各位走过路过给点思路,谢谢了!

事情是这样的:

我有一个DLL文件,在DllMain里面会开线程(当然不会去Wait它),这个线程里面会做一些事情,当调用一些API函数的时候,会导致Crash。后来分析这些Crash都是由于这些函数(GetModuleHandle、GetProcAddress)内部会去访问ntdll!LdrpLoaderLock这把锁导致。

附一下定义:
typedef struct _RTL_CRITICAL_SECTION
{
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;
    HANDLE LockSemaphore;
    ULONG_PTR SpinCount;
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;

具体访问就是调用RtlEnterCriticalSection获得锁和RtlLeaveCriticalSection释放锁。

在Enter或者Leave的时候,这个CRITICAL_SECTION的LockSemaphore值并非一个事件内核对象的句柄,所以抛出了STATUS_OBJECT_TYPE_MISMATCH的异常。

调试分析的时候,发现最开始LdrpLoaderLock的LockSemaphore成员确实是一个事件对象,但不知什么时候,这个事件对象被Close了,而其他某个线程CreateFile动作刚好返回了这个句柄值,所以我这边线程再访问这个锁的时候,抛出了上面说的类型不匹配的异常。因为原来的句柄值对应的是一个事件内核对象,现在这个句柄值对应的是一个文件类型对象了。

另外,这个现象是有概率出现的,差不多运行十次会出现一次。另外有时候没那么巧,句柄值没有被复用,这个时候这个句柄值就是无效的,返回的错误也就变成了STATUS_INVALID_HANDLE。

不知道大家有没有遇到过这个问题。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 3407
活跃值: (1242)
能力值: ( LV13,RANK:335 )
在线值:
发帖
回帖
粉丝
2
没有遇见过,确实很奇怪。
可以给一个复现代码吗??
一起研究下。。。
2016-7-1 11:28
0
雪    币: 3586
活跃值: (4729)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
理论上DllMain CreateThread就会死锁的...
2016-7-1 12:17
0
雪    币: 3407
活跃值: (1242)
能力值: ( LV13,RANK:335 )
在线值:
发帖
回帖
粉丝
4
没有这种事哈...
2016-7-1 14:17
0
雪    币: 23
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
检查一下你CreateThread函数有没有溢出
2016-7-1 14:18
0
雪    币: 2291
活跃值: (938)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
结帖:
原因找到了,创建线程使用的_beginthread,而错就错在,创建完线程后不应该去CloseHandle,CRT内部会自动Close。我去CloseHandle的后果就是这个句柄项被提前标记为闲置,随后其他模块触发到访问ntdll!LdrLoaderLock锁时,在一定几率下,内部的事件对象给Ring3分配的句柄值刚好就是原来给线程的Handle值。而CRT线程结束的时候(_endthread)又去Close这个它认为是自己线程句柄的东东,实际上这个已经变成了LdrLoaderLock的事件对象句柄。阴差阳错CLose错误。再后面释放这把锁的时候,这个句柄已经被关闭了。LdrLoaderLock里面的值天知道现在是哪个内核对象,所以抛各种异常了!
2016-7-1 17:14
0
游客
登录 | 注册 方可回帖
返回
//