前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >8.10 TLS线程局部存储反调试

8.10 TLS线程局部存储反调试

原创
作者头像
微软技术分享
发布2023-09-27 10:00:25
3190
发布2023-09-27 10:00:25
举报
文章被收录于专栏:灰帽黑客:攻守道

TLS(Thread Local Storage)用来在进程内部每个线程中存储私有的数据。每个线程都会拥有独立的TLS存储空间,可以在TLS存储空间中保存线程的上下文信息、变量、函数指针等。TLS其目的是为了解决多线程变量同步问题,声明为TLS变量后,当线程去访问全局变量时,会将这个变量拷贝到自己线程中的TLS空间中,以防止同一时刻内多次修改全局变量导致变量不稳定的情况,先来看一段简单的案例:

代码语言:c
复制
#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中断处理函数的,因此可以利用这一点来判断程序是否正在运行在调试器下。

代码语言:c
复制
#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;
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档