《逆向工程核心原理》——TLS回调函数
pe中TLS(thread local storage)中函数的执行时机早于入口函数(entry point),
相关结构:
// // Thread Local Storage // typedef VOID (NTAPI *PIMAGE_TLS_CALLBACK) ( PVOID DllHandle, DWORD Reason, PVOID Reserved ); typedef struct _IMAGE_TLS_DIRECTORY64 { ULONGLONG StartAddressOfRawData; ULONGLONG EndAddressOfRawData; ULONGLONG AddressOfIndex; // PDWORD ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; DWORD SizeOfZeroFill; union { DWORD Characteristics; struct { DWORD Reserved0 : 20; DWORD Alignment : 4; DWORD Reserved1 : 8; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } IMAGE_TLS_DIRECTORY64; typedef IMAGE_TLS_DIRECTORY64 * PIMAGE_TLS_DIRECTORY64; 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;
例子:
#include <iostream> #include <Windows.h> //TLS回调函数测试 void NTAPI MY_TLS_CALLBACK(PVOID DllHandle, DWORD Reason, PVOID Reserved) { printf("CALL TLS 1\n"); switch (Reason) { case DLL_PROCESS_ATTACH: printf("DLL_PROCESS_ATTACH\ttls 1\n"); break; case DLL_THREAD_ATTACH: printf("DLL_THREAD_ATTACH\ttls 1\n"); break; case DLL_THREAD_DETACH: printf("DLL_THREAD_DETACH\ttls 1\n"); break; case DLL_PROCESS_DETACH: //printf("DLL_PROCESS_DETACH\ttls 1\n");//进程结束时并没有输出,可能关闭了通道?? break; } } void NTAPI MY_TLS_CALLBACK2(PVOID DllHandle, DWORD Reason, PVOID Reserved) { printf("CALL TLS 2\n"); switch (Reason) { case DLL_PROCESS_ATTACH: printf("DLL_PROCESS_ATTACH\ttls 2\n"); break; case DLL_THREAD_ATTACH: printf("DLL_THREAD_ATTACH\ttls 2\n"); break; case DLL_THREAD_DETACH: printf("DLL_THREAD_DETACH\ttls 2\n"); break; case DLL_PROCESS_DETACH: //printf("DLL_PROCESS_DETACH\ttls 2\n"); break; } } /* #ifdef _M_AMD64 #pragma comment (linker, "/INCLUDE:_tls_used") #pragma comment (linker, "/INCLUDE:p_tls_callback1") #pragma const_seg(push) #pragma const_seg(".CRT$XLX") EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1[] = { MY_TLS_CALLBACK,MY_TLS_CALLBACK2,0 }; #pragma const_seg(pop) #endif #ifdef _M_IX86 #pragma comment (linker, "/INCLUDE:__tls_used") #pragma comment (linker, "/INCLUDE:_p_tls_callback1") #pragma const_seg(push) #pragma const_seg(".CRT$XLX") EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1[] = { MY_TLS_CALLBACK,MY_TLS_CALLBACK2,0 }; #pragma const_seg(pop) #endif */ #ifdef _M_AMD64 #pragma comment(linker,"/INCLUDE:_tls_used") #pragma const_seg(".CRT$XLX") EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1[] = { MY_TLS_CALLBACK,MY_TLS_CALLBACK2,0 }; #pragma const_seg() #endif #ifdef _M_IX86 #pragma comment (linker, "/INCLUDE:__tls_used") #pragma const_seg(".CRT$XLX") EXTERN_C const PIMAGE_TLS_CALLBACK p_tls_callback1[] = { MY_TLS_CALLBACK,MY_TLS_CALLBACK2,0 }; #pragma const_seg() #endif DWORD WINAPI MyThreadFunction(LPVOID lpParam) { int nb = *(int*)lpParam; for (int i = 0; i < nb; ++i) { printf("number: %d\n", i); Sleep(1000); } return 1; } int main() { std::cout << "Hello World!\n"; DWORD dwThreadId=0; int number = 3; HANDLE hThread= CreateThread( NULL, // default security attributes 0, // use default stack size MyThreadFunction, // thread function name &number, // argument to thread function 0, // use default creation flags &dwThreadId); // returns the thread identifier getchar(); }
输出: