TLS是Thread Local Storage的縮寫,線程局部存儲,主要是爲了解決多線程中的變量同步的問題html
進程中的全局變量與函數內定義的靜態(static)變量,是各個線程均可以訪問的共享變量。在一個線程修改的內存內容,對全部的線程都生效。這是一個優勢也是一個缺點,優勢是交換數據快,缺點是多個數據訪問共享數據,須要昂貴的同步開銷,也容易形成同步相關的BUG數組
若是須要在一個線程內部的各個函數調用都能訪問、但其它線程不能訪問的變量(被稱爲static memory local to a thread 線程局部靜態變量),就須要新的機制TLS來處理。安全
當線程A去修改TLS變量的時候,TLS變量不會有影響,每一個人都有一個TLS變量的副本,互不影響。多線程
_declspec(thread) int g_number = 100;
https://www.cnblogs.com/Sna1lGo/p/14466889.html函數
TLS在安全領域中,常被用來處理如反調試、搶佔執行等操做spa
1 首先加上編譯選項線程
#pragma comment(linker,"/INCLUDE:__tls used")調試
2htm
/*
註冊TLS函數 .CRT$XLX的做用
CRT表示使用C Runtime機制
X表示表示名隨機
L表示TLS Callback section
X也能夠換成B~Y任意一個字符
*/
#pragma data_seg(".CRT$XLX")
//存儲回調函數地址
PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[]= {TLS_CALLBACK1,0};
//這個數組纔是TLS的關鍵
#pragma data_seg()
void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
}
當一個程序被調用的時候,先執行TLS函數後,再跳轉到程序的IMAGEBASE執行PE文件結構。blog
能夠在TLS函數中添加代碼來防止程序被調試
也是可選pe頭的數據目錄表下面的一個內容,可是索引是9
//TLS結構體
typedef struct _IMAGE_TLS_DIRECTORY32 {
DWORD StartAddressOfRawData;
DWORD EndAddressOfRawData;
DWORD AddressOfIndex; // PDWORD
DWORD AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *
DWORD SizeOfZeroFill;
union {
DWORD Characteristics;
struct {
DWORD Reserved0 : 20;
DWORD Alignment : 4;
DWORD Reserved1 : 8;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;