8.10 TLS线程局部存储反调试

tls,线程,局部,存储,调试 · 浏览次数 : 21

小编点评

**TLS(Thread Local Storage)简介** TLS是一种在进程内部每个线程中存储私有的数据的技术。每个线程都会拥有独立的TLS存储空间,可以在TLS存储空间中保存线程的上下文信息、变量、函数指针等。TLS其目的是为了解决多线程变量同步问题,当线程去访问全局变量时,会将这个变量拷贝到自己线程中的TLS空间中,以防止同一时刻内多次修改全局变量导致变量不稳定的情况。 **TLS中断** TLS中断是一种另一种反调试技术,它利用进程中的线程来执行自定义的中断处理函数,TLS中断处理函数会被在程序加载之前就运行,并能够抢在调试器对程序进行跟踪之前终止执行,这使得它成为一种相对安全的反调试技术。 **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\\";// ``` 这段代码定义了一个名为 `g_nNum` 的线程局部变量,并将其初始值设置为 `0x11111111`。 **TLS中断处理函数** ```c void NTAPI __stdcall TLS_CALLBACK(PVOID DllHandle, DWORD dwReason, PVOID Reserved){ if (IsDebuggerPresent()) { MessageBox(NULL, \" TLS_CALLBACK: 请勿调试本程序 !\", \"TLS Callback\", MB_ICONSTOP); ExitProcess(0); } } ``` 当程序中存在调试时,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;
}

与8.10 TLS线程局部存储反调试相似的内容:

8.10 TLS线程局部存储反调试

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

上周热点回顾(10.2-10.8)

热点随笔: · 【故障公告】遭遇用心良苦的疯狂攻击:DDoS + CC攻击 (博客园团队)· 一种对数据库友好的GUID的变种使用方法 (ensleep)· BS系统的登录鉴权流程演变 (风吹草)· 会员权益-新功能发布:定时发布博文 (博客园团队)· 面试官随便问几个问题就知道你究竟做没做过微信支

[转帖]BASH编写入门与实例

1 2 3 4 5 6 7 8 9 10 怎么写shell脚本: 。使用任何编辑工具编写shell脚本 例如vi -#!/bin/bash #在第一行放置头格式说明 -#!/usr/bin/gawk //awk需要添加的头格式,让系统知道用什么方式去解析此文件 -#!/usr/local/bin/p

[转帖]记录一则enq: TX - row lock contention的分析过程

https://www.cnblogs.com/jyzhao/p/8628184.html 故障描述:与客户沟通,初步确认故障范围大概是在上午的8:30-10:30之间,反应故障现象是Tomcat的连接数满导致应用无法连接,数据库alert中无明显报错,需要协助排查原因。 1.导入包含故障时刻的数据

[转帖]记录一则enq: TX - row lock contention的分析过程

https://www.cnblogs.com/jyzhao/p/8628184.html 故障描述:与客户沟通,初步确认故障范围大概是在上午的8:30-10:30之间,反应故障现象是Tomcat的连接数满导致应用无法连接,数据库alert中无明显报错,需要协助排查原因。 1.导入包含故障时刻的数据

[转帖]Sql Server中通过sql命令获取cpu占用及产生锁的sql

https://www.jb51.net/article/266255.htm 这篇文章主要介绍了Sql Server中通过sql命令获取cpu占用及产生锁的sql,需要的朋友可以参考下 获取SQLSERVER中产生锁的SQL语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1

[转帖]Keepalived如何实现Nginx高可用

https://www.jb51.net/article/266305.htm Keepalived安装可参考Mysql+Keepalived实现双主热备 Master上的keepalived.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

python基础环境

刚开始接触并学习一门开发语言,带着不求甚解的想法,其实也挺有好处的:我并不是所有的东西都知道,但是代码跑起来了。 但是时间久了,还是带着这种想法,可能就会遇到一些棘手的问题。比如电脑上不知不觉已经安装了多个python版本,python3.8/3.10/3.11,甚至一些软件中也集成有python解

杭州亚运会实现核心系统100%上云、云上转播7200+小时

杭州亚运会实现核心系统100%上云。 10月8日晚,杭州亚运会圆满闭幕。 作为史上首届“云上亚运”,杭州亚运会创造了历史。杭州亚运会实现了核心系统100%上云,并借助后台云算力、云存储等云技术保障,建设一系列各层级、各场馆数字指挥平台,实现全面感知、高效指挥。 同时,首次实现云上转播,据统计,杭州亚

scanf、cin及其优化、快读性能测试

为了让大家了解C++各种IO方式的性能,于是就有了这篇文章。 本次测试采取的数据均为 \(10^6\) 个不超过 \(10^8\) 随机正整数。 测试代码: #include using namespace std; int x; int main(){ freopen