This article has been published in section 2012.11 of the "black line of defense". Please indicate the source for reprinting!
From http://www.bhst.org & http://nightx.info
0 × 00 TLS description
Thread Local Storage (TLS) is a mechanism provided by Windows to allow multiple threads in a process to access global variables at the same time. TLS can be used by the operating system to complete the entire mutex process, or you can write a function to control the semaphore. When a thread in a process accesses a preset memory space, the operating system calls the system's default or user-defined semaphore function to ensure data integrity and correctness.
When the Coder chooses to use its own semaphore function, in the application initialization phase, the system will call an initialization function compiled by the user to complete the semaphore initialization and other initialization work. This call must be completed before the program is actually executed to the entry point to ensure the correctness of program execution.
Figure 1
Anti-debugging Based on TLS, the principle is to execute the detection debugger code before the actual entry point code is executed. The implementation method is to use the TLS callback function. The result of TLS anti-debugging is 1. The anti-debugging code has been executed and exited before the OD dynamic debugger loads the program to the entry point. In addition, some viruses can be started before the debugger starts when TLS is used, because some debuggers work at the main entry point of the program.
0 × 01 function prototype
The TLS callback function is prototype as follows:
Void NTAPI TlsCallBackFunction (PVOID Handle, DWORD Reason, PVOID Reserve );
Implementing TLS anti-debugging is to make full use of the TLS callback function to gain control of the program before the program entry point, so that the general anti-debugging technology has a better practical effect.
In PE format, a space is opened for TLS data, and the location is IMAGE_NT_HEADERS.OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_TLS].
The DataDirectory element has the following data structure:
Typedef struct _ IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
The DataDirectory element of TLS. The VirtualAddress Member points to a struct. The struct defines the memory address to be mutually exclusive, the TLS callback function address, and other information.
0 × 02 C ++ next TLS-Anti-Debug Demo
The VC compiler provided by Microsoft supports TLS directly in the program by default. To use TLS in the program, you must first create a separate data segment for the TLS data and fill the segment with the relevant data, notifies the linker to add data to the PE File Header For TLS data.
The first DEMO of anti-debugging before loading using TLS is provided: test1.
The Code is as follows:
- # Include "windows. h"
- # Include "iostream"
- # Include "tlhelp32.h"
- // Notify the linker PE file to create the TLS directory
- # Pragma comment (linker, "/INCLUDE :__ tls_used ")
- Void lookupprocess (void );
- Void Debugger (void );
- Void NTAPI tls_callback (PVOID h, DWORD reason, PVOID pv)
- {
- Lookupprocess ();
- Debugger ();
- MessageBox (NULL, "Not Main !"," Test1 ", MB_ OK );
- Return;
- }
- // Create a TLS segment
- # Pragma data_seg (". CRT $ XLB ")
- // Define the callback function
- PIMAGE_TLS_CALLBACK p_thread_callback = tls_callback;
- # Pragma data_seg ()
-
- Int main ()
- {
- MessageBox (NULL, "Main !"," Test1 ", MB_ OK );
- Return 0;
- }
- // Anti-debug1 process Traversal
- Void lookupprocess ()
- {
- PROCESSENTRY32 pe32;
- Pe32.dwSize = sizeof (pe32 );
- HANDLE hProcessSnap =: createconlhelp32snapshot (TH32CS_SNAPPROCESS, 0 );
- BOOL bMore =: Process32First (hProcessSnap, & pe32 );
- While (bMore)
- {
- Strlwr (pe32.szExeFile );
- If (! Strcmp(pe32.szExeFile,”ollyice.exe "))
- {
- Exit (0 );
- }
- If (! Strcmp(pe32.szExeFile,”ollydbg.exe "))
- {
- Exit (0 );
- }
- If (! Strcmp(pe32.szExeFile,”peid.exe "))
- {
- Exit (0 );
- }
- If (! Strcmp(pe32.szExeFile,”idaq.exe "))
- {
- Exit (0 );
- }
- BMore =: Process32Next (hProcessSnap, & pe32 );
- }
- : CloseHandle (hProcessSnap );
- }
-
- // Anti-debug2
- Void Debugger (void)
- {
- Int result = 0;
- _ Asm {
- Mov eax, dword ptr fs: [30 h] // 30 h TEB offset
- Movzx eax, byte ptr ds: [eax + 2 h] // obtain BeingDebug from PEB. If it is set to 1, it will be debugged.
- Mov
- Result, eax
- }
- If (result) exit (0 );
- }
Copy code
Figure 2
2. You can clearly determine that the TLS callback function is executed before the program is executed through a pop-up window. In the above Code, the section ". CRT $ XLB" for creating a TLS segment has the following meanings:
. CRT indicates that the C RunTime mechanism is used. In the XLB behind $, X indicates a random identifier, L indicates a TLS callback section, and B can be replaced with any letter from B to Y, but cannot use ". CRT $ XLA "and". CRT $ XLZ ", because". CRT $ XLA "and". CRT $ XLZ "is used for tlssup. obj.
If you want to define multiple TLS callback functions, you can
PIMAGE_TLS_CALLBACK p_thread_callback = tls_callback;
Changed:
PIMAGE_TLS_CALLBACK p_thread_callback [] = {tls_callback_1, tls_callback_2, tls_callback_3, 0 };
Note:
In this way, the TLS implementation is invalid under VC6.0. 3. The reason is the TLSSUP in VC6. OBJ has a problem. It defines the first item of the callback table, and the value 0 or 0 indicates that the callback table ends. Therefore, all functions we add will not be called.
Figure 3
If you have to implement TLS in VC6.0, you can write TLSSUP. OBJ as follows:
Create a console project, create a tlssup. c file, and add the file to the project.
Right-click the tlssup. c file, select Setting [settings]-> C/C ++-> Gategory-> recomliled Headers [pre-compiled header files]-> Not using precompiled headers [pre-compensated Headers Not applicable]. 4
Figure 4
// Tlssup. c code:
- # Include <windows. h> # include <winnt. h> int _ tls_index = 0; 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; extern returns my_tls_callback []; IMAGE_TLS_DIRECTORY32 _ tls_used = {(DWORD) & _ tls_start, (DWORD) & _ tls_end, (DWORD) & _ tls_index, (DWORD) my_tls_callback, 0, 0 };
Then, define my_tls_callbackt in other CPP files:
Extern "C" PIMAGE_TLS_CALLBACK my_tls_callback [] = {my_tls_callback1, 0 };
There can be multiple callbacks, but you must add an empty item at the end. Otherwise, an error may occur.
0 × 03 implementation results
For the preceding DEMO1, compile and run the command to view the effects of different loads:
Run the program directly after compiling with VS2010, for example, 2;
Use the built-in debugger of VS2010 to load and debug the program, and the process exits directly;
Figure 5 Use OllyDbg to load program debugging and exit the process;
Figure 5
Of course, the final anti-debugging effect depends on the anti-debugging code in the TLS callback function.
0 × 04 Assembly implementation
The compilation of tasks that can be done by advanced languages can also be done by nature. A Demo of the compilation implementation is provided for reference:
- . 386
- . Model flat, stdcall
- Option casemap: none
-
- Include \ masm32 \ include \ windows. inc
- Include \ masm32 \ include \ user32.inc
- Include \ masm32 \ include \ kernel32.inc
- Include \ masm32 \ include \ ntdll. inc
- Includelib \ masm32 \ lib \ user32.lib
- Includelib \ masm32 \ lib \ kernel32.lib
- Includelib \ masm32 \ lib \ ntdll. lib
-
- . Const
- TLS_CallBackStart dd TlsCallBack0
- SzInNormal db 'normal running', 0
- SzTitle db 'anti-debug', 0
- SzInTls db 'breakpoint settings error', 0
- SzResult db 'cannot write back to the modified register ', 0
-
- PUBLIC _ tls_used
- _ Tls_used IMAGE_TLS_DIRECTORY <TLS_Start, TLS_End, dwTLS_Index, TLS_CallBackStart, 0,?>
-
- . Data?
- DwTLS_Index dd?
- DwResult dd?
-
- OPTION DOTNAME
- ; Define a TLS Section
- . Tls SEGMENT
- TLS_Start LABEL DWORD
- Dd 0100 h dup ("slt .")
- TLS_End LABEL DWORD
- . Tls ENDS
- OPTION NODOTNAME
-
- . Code
- ; TLS callback function
- TlsCallBack0 proc Dllhandle: LPVOID, dwReason: DWORD, lpvReserved: LPVOID
- Mov eax, dwReason
- Cmp eax, DLL_PROCESS_ATTACH; called during loading
- Jnz ExitTlsCallBack0
- Invoke GetCurrentProcessId
- Invoke OpenProcess, PROCESS_ALL_ACCESS, NULL, eax
- Invoke CheckRemoteDebuggerPresent, eax, addr dwResult
- Cmp dword ptr dwResult, 0
- Jne _ found
- Jmp ExitTlsCallBack0
- _ Found:
- ; Invoke MessageBox, NULL, addr szInTls, addr szTitle, MB_ICONWARNING
- Invoke GetCurrentThread
- Invoke NtSetInformationThread, eax, 11 H, NULL, NULL
- ; Invoke MessageBox, NULL, addr szResult, addr szTitle, MB_ICONWARNING
- Mov eax, ebx
-
- ExitTlsCallBack0:
- Mov dword ptr [TLS_Start], 0
- Xor eax, eax
- Inc eax
- Ret
-
- TlsCallBack0 endp
-
- Start:
- Invoke MessageBox, NULL, addr szInNormal, addr szTitle, MB_ OK
- Invoke ExitProcess, 1
- End Start
0 × 05 anti-debugging strategy
Several breakthrough methods are provided for TLS anti-debugging. [Note: For case-free and non-Other PE encryption environments]:
1. Use the modified version of Ollydbg. Take ShoutBoy's Jiack OD as an example to load the program and stop it at the TLS callback function entry point. Then you can modify the code, skip the anti-debugging part, save the program file, and then load it with the common OD. 6
Figure 6
2. Manually erase TLS anti-debugging, use IDA to load the program, and find the TlsCallback_0 Function in the Function WIndow. 7:
Function segment:. text
Location: 00401190 [the converted file offset is 590]
Length: 44 [10 to 68 bytes]
Figure 7
The conversion result shows that the file offset is 590 and the length is 68 bytes. Use the C32asm and other hexadecimal editor to fill in the hexadecimal code with 00. 8
Figure 8
When the program is executed, only the second window is displayed. Load the OD, and the anti-debugging part of the TLS callback function has been skipped to reach the EP. 9
Figure 9
0 × 06 one-point extension
The TLS callback function is used to execute the Anti-Debug function before the debugger is loaded to protect the software from malicious modification. The key part is the coding of the specific Anti-debugging part. For example, traditional breakpoint detection, Process detection, and debugger detection. Then, in order to better implement the Anti-debugging effect, encryption can be performed on the input and output tables in a way similar to the encryption shell to protect TLS code from being easily deleted.