TLS CallBack
TLS(Thread-local storage,线程本地存储)回调属于一种特殊的回调函数,其会在进程加载前、进程退出前、线程加载前、线程退出前执行
其函数原型为:
void NTAPI tls_callback_1(
PVOID DllHandle, // 模块句柄
DWORD Reason, // DllMain的fdwReason参数一样
PVOID Reserved // 保留
);
使用TLS Callback Function
在vs中,可用直接使用编译器功能来设置TLS回调
#ifdef _WIN64
#pragma comment (linker, "/INCLUDE:_tls_used") // 指明使用TLS回调
#pragma comment (linker, "/INCLUDE:thread_callback_base") // 强制编译器生成对thread_callback_base的引用,防止优化
#else
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:_thread_callback_base")
#endif
注意:x64下的_tls_used
比x86下的__tls_used
少一个_
,thread_callback_base
也是同理
_tls_used
指明使用TLS回调,将在PE中创建一个.tls
的节thread_callback_base
则是强制编译器生成对thread_callback_base
的引用,防止在Release下的优化导致TLS回调被优化掉,此处的thread_callback_base
是一个TLS回调数组,以NULL结尾
之后设置TLS回调,节名.CRT$XL
的含义如下:
CRT
表示使用C Runtime机制$X
表示随机标识L
表示TLS CallBack Section- 最后的
F
替换可以为B ~ Y
任意一个字符
#ifdef _WIN64
#pragma const_seg(".CRT$XLF")
EXTERN_C const
#else
#pragma data_seg(".CRT$XLF")
EXTERN_C
#endif
PIMAGE_TLS_CALLBACK thread_callback_base[] = { tls_callback_1, tls_callback_2, 0 }; // 设置TLS回调
#ifdef _WIN64
#pragma const_seg()
#else
#pragma data_seg()
#endif //_WIN64
示例
#include <stdio.h>
#include <Windows.h>
#ifdef _WIN64
#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:thread_callback_base")
#else
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:_thread_callback_base")
#endif
void generate_str(char *ptr, DWORD reason)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
strcat(ptr, "DLL_PROCESS_ATTACH\n");
break;
case DLL_PROCESS_DETACH:
strcat(ptr, "DLL_PROCESS_DETACH\n");
break;
case DLL_THREAD_ATTACH:
strcat(ptr, "DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
strcat(ptr, "DLL_THREAD_DETACH\n");
break;
}
}
// TLS回调
void NTAPI tls_callback_1(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
char ptr[256] { 0 };
strcpy(ptr, " TLS Callback1: ");
generate_str(ptr, Reason);
WriteConsoleA(hStdout, ptr, strlen(ptr), NULL, NULL);
}
// TLS回调
void NTAPI tls_callback_2(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
char ptr[256] { 0 };
strcpy(ptr, " TLS Callback2: ");
generate_str(ptr, Reason);
WriteConsoleA(hStdout, ptr, strlen(ptr), NULL, NULL);
}
#ifdef _WIN64
#pragma const_seg(".CRT$XLF")
EXTERN_C const
#else
#pragma data_seg(".CRT$XLF")
EXTERN_C
#endif
PIMAGE_TLS_CALLBACK thread_callback_base[] = { tls_callback_1, tls_callback_2, 0 };
#ifdef _WIN64
#pragma const_seg()
#else
#pragma data_seg()
#endif //_WIN64
#define OK_PRINT_FLAG(s) ("\033[1;40;32m[+]\033[0m "##s)
#define ERR_PRINT_FLAG(s) ("\033[1;40;31m[-]\033[0m "##s)
// 线程回调
DWORD WINAPI thread_func(
_In_ LPVOID lpParameter
)
{
printf(OK_PRINT_FLAG("Enter thread func...\n"));
Sleep(5000);
printf(OK_PRINT_FLAG("Leave thread func...\n"));
return 0;
}
int main(void)
{
printf(OK_PRINT_FLAG("Enter main...\n"));
HANDLE hThread = CreateThread(NULL, 0, thread_func, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
printf(OK_PRINT_FLAG("Leave main...\n"));
return 0;
}
注:x64dbg中,设置 - 事件选项卡中勾选TLS回调函数,则可用在TLS回调执行时断下
TLS记录存储在.tls
节中,其回调在.rdata
中