8.10 TLS線程局部存儲反調試

TLS(Thread Local Storage)用來在進程內部每個線程中存儲私有的數據。每個線程都會擁有獨立的TLS存儲空間,可以在TLS存儲空間中保存線程的上下文信息、變量、函數指針等。TLS其目的是爲了解決多線程變量同步問題,聲明爲TLS變量後,當線程去訪問全局變量時,會將這個變量拷貝到自己線程中的TLS空間中,以防止同一時刻內多次修改全局變量導致變量不穩定的情況,先來看一段簡單的案例:

#include <Windows.h>
#include <stdio.h>

#pragma comment(linker, "/INCLUDE:__tls_used")

// TLS變量 
__declspec (thread) int g_nNum = 0x11111111;
__declspec (thread) char g_szStr[] = "TLS g_nNum = 0x%p ...\r\n";

// 當有線程訪問tls變量時,該線程會複製一份tls變量到自己tls空間
// 線程只能修改自己的空間tls變量,不會修改到全局變量

// TLS回調函數A
void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Red)
{
    if (DLL_THREAD_DETACH == Reason) // 如果線程退出則打印信息   
        printf("t_TlsCallBack_A -> ThreadDetach!\r\n");
    return;
}

// TLS回調函數B
void NTAPI t_TlsCallBack_B(PVOID DllHandle, DWORD Reason, PVOID Red)
{
    if (DLL_THREAD_DETACH == Reason) // 如果線程退出則打印信息 
        printf("t_TlsCallBack_B -> ThreadDetach!\r\n");

    /* Reason 什麼事件觸發的
    DLL_PROCESS_ATTACH   1
    DLL_THREAD_ATTACH    2
    DLL_THREAD_DETACH    3
    DLL_PROCESS_DETACH   0        */
    return;
}

// 註冊TLS回調函數,".CRT$XLB"
#pragma data_seg(".CRT$XLB") 
PIMAGE_TLS_CALLBACK p_thread_callback[] = { t_TlsCallBack_A, t_TlsCallBack_B, };
#pragma data_seg()

DWORD WINAPI t_ThreadFun(PVOID pParam)
{
    printf(g_szStr, g_nNum);
    g_nNum = 0x22222222;
    printf(g_szStr, g_nNum);
    return 0;
}

int main(int argc, char * argv[])
{
    CreateThread(NULL, 0, t_ThreadFun, NULL, 0, 0);
    Sleep(100);
    CreateThread(NULL, 0, t_ThreadFun, NULL, 0, 0);

    system("pause");
    return 0;
}

TLS(Thread Local Storage)中斷是另一種反調試技術,它利用進程中的線程來執行自定義的中斷處理函數,TLS中斷處理函數會被在程序加載之前就運行,並能夠搶在調試器對程序進行跟蹤之前終止執行,這使得它成爲一種相對安全的反調試技術。當程序被加載時,TLS中斷會自動執行,而對於調試器來說,默認情況下是不會運行TLS中斷處理函數的,因此可以利用這一點來判斷程序是否正在運行在調試器下。

#include <Windows.h>
#include <stdio.h>

// linker spec 通知鏈接器PE文件要創建TLS目錄
#ifdef _M_IX86
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:__tls_callback")
#else
#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:_tls_callback")
#endif

void NTAPI __stdcall TLS_CALLBACK(PVOID DllHandle, DWORD dwReason, PVOID Reserved)
{
    if (IsDebuggerPresent())
    {
        MessageBox(NULL, " TLS_CALLBACK: 請勿調試本程序 !", "TLS Callback", MB_ICONSTOP);
        ExitProcess(0);
    }
}

// 創建TLS段
EXTERN_C
#ifdef _M_X64
    #pragma const_seg (".CRT$XLB")
    PIMAGE_TLS_CALLBACK _tls_callback = TLS_CALLBACK;
#else
    #pragma data_seg (".CRT$XLB")
    PIMAGE_TLS_CALLBACK _tls_callback = TLS_CALLBACK;
#endif

int main(int argc, char * argv[])
{
    system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章