首页
社区
课程
招聘
[转帖]坑灰未冷山东乱,loader原来不读书
发表于: 2009-12-8 16:36 8747

[转帖]坑灰未冷山东乱,loader原来不读书

2009-12-8 16:36
8747
自己转自己的

http://www.team509.com/modules.php?name=News&file=article&sid=80

谢谢7楼的兄弟帮我写注!

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

收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
2
没懂啥意思呢。。。
看来我还是需要继续努力
2009-12-8 17:40
0
雪    币: 1491
活跃值: (985)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
3
看完了。。
还是不懂
继续努力ing
2009-12-8 17:43
0
雪    币: 213
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
支持一个 呵呵
2009-12-8 18:30
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
5
支持,很好的内容。
LZ的文档和测试程序,我本地一份吧
IDA和DumpBin等工具在检测Tls Callback函数时存在的一个问题,及解决方案

详见http://www.team509.com/loader.rar
上传的附件:
2009-12-8 18:34
0
雪    币: 203
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
team509的高手啊
2009-12-8 18:59
0
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
7
应该说楼主言简意赅,一语说出了关键所在:
系统对PE文件的Loader在检测是否有TLS Callback存在并调用函数时,读取记录TLS的IMAGE_DATA_DIRECTORY结构,从其VirtualAddress成员中得到IMAGE_TLS_DIRECTORY结构的偏移(加上基址变成指针),但并未检测其Size成员。因此即使此处Size成员置0,依然可以读取并调用TLS Callback函数。

但IDA、DumpBin等工具在检测TLS Callback时,则检测了相应IMAGE_DATA_DIRECTORY结构的Size成员

因此,当编写者有意将相应IMAGE_DATA_DIRECTORY结构的Size成员置0时,IDA和DumpBin等工具将认为这个TLS Callback无效,然而PE的Loader却不检测Size成员而依然认为其有效并正常执行TLS Callback,从而导致IDA等对此TLS Callback的误判。


接下来我验证一下楼主所提到的内容。

PE的Loader对TLS Callback的读取和调用在ntdll!LdrpCallTlsInitializers

.text:7C948578
.text:7C948578 ; *************** S U B R O U T I N E ***************************************
.text:7C948578
.text:7C948578 ; Attributes: bp-based frame
.text:7C948578
.text:7C948578 ; int __stdcall LdrpCallTlsInitializers(int ImageBase,int InitTls)
.text:7C948578 __stdcall LdrpCallTlsInitializers(x, x) proc near
.text:7C948578 ; CODE XREF: LdrpInitializeThread(x)+EDCDp
.text:7C948578 ; LdrShutdownThread()+16941p
.text:7C948578 ; LdrpRunInitializeRoutines(x)+13FDFp
.text:7C948578 ; LdrShutdownThread()+2231Cp
.text:7C948578 ; LdrpInitializeThread(x)+1AD39p
.text:7C948578 ; LdrpRunInitializeRoutines(x)+19B86p ...
.text:7C948578
.text:7C948578 pSize= dword ptr -28h
.text:7C948578 AddressOfCallBacks= dword ptr -20h
.text:7C948578 CallBackFunction= dword ptr -1Ch
.text:7C948578 ms_exc = CPPEH_RECORD ptr -18h
.text:7C948578 ImageBase = dword ptr 8
.text:7C948578 InitTls = dword ptr 0Ch
.text:7C948578
.text:7C948578 push 18h
.text:7C94857A push offset dword_7C9485D0
.text:7C94857F call __SEH_prolog
.text:7C94857F
.text:7C948584 lea eax, [ebp+pSize]
.text:7C948587 push eax
.text:7C948588 push IMAGE_DIRECTORY_ENTRY_TLS
.text:7C94858A push 1
.text:7C94858C mov edi, [ebp+ImageBase]
.text:7C94858F push edi
.text:7C948590 call RtlImageDirectoryEntryToData(x,x,x,x) ; 取IMAGE_TLS_DIRECTORY结构指针
.text:7C948590
.text:7C948595 xor ebx, ebx
.text:7C948597 mov [ebp+ms_exc.disabled], ebx
.text:7C94859A cmp eax, ebx ; 非0即为成功,下面读取其中的AddressOfCallBacks数组,循环调用其中的每个CallBack函数。注意这里没有检查相应的DataDirectory中的Size。
.text:7C94859C jz short loc_7C9485BE
.text:7C94859C
.text:7C94859E mov esi, [eax+IMAGE_TLS_DIRECTORY.AddressOfCallBacks]
.text:7C9485A1 mov [ebp+AddressOfCallBacks], esi
.text:7C9485A4 cmp esi, ebx
.text:7C9485A6 jz short loc_7C9485BE
.text:7C9485A6
.text:7C9485A8 cmp _ShowSnaps, bl
.text:7C9485AE jnz loc_7C95CA9E
.text:7C9485AE
.text:7C9485B4
.text:7C9485B4 loc_7C9485B4: ; CODE XREF: LdrpGenericExceptionFilter(x,x)+4589j
.text:7C9485B4 ; LdrpGenericExceptionFilter(x,x)+45BBj
.text:7C9485B4 mov eax, [esi]
.text:7C9485B6 cmp eax, ebx
.text:7C9485B8 jnz loc_7C95CAB3
.text:7C9485B8
.text:7C9485BE
.text:7C9485BE loc_7C9485BE: ; CODE XREF: LdrpCallTlsInitializers(x,x)+24j
.text:7C9485BE ; LdrpCallTlsInitializers(x,x)+2Ej
.text:7C9485BE ; LdrpGenericExceptionFilter(x,x)+4614j
.text:7C9485BE or [ebp+ms_exc.disabled], 0FFFFFFFFh
.text:7C9485C2 call __SEH_epilog
.text:7C9485C2
.text:7C9485C7 retn 8
.text:7C9485C7
.text:7C9485C7 __stdcall LdrpCallTlsInitializers(x, x) endp
.text:7C9485C7
.text:7C9485C7 ; ---------------------------------------------------------------------------

