TLS Code Execute
TLS简介
线程局部存储(Thread Local Storage,TLS)用来将数据与一个正在执行的指定线程关联起来。
进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。
如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),这就是TLS。
TLS提供了一个回调函数(callback function),在线程程初始化和终止的时候都会调用,由于回调函数会在入口点(EP)前执行,而调试器通常会默认在主函数入口点main设置断点,所以常常被用来作为反调试手段使用,同时回调函数允许我们自由编写任意代码,TLS分为静态TLS和动态TLS,静态TLS会把TLS相关数据硬编码在PE文件内,在本篇文章内我们使用静态TLS来实现代码执行。
静态TLS
TLS回调函数遵循特殊的编写约定,与dll主函数相似。
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
PVOID DllHandle,
DWORD Reason, //Reason 遵循dll调用时相同的参数
PVOID Reserved
);静态TLS存储在PE头IMAGE_DATA_DIRECTORY DataDirectory[9]的位置,同其他目录表数组一样,也是8字节结构 (VA+Size),从TLS的VA处,可以找到该目录的详细信息。
typedef struct _IMAGE_TLS_DIRECTORY32 { //SIZE:0x18h
DWORD StartAddressOfRawData;
DWORD EndAddressOfRawData;
DWORD AddressOfIndex; // PDWORD
DWORD AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *
DWORD SizeOfZeroFill;
DWORD Characteristics;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;
代码实现
x64的回调函数声明使用别的预处理指令
扩展
由于TLS调用时通常已经初始化了所以进程相关信息(DLL加载、PEB分配),所以理论上我们能在TLScallback函数内实现任意代码,理论上我们能在TLS实现其他任意技术,如在TLS回调函数内实现Mapping注入技术。

LINKS
最后更新于
这有帮助吗?