TLS回调函数
简介
代码逆向分析领域中,TLS(Thread Local Storage,线程局部存储)回调函数(Callback Function)常用于反调试。
TLS 回调函数的调用运行要先于 EP 代码的执行,该特征使它可以作为一种反调试技术使用。
TLS
讲解 TLS 回调函数前,先简单了解一下有关 TLS 的知识。TLS 是各线程的独立的数据存储空间。使用 TLS 技术可在线程内部独立使用或修改进程的全局数据或静态数据,就像对待自身的局部变量一样。
IMAGE_DATA_DIRECTORY[9]
若在编程中启用了 TLS 功能,PE 头文件中就会设置 TLS 表(TLS Table)项目,如下图所示(IMAGE_NT_HEADERS-IMAGE_OPTIONAL_HEADER-IMAGE_DATA_DIRECTORY[9])。
IMAGE_TLS_DIRECTORY
1 |
|
IMAGE_TLS_DIRECTORY
结构体有 2 种版本,分别为 32 位版本与 64 位版本。
DIE 会直接为我们解析IMAGE_TLS_DIRECTORY
结构体。
代码逆向分析中涉及的主要成员为AddressOfCallback6s
,该值指向含有 TLS 回调函数地址(VA)的数组。这意味着可以向同一程序注册多个 TLS 回调函数(数组以 NULL 值结束)。
回调函数地址数组
该数组中实际存储的就是 TLS 回调函数的地址。进程启动运行时,(执行 EP 代码前)系统会逐一调用存储在该数组中的函数。请注意,虽然以上练习示例中仅注册了 1 个 TLS 函数(地址为 0x401000),但其实我们可以通过修改程序注册多个 TLS 函数。
TLS 回调函数
接下来从技术层面简单整理之前介绍的 TLS 回调函数相关内容。
所谓 TLS 回调函数是指,每当创建/终止进程的线程时会自动调用执行的函数。有意思的是,创建进程的主线程时也会自动调用回调函数,且其调用执行先于 EP 代码。反调试技术利用的就是 TLS 回调函数的这一特性。
请注意,创建或终止某线程时,TLS 回调函数都会自动调用执行,前后共 2 次(原意即为此)。执行进程的主线程(运行进程的 EP 代码)前,TLS 回调函数会先被调用执行,许多逆向分析人员将该进程应用于程序的反调试技术。
IMAGE_TLS_CALLBACK
TLS 回调函数的定义如下:
1 |
|
仔细观察 TLS 回调函数的定义可以发现,它与DllMaiin()
函数的定义类似。
1 |
|
观察以上 2 个函数可以发现,它们的参数顺序和函数都是一样的。其中,参数DllHandle
为模块句柄(即加载地址),参数Reason
表示调用 TLS 回调函数的原因,具体原因有 4 种,如以下代码所示:
1 |
|
要想准确理解 TLS 回调函数的工作原理(在哪个时间点调用哪个回调函数),最好的方法就是亲自创建。