The special thing about TLS is that the program's entry point EP is not the first instruction to execute, so it is often used for anti-debug detection.
Use an already open TLS program to do the instructions.
Data
TLS exists in the PE file format. The IMAGE_DATA_DIRECTORY DataDirectory[9]
address where the TLS directory is stored.
winNT.h [F12 可得到定义位置]#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory同其他目录表数组一样,也是8字节结构 (VA+Size)typedefstruct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size;} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
Details of the directory can be found from the VA at TLS.
32位下的TLS目录详情typedefstruct _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;
Addressofcallbacks is a pointer to an array of pointers, and a pointer array is the address of a callback function that is registered by TLS. The callback function is continuously distributed as an array and ends with a DWORD value that is all 0.
A TLS can have multiple callback functions, which are called.
Therefore, it 00401000
is the TLS registered callback function, you can see that the program only registered a callback function.
Trigger mechanism
The TLS callback function is called automatically when the thread is created/terminated.
EP is entered after the system has created the program's main thread, so the TLS callback function is run before the EP, which is why many anti-debugging techniques are used with TLS.
Definition of the TLS callback function
typedef VOID(NTAPI *PIMAGE_TLS_CALLBACK) ( PVOID DllHandle, //模块句柄,即加载地址 DWORD Reason, PVOID Reserved );其中reason有以下几种:(winNT.h)#define DLL_PROCESS_ATTACH 1 进程启动#define DLL_THREAD_ATTACH 2 线程启动#define DLL_THREAD_DETACH 3 线程退出#define DLL_PROCESS_DETACH 0 进程退出
Programming examples
//Tls_test.cpp: Defines the entry point of the console application. //#include "stdafx.h"#include <windows.h>#include <stdio.h>#pragma COMMENT (linker, "/include:__tls_used")voidNtapi tls_callback1 (lpvoid dllhhanle,dword reason,pvoid Reserved) {printf("Tls_callback1:d llhandle=%x,reason=%d\n", Dllhhanle,reason);}voidNtapi Tls_callback2 (lpvoid dllhhanle,dword reason,pvoid Reserved) {printf("Tls_callback2:d llhandle=%x,reason=%d\n", Dllhhanle,reason);}#pragma data_seg (". Crt$xlx ")Pimage_tls_callback Ptls_callbacks[]={tls_callback1,tls_callback2,0};//end with 0#pragma data_seg ()DWORD WINAPI ThreadProc (lpvoid lpparam) {printf("ThreadProc () start\n");printf("ThreadProc () end\n");return 0;}int_tmain (intARGC, _tchar* argv[]) {HANDLE hthread = NULL;printf("Main start\n"); Hthread = CreateThread (NULL,0, Threadproc,null,0, NULL); WaitForSingleObject (Hthread, -* +); CloseHandle (Hthread);printf("Main end\n");return 0;}
The description of the code, in the "hacker-free attack and defense," said the very clear.
#pragma comment(linker,"/INCLUDE:__tls_used")
Indicates that you want to use the TLS table
#pragma data_seg(".CRT$XLX")PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[]={tls_callback1,tls_callback2,0};#pragma data_seg()
Register the callback function, .CRT$XLX
CRT 表示
C RunTime ' mechanism
X indicates that the identity name is random, but does not mean that it can be random, only with X
L represents the TLS callback section
X (b-y) Any one letter can be
WaitForSingleObject(hThread,60*1000);
When the main thread executes, the threads that are created are exited. (Causes the main thread to block 60s)
Interestingly, the above code was compiled under VS2008. With VC6.0 compilation, TLS is invalid. At that time did not know how to do, on the Internet to search for solutions. First of all, humorous, this is the gap with Daniel, they may be thinking, if the TLS call in addition to the problem, then it must be TLS in the structure of the PE problem. Then they went to check the TLS structure and found that the problem was here. Therefore, the idea is very important, did not come out the result must ponder, thought out to try.
Let me summarize the question and give a new solution. TLS callback problem, online has been given a solution, but there are always some problems, basically as follows:1, VC6 not supported.2, the debug version of VS2005 Normal, release version is not normal.3, VS2005 release version is normal, debug version is not normal. VC6 is not supported because of a problem with the tlssup.obj of the VC6 band, which has defined the first item of the callback table and is0,0means the end of the callback table, so our added function is not called. [INDENT] for the first2A question, I did not meet, but met the first3A problem. The problem was studied and the problem was found: in the link process, the section. Crt$xla and. Crt$xlb should be merged alphabetically without gaps, but in the output of the debug version the fact is not so, the order is correct, but there is a large gap, gap fill0, which is the equivalent of adding in front of our callback table0A number of0, and again the callback table ended prematurely, which might be a bug. For the second situation, I did not encounter, do not know whether this is the reason, if it is, then I think it should be link bug. In response to the above problem, originally I would like to use VS2008 tlssup.obj, but it is incompatible with VC6, changed to more trouble, then I suddenly thought, maybe we can create a tlssup.obj, based on this idea, wrote their own tlssup, Current test results show that it can be compatible with vc6,vs2005,vs2008, the code is as follows:/* File name: TLSSUP.C, required to compile in C, if your project is CPP project, please cancel the precompiled header for this source file */ #include <windows.h> #include <winnt.h> int_tls_index=0;#pragma data_seg (". TLS") int_tls_start=0;#pragma data_seg (". tls$zzz") int_tls_end=0;#pragma data_seg (". Crt$xla ") int__xl_a=0;#pragma data_seg (". Crt$xlz ") int__xl_z=0;#pragma data_seg (". rdata$t") externPimage_tls_callback my_tls_callbacktbl[]; Image_tls_directory32 _tls_used={(DWORD) &_tls_start, (DWORD) &_tls_end, (DWORD) &_tls_index, (DWORD) my_ TLS_CALLBACKTBL,0,0};/*tlssup.c End * /We then define the MY_TLS_CALLBACKTBL in the other CPP files as follows:extern "C"Pimage_tls_callback my_tls_callbacktbl[] = {MY_TLS_CALLBACK1,0};//can have multiple callbacks, but be sure to add an empty entry at the end, otherwise it is likely to go wrong. Of course, the following line is not less:#pragma COMMENT (linker, "/include:__tls_used")
I see, VC6.0 the program callback function address array is really the first 0, after modification, found that the TLS callback to create the thread is not a problem, but the main function is not tls_callback execution, can not figure out why. The best way to reverse debugging is to detect it before EP, so VC6.0 does not do it in this way. Then I simply used the vs2008.
VS2008 the correct version of the execution result: C:\vc6\myprojects\tls_test\release>tls_test.exetls_callback1:d llhandle=400000, reason=1//program started (but not yet into EP)Tls_callback2:d llhandle=400000, reason=1Main Starttls_callback1:d llhandle=400000, reason=2 //Create thread to startTls_callback2:d llhandle=400000, reason=2ThreadProc () Startthreadproc ()EndTls_callback1:d llhandle=400000, reason=3 //created thread execution completeTls_callback2:d llhandle=400000, reason=3MainEndTls_callback1:d llhandle=400000, reason=0 //Program ExitTls_callback2:d llhandle=400000, reason=0
There are two questions:
1. The TLS callback function is consistent with the parameters of the DllMain function, so ReasonForCall
does their representation mean the same thing?
For example dll_process_attach
, a DLL creation or process creation.
Also, a program first create a process, TLS once, and then create the main thread, supposedly should be TLS once, how not it. The main function is running on the main thread.
2. < reverse engineering Core Principles > p457, when a thread is created, then TLS executes before the thread is created. Can be "hacker-free technology" is also said to be implemented before, that is, after the creation of the implementation. Depressed, feel wrong ah, should be created after the thread, the thread is not started, and start TLS, which means that the thread has been created. From my understanding or, perhaps, the author thinks that the thread was created successfully as a thread that was started as an identity.
I feel like this is actually the callback function after the thread was created (not the execution function, of course), so it should be created successfully. But it's not done yet. callback function, it is not after the end of a notice to you, and then I go to customize the callback function.
3. In fact, this PE file has a. TLS segment. TLS directory is stored in the. Rdata area, the callback function address is in the. Rdata area, the callback function is in the. Text area, and the TLS area has a yarn relationship? So, don't know this. The TLS section is used for hair.
Hey, say more is a tear, on the thread or ignorant ah.
TLS (Thread Local Storage) anti-debug principle