PE文件解析-全局指针表与线程局部存储(TLS)

一、全局指针表

    PE文件头可选映像头中数据目录表的第9成员IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]指向全局指针。

    在x86与x64系列平台没有使用全局指针表,目前只应用于MIPS等平台上,多用于参数传递。

二、线程局部存储(TLS)

1.位置与简介

    PE文件头可选映像头中数据目录表的第10成员IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]指向线程局部存储,英文简写"TLS"。通常一个包含了TLS表的程序,它就会拥有".tls"段,这个段里面保存了变量和回调函数的数据,但是TLS表本身的结构体一般存在于".rdata"段内。

    TLS用来保存变量或回调函数。TLS中的变量单独存在于每个独立的线程当中,每个线程中对该变量的操作都不会影响到其他线程中的TLS变量。

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

    TLS变量的创建方法有两种方式,分别是动态方式和静态方式,动态方法会用到TlsAlloc、TlsFree、TlsSetValue、TlsGetValue这几个函数来操作变量,静态方法会用声明__declspec (thread) int xx = 1;这样的方式来创建。需要注意的是静态创建的TLS变量不能用于DLL动态库中。

2.数据结构

    线程局部存储(TLS)的数据结构体如下:

typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;
    DWORD   EndAddressOfRawData;
    PDWORD  AddressOfIndex;
    PIMAGE_TLS_CALLBACK *AddressOfCallBacks;
    DWORD   SizeOfZeroFill;
    DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32;

需要注意的是,这个结构体里的字段都是VA,也就是起始虚拟地址。

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

猜你喜欢

转载自blog.csdn.net/zhyulo/article/details/85926568