TLS(线程句柄存储)
TLS表地址在数据目录项数组下标为9的位置
TLS结构体定义如下
typedef struct _IMAGE_TLS_DIRECTORY32
{
DWORD StartAddressOfRawData; // TLS初始化数据的起始地址
DWORD EndAddressOfRawData; // TLS初始化数据的结束地址 两个正好定位一个范围,范围放初始化的值
DWORD AddressOfIndex; // TLS索引的位置
DWORD AddressOfCallBacks; // Tls回调函数的数组指针
DWORD SizeOfZeroFill; // 填充 0的个数
union
{
DWORD Characteristics; // 保留
struct
{
DWORD Reserved0 : 20;
DWORD Alignment : 4;
DWORD Reserved1 : 8;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
} IMAGE_TLS_DIRECTORY32;
TLS有动态和静态使用的两种方式
- 动态方式是用三个api
TlsAlloc 分配空间
TlsSetValue 向空间放值
TlsGetValue 获取值
注意:动态线程局部存储是不会在PE文件中有tls节区的,主要给除了主线程之外的线程使用,各线程之间独享,一般用于存放线程专用信息(线程名字) - 静态方式就是用关键字__declspec(thread)生成带有TLS的PE文件,如下定义
//定义TLS变量
__declspec(thread) int g_nTest = 0x87654093; //主线程 TLS变量,只能给主线程使用
__declspec(thread) char g_szHello[] = "Hello";
//定义TLS回调函数
BOOL WINAPI TlsProc(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
MessageBox(NULL, "TlsProc", "Test", MB_OK);
}
return TRUE;
}
通过FS定位TLS中的数据
Fs[2c]指向一个指针数组,数组每个元素是一个指针,指针指向一片分配的内存
Fs[2c]-----指针-------内存空间(tls节区空间)
结构图如下