能力值:
(RANK:860 )
|
-
-
2 楼
没懂啥意思呢。。。
看来我还是需要继续努力
|
能力值:
(RANK:860 )
|
-
-
3 楼
看完了。。
还是不懂
继续努力ing
|
能力值:
( LV3,RANK:20 )
|
-
-
4 楼
支持一个 呵呵
|
能力值:
( LV15,RANK:670 )
|
-
-
5 楼
支持,很好的内容。
LZ的文档和测试程序,我本地一份吧
IDA和DumpBin等工具在检测Tls Callback函数时存在的一个问题,及解决方案
详见http://www.team509.com/loader.rar
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
team509的高手啊
|
能力值:
( 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结构中的函数指针并循环调用了。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
厉害。学习。
|
|
|