逆向 | windows TLS回调

发布时间 2023-04-07 16:16:56作者: Mz1

逆向 | windows TLS回调

之前逆向的时候偶尔会碰到tls回调,但是没有自己实现过,今天想着实现一下。
参考的代码来自 逆向工程核心原理。
代码如下:

#include <windows.h>

#pragma comment (linker, "/INCLUDE:__tls_used")

void print_console(char* msg) {
	HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	WriteConsoleA(hStdout, msg, strlen(msg), NULL, NULL);
}

DWORD WINAPI ThreadProc(LPVOID lParam) {	
	print_console("thread proc start \n");
	print_console("thread proc end \n");
	return 0;
}

VOID NTAPI TLS_CALLBACK1(PVOID DllHandle, DWORD Reason, PVOID Reversed) {
	char msg[55] = { 0 };
	wsprintfA(msg, "callback1: DllHandle=%X, Reason:%d \n", DllHandle, Reason);
	print_console(msg);
	MessageBox(0, 0, 0, 0);
}
VOID NTAPI TLS_CALLBACK2(PVOID DllHandle, DWORD Reason, PVOID Reversed) {
	char msg[55] = { 0 };
	wsprintfA(msg, "callback2: DllHandle=%X, Reason:%d \n", DllHandle, Reason);
	print_console(msg);
}


#pragma data_seg(".CRT$XLB")
PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK1, TLS_CALLBACK2, 0 };

#pragma data_seg()

int main() {
	print_console("main hello \n");

	HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
	WaitForSingleObject(hThread, 60 * 1000);
	CloseHandle(hThread);

	print_console("main bye\n");
	return 0;
}

有一个很魔幻的事情出现了,我的编译环境是vc6 x86,然后编译完我的tls回调并没有执行。
于是我去查了pe,发现tls回调表的位置上并没有回调函数,回调函数地址呗填写在了一个很靠后的位置(应该是链接器填写的问题)
经过patch以后可以执行回调,ida也能成功识别。
tls表结构可以参考这个文章:https://blog.csdn.net/weixin_30615767/article/details/98577560

主要的结构就是这个:

typedef struct _IMAGE_TLS_DIRECTORY32 
{
    DWORD   StartAddressOfRawData; //  TLS初始化数据的起始地址
    DWORD   EndAddressOfRawData;// TLS初始化数据的结束地址  两个正好定位一个范围,范围放初始化的值
    PDWORD  AddressOfIndex;// TLS 索引的位置
    PIMAGE_TLS_CALLBACK *AddressOfCallBacks;// Tls回调函数的数组指针
    DWORD   SizeOfZeroFill;// 填充0的个数
    DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32

就是回调数组指针上是一系列回调函数地址,结果链接器给我填错位置了,嗐。