云涯历险记

热爱可抵万难

云涯历险记

热爱可抵万难

恶意代码分析实战

恶意代码分析实战:第十六章 反调试技术

3 感染调试器功能

3.1 使用TLS回调

3.1.1 线程局部存储(TLS)

PE文件头可选映像头中数据目录表的第10成员IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]指向线程局部存储,英文简写”TLS”。

这个段里面保存了变量和回调函数的数据,但是TLS表本身的结构体一般存在于”.rdata”段内。

TLS中的变量:单独存在于每个独立的线程当中,每个线程中对该变量的操作都不会影响到其他线程中的TLS变量。

TLS中的回调函数:在程序入口点(AddressOfEntry)之前执行,也就是说程序在被调试时,还没有在入口点处断下来之前,TLS中的变量和回调函数就已经执行完了,所以TLS可以用作反调试之类的操作。

在IDA中使用ctrl+E 组合键查看回调函数,是TlsCallback。

数据结构如下:

typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD StartAddressOfRawData;               tls模板在内存中的起始VA,模板是用于创建线程时初始化TLS数据的;
    DWORD EndAddressOfRawData;                 tls模板在内存中的结束VA;
    PDWORD AddressOfIndex;                     存储TLS索引的位置
    PIMAGE_TLS_CALLBACK *AddressOfCallBacks;   指向TLS注册的回调函数的函数指针数组
    DWORD SizeOfZeroFill;                      用于指定非零初始化数据后面的空白空间的大小
    DWORD Characteristics;                     保留

} IMAGE_TLS_DIRECTORY32;