TLS反调试

TLS

TLS是Thread Local Storage的缩写,线程局部存储,主要是为了解决多线程中的变量同步的问题

TLS的意义

进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有的线程都生效。这是一个优点也是一个缺点,优点是交换数据快,缺点是多个数据访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG

如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制TLS来处理。

TLS变量

当线程A去修改TLS变量的时候,TLS变量不会有影响,每个人都有一个TLS变量的副本,互不影响。

创建TLS变量

_declspec(thread) int g_number = 100;

TLS代码实践

https://www.cnblogs.com/Sna1lGo/p/14466889.html

TLS用途2

TLS在安全领域中,常被用来处理如反调试、抢占执行等操作

TLS回调函数

1 首先加上编译选项

#pragma comment(linker,"/INCLUDE:__tls used")

2

/*
注册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()

TLS回调函数格式

void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{

}

TLS函数何时被调用

image-20210302013952076

当一个程序被调用的时候,先执行TLS函数后,再跳转到程序的IMAGEBASE执行PE文件结构。

可以在TLS函数中添加代码来防止程序被调试

PE文件中的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;