Aerosol Posted December 8, 2014 Report Posted December 8, 2014 TLS (thread local storage) calls are subroutines that are executed before the entry point . There is a section in the PE header that describes the place of a TLS callback. Malwares employ TLS callbacks to evade debugger messages. When a particular malware employed with TLS callbacks is loaded into a debugger, the malware finishes its work before the debugger stops at the entry point.Let’s start with a simple example of a TLS callback in C:/***************************************** TLS Example ProgramCompile With MSVC********************************************/#include#pragma comment(linker, "/INCLUDE: tls_used")void NTAPI TlsCallBac(PVOID h, DWORD dwReason, PVOID pv);#pragma data_seg(".CRT$XLB")PIMAGE_TLS_CALLBACK p_thread_callback = TlsCallBac;#pragma data_seg()void NTAPI TlsCallBac(PVOID h, DWORD dwReason, PVOID pv){MessageBox(NULL, "In TLS", "In TLS", MB_OK);return;}int main(int argc , char**argv){MessageBox(NULL, "In Main", "In Main", MB_OK);return 0;}After running this program, the “In TLS” Message box will pop up first rather than “In Main.” This proves that TLS callbacks are executed before the entry point.Following is the dumpbin output of the exe compiled using the above code:FILE HEADER VALUES14C machine (x86)4 number of sections52C01E9D time date stamp Sun Dec 29 18:37:41 20130 file pointer to symbol table0 number of symbolsE0 size of optional header103 characteristics Relocations stripped Executable32 bit word machineOPTIONAL HEADER VALUES10B magic # (PE32)8.00 linker version7000 size of code5000 size of initialized data0 size of uninitialized data1256 entry point (00401256)1000 base of code8000 base of data400000 image base (00400000 to 0040CFFF)1000 section alignment1000 file alignment4.00 operating system version0.00 image version4.00 subsystem version0 Win32 versionD000 size of image1000 size of headers0 checksum3 subsystem (Windows CUI)0 DLL characteristics100000 size of stack reserve1000 size of stack commit100000 size of heap reserve1000 size of heap commit0 loader flags10 number of directories0 [ 0] RVA [size] of Export Directory9524 [ 3C] RVA [size] of Import Directory0 [ 0] RVA [size] of Resource Directory0 [ 0] RVA [size] of Exception Directory0 [ 0] RVA [size] of Certificates Directory0 [ 0] RVA [size] of Base Relocation Directory0 [ 0] RVA [size] of Debug Directory0 [ 0] RVA [size] of Architecture Directory0 [ 0] RVA [size] of Global Pointer Directory9260 [ 18] RVA [size] of Thread Storage Directory9218 [ 40] RVA [size] of Load Configuration Directory0 [ 0] RVA [size] of Bound Import Directory8000 [ F8] RVA [size] of Import Address Table Directory0 [ 0] RVA [size] of Delay Import Directory0 [ 0] RVA [size] of COM Descriptor Directory0 [ 0] RVA [size] of Reserved DirectoryThe Thread Storage Directory is filled up.The TLS directory is defined in MSDN as(http://msdn.microsoft.com/en-us/magazine/cc301808.aspx):typedef struct _IMAGE_TLS_DIRECTORY { UINT32 StartAddressOfRawData;UINT32 EndAddressOfRawData; PUINT32 AddressOfIndex;PIMAGE_TLS_CALLBACK *AddressOfCallBacks; UINT32 SizeOfZeroFill;UINT32 Characteristics;} IMAGE_TLS_DIRECTORY, *PIMAGE_TLS_DIRECTORYLet’s try to look at a sample that employs TLS callbacks.Supplying it to PEID says it has been packed with NULLSoft packer.Note: The first layer packer is irrelevant to this analysis, This packer basically creates injects inside a new process, which is the unpacked image: .This is a valid MZ image.If you look at the MZ image, you will notice a weird thing about the address of the entry point:00000108 00000000 DD 00000000 ; AddressOfEntryPoint = 00000010C 00100000 DD 00001000 ; BaseOfCode = 100000000110 00800000 DD 00008000 ; BaseOfData = 800000000114 00004000 DD 00400000 ; ImageBase = 400000As you can see, over there the address of the entry point is 0 but, at the same time, the TLS table is supplied:000001A0 60920000 DD 00009260 ; TLS Table address = 9260000001A4 18000000 DD 00000018 ; TLS Table size = 18 (24.)Here is the dump of the TLS tableE4 96 00 00 F2 96 00 00 FE 96 00 00 0E 97 00 00 24 97 00 00 40 97 00 00 5A 97 00 00 72 9700 008C 97 00 00 A2 97 00 00 B2 97 00 00 CC 97 00 00 DE 97 00 00 EC 97 00 00 FE 97 00 00 1698 00 0024 98 00 00 30 98 00 00 3E 98 00 00 48 98 00 00that gives us the location of TLS entry point . There are two ways to catch TLS calls:1 : Change the Ollydbg setting to the system breakpoint:2 : Set up a hardware breakpoint at 0x7C9011A4We will use the second method, which is more preferable. After loading the TLS application, it will stop here in the debugger:7C901194 8BEC MOV EBP,ESP7C901196 56 PUSH ESI7C901197 57 PUSH EDI7C901198 53 PUSH EBX7C901199 8BF4 MOV ESI,ESP7C90119B FF75 14 PUSH DWORD PTR SS:[EBP+14]7C90119E FF75 10 PUSH DWORD PTR SS:[EBP+10]7C9011A1 FF75 0C PUSH DWORD PTR SS:[EBP+C]7C9011A4 FF55 08 CALL DWORD PTR SS:[EBP+8] ; TLS Callback7C9011A7 8BE6 MOV ESP,ESI7C9011A9 5B POP EBX7C9011AA 5F POP EDI7C9011AB 5E POP ESI7C9011AC 5D POP EBP7C9011AD C2 1000 RETN 10Stepping inside the call leads us here. Now, to fix the PE header, we need fix the entry point of the application to the exact location of the TLS callback and the Zero TLS table value:00401350 |. 56 PUSH ESI00401351 |. 56 PUSH ESI00401352 |. 56 PUSH ESI00401353 |. 56 PUSH ESI00401354 |. 56 PUSH ESI00401355 |. C700 16000000 MOV DWORD PTR DS:[EAX],160040135B |. E8 57170000 CALL me.00402AB700401360 |. 83C4 14 ADD ESP,1400401363 |. 6A 16 PUSH 1600401365 |. 58 POP EAX00401366 |. 5E POP ESI00401367 |. C3 RETN00401368 |> 3935 D4AC4000 CMP DWORD PTR DS:[40ACD4],ESI0040136E |.^74 DB JE SHORT me.0040134B00401370 |. 8B0D E0AC4000 MOV ECX,DWORD PTR DS:[40ACE0]00401376 |. 8908 MOV DWORD PTR DS:[EAX],ECX00401378 |. 33C0 XOR EAX,EAX0040137A |. 5E POP ESI0040137B . C3 RETNChange entry point = 0×0401350;000000FC 00700000 DD 00007000 ; SizeOfCode = 7000 (28672.)00000100 00500000 DD 00005000 ; SizeOfInitializedData = 5000 (20480.)00000104 00000000 DD 00000000 ; SizeOfUninitializedData = 000000108 50134000 DD 00401350 ; AddressOfEntryPoint = 4013500000010C 00100000 DD 00001000 ; BaseOfCode = 100000000110 00800000 DD 00008000 ; BaseOfData = 800000000114 00004000 DD 00400000 ; ImageBase = 400000After this step, TLS callbacks won’t be called and you can start debugging your application from entry point.Source 1 Quote