.text:7C95CA9E ; ---------------------------------------------------------------------------
.text:7C95CA9E
.text:7C95CA9E loc_7C95CA9E: ; CODE XREF: LdrpCallTlsInitializers(x,x)+36j
.text:7C95CA9E push esi
.text:7C95CA9F push eax
.text:7C95CAA0 push edi
.text:7C95CAA1 push offset s_LdrTlsCallbac ; "LDR: Tls Callbacks Found. Imagebase %p "...
.text:7C95CAA6 call _DbgPrint
.text:7C95CAA6
.text:7C95CAAB add esp, 10h
.text:7C95CAAE jmp loc_7C9485B4
.text:7C95CAAE
.text:7C95CAB3 ; ---------------------------------------------------------------------------
.text:7C95CAB3
.text:7C95CAB3 loc_7C95CAB3: ; CODE XREF: LdrpCallTlsInitializers(x,x)+40j
.text:7C95CAB3 mov [ebp-1Ch], eax
.text:7C95CAB6 add esi, 4
.text:7C95CAB9 mov [ebp+AddressOfCallBacks], esi
.text:7C95CABC cmp _ShowSnaps, bl
.text:7C95CAC2 jz short loc_7C95CAD3
.text:7C95CAC2
.text:7C95CAC4 push eax
.text:7C95CAC5 push edi
.text:7C95CAC6 push offset s_LdrCallingTls ; "LDR: Calling Tls Callback Imagebase %p "...
.text:7C95CACB call _DbgPrint
.text:7C95CACB
.text:7C95CAD0 add esp, 0Ch
.text:7C95CAD0
.text:7C95CAD3
.text:7C95CAD3 loc_7C95CAD3: ; CODE XREF: LdrpGenericExceptionFilter(x,x)+459Dj
.text:7C95CAD3 push ebx ; Reserved
.text:7C95CAD4 push dword ptr [ebp+0Ch] ; Reason
.text:7C95CAD7 push edi ; ImageBase
.text:7C95CAD8 push dword ptr [ebp-1Ch] ; CallBackFunction
.text:7C95CADB call LdrpCallInitRoutine(x,x,x,x)
.text:7C95CADB
.text:7C95CAE0 jmp loc_7C9485B4
.text:7C95CAE0
.text:7C95CAE0 ; ---------------------------------------------------------------------------

可以看到,在调用RtlImageDirectoryEntryToData得到TLS对应的IMAGE_TLS_DIRECTORY结构的指针后,并没有检查相应IMAGE_DATA_DIRECTORY结构的Size成员(其实RtlImageDirectoryEntryToData除了返回结构指针外,IMAGE_DATA_DIRECTORY结构的Size成员同样写入最后一个参数提供的地址中返回给调用者了,但是这里没有检查这个值)就直接查找IMAGE_TLS_DIRECTORY结构中的函数指针并循环调用了。
2009-12-8 18:59
0
雪    币: 8331
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
厉害。学习。
2009-12-28 13:36
0
游客
登录 | 注册 方可回帖
返回
//