TLS反调试
0x01 TLS反调试简介
TLS(Thread Local Storage)原本的目的是解决多线程程序中变量同步的问题。线程本身有独立于其他线程的栈空间,因此线程中的局部变量不用考虑同步问题。多线程同步问题在于对全局变量的访问,TLS在操作系统的支持下,通过把全局变量打包到一个特殊的节,当每次创建线程时把这个节中的数据当做副本,拷贝到进程空闲的地址空间中。以后线程可以像访问局部变量一样访问该异于其他线程的全局变量的副本,而不用加同步控制。
基于TLS的反调试,原理实为在实际的入口点代码执行之前执行检测调试器代码,实现方式便是使用TLS回调函数实现。通过TLS反调试实现的效果。
0x02 实现原理
(1)TLS回调函数
当用户选择使用自己编写的回调函数时,在应用程序初始化阶段,系统将要调用一个由用户编写的回调函数以完成相应的初始化以及其他的一些初始化工作。此调用将在程序真正开始执行到入口点之前就完成,以保证程序执行的正确性。
TLS回掉函数:
void NTAPI TLS_CALLBACK(PVOID DllHandle, DWORD Reason, PVOID Reserved);
第一个参数为模块句柄,即加载地址,第二个参数为调用原因,调用原因有四种:
#define DLL_PROCESS_ATTACH 1
#define DLL_THREAD_ATTACH 2
#define DLL_THREAD_DETACH 3
#define DLL_PROCESS_ATTACH 0
主线程调用main前调用TLS回调函数,调用原因为DLL_PROCESS_ATTACH
子线程启动前调用TLS,原因为DLL_THREAD_ATTACH
子线程结束后调用TLS,原因为DLL_THREAD_DETACH
主线程结束后调用TLS的原因为DLL_PROCESS_DETACH
TLS回掉函数注册:
PIMAGE_TLS_CALLBACK _tls_callback[] = { SH_TLS_CALLBACKA, SH_TLS_CALLBACKB, 0 };
(2)TLS数据所在的节(Section)
PE文件中,专门为TLS数据开辟了一个节存储,它的RVA和大小记录在PE文件可选头的数据目录表中:IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]。
DataDirectory的数据结构:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
(3)TLS数据段的建立
要使用TLS,必须为TLS数据单独建一个数据段,用相关数据填充此段,并通知链接器为TLS数据在PE文件头中添加数据。
//linker spec通知链接器PE文件要创建TLS目录,X86和X64有所区别
#ifdef _M_IX86
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:__tls_callback")
#else
#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:_tls_callback")
#endif
//创建TLS段
EXTERN_C
#ifdef _M_X64
#pragma const_seg (".CRT$XLB")
const
#else
#pragma data_seg (".CRT$XLB")
#endif
/*
注册TLS函数
.CRT$XLX的作用
CRT表示使用C Runtime 机制
X表示表示名随机
L表示TLS Callback section
X也可以换成B~Y任意一个字符
*/
0x03 源代码
// TLS反调试.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <Windows.h>
#include <tchar.h> #pragma comment(lib,"ntdll.lib") extern "C" NTSTATUS NTAPI NtQueryInformationProcess(HANDLE hProcess, ULONG InfoClass, PVOID Buffer, ULONG Length, PULONG ReturnLength); #define NtCurrentProcess() (HANDLE)-1 void NTAPI __stdcall SH_TLS_CALLBACKA(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
if (IsDebuggerPresent())
{
MessageBoxA(NULL, "TLS_CALLBACK: Debugger Detected!", "TLS Callback", MB_OK);
// ExitProcess(1);
}
else
{
MessageBoxA(NULL, "TLS_CALLBACK: No Debugger Present!...", "TLS Callback", MB_OK);
}
} void NTAPI __stdcall SH_TLS_CALLBACKB(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
HANDLE DebugPort = NULL;
if (!NtQueryInformationProcess(
NtCurrentProcess(),
7, // ProcessDebugPort
&DebugPort, // If debugger is present, it will be set to -1 | Otherwise, it is set to NULL
sizeof(HANDLE),
NULL))
{
if (DebugPort)
{
MessageBoxA(NULL, "TLS_CALLBACK2: Debugger detected!", "TLS callback", MB_ICONSTOP);
} else
{
MessageBoxA(NULL, "TLS_CALLBACK2: No debugger detected", "TLS callback", MB_ICONINFORMATION);
}
}
} //linker spec通知链接器PE文件要创建TLS目录,X86和X64有所区别
#ifdef _M_IX86
#pragma comment (linker, "/INCLUDE:__tls_used")
#pragma comment (linker, "/INCLUDE:__tls_callback")
#else
#pragma comment (linker, "/INCLUDE:_tls_used")
#pragma comment (linker, "/INCLUDE:_tls_callback")
#endif
//创建TLS段
EXTERN_C
#ifdef _M_X64
#pragma const_seg (".CRT$XLB")
const
#else
#pragma data_seg (".CRT$XLB")
#endif
//end linker //tls import定义多个回调函数
PIMAGE_TLS_CALLBACK _tls_callback[] = { SH_TLS_CALLBACKA, SH_TLS_CALLBACKB, 0 };
#pragma data_seg ()
#pragma const_seg ()
//end int main()
{ MessageBoxA(NULL, "SH TLS ANTI-DEBUG", "MAIN", MB_OK);
return 0; }
TLS反调试的更多相关文章
- WIN10 X64下通过TLS实现反调试
目录(?)[-] TLS技术简介 1 TLS回调函数 2 TLS的数据结构 具体实现及原理 1 VS2015 X64 release下的demo 2 回调函数的具体实现 21 使用IsDebugger ...
- TLS回调函数以及反调试简单使用
TLS回调函数以及反调试简单使用 0x00 TLS介绍 TLS(Thread Local Storage,线程局部储存),主要用于给线程独立的传值,由于线程不拥有进程的资源,所以几个同一进程的几个线 ...
- 基于TLS的反调试技术
TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...
- 通过TLS回调函数的反调试
下面是TLS数据结构的定义 typedef struct _IMAGE_TLS_DIRECTORY { DWORD StartAddressOfRawData; DWORD EndAddressOfR ...
- Windows 32位-调试与反调试
1.加载调试符号链接文件并放入d:/symbols目录下. 0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/s ...
- C/C++ 程序反调试的方法
C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...
- Windows反调试技术(下)
OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...
- 使用KRPano资源分析工具强力加密KRPano项目(XML防破解,切片图保护,JS反调试)
软件交流群:571171251(软件免费版本在群内提供) krpano技术交流群:551278936(软件免费版本在群内提供) 最新博客地址:blog.turenlong.com 限时下载地址:htt ...
- 反调试技术常用API,用来对付检测od和自动退出程序
在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...
随机推荐
- GROUP by 方法 C#
1.用两层循环计算,前提条件是数据已经按分组的列排好序的. DataTable dt = new DataTable(); dt.Columns.AddRange(new DataColumn[] { ...
- 小程序获取openid 小程序授权
小程序获取openid 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. wx.login(Object object) 调用接口获取登录凭证(cod ...
- ubuntn 安装python3 及 django及pip3
1.sudo apt-get install python3-pip 安装pip3 2.sudo pip3 install django 通过pip3安装django 3. sudo apt ...
- IDEA中部署tomcat,运行JSP文件,编译后的JSP文件存放地点总结
首先保证你正常部署了Tomcat,并且正常在浏览器中运行了JSP文件. 那么Tomcat编译后的JSP文件(_jsp.class 和 _jsp.java)的存放地点: (一)一般存放在你安装的Tomc ...
- loj#2020. 「AHOI / HNOI2017」礼物
题意:给定xy数组求 \(\sum_{i=0}^{n-1}(x_i+y_{(i+k)\modn}+c)^2\) 题解:先化简可得 \(n*c^2+2*\sum_{i=0}^{n-1}x_i-y_i+\ ...
- 【PowerDesigner】【2】将工具栏显示出来
问题:我的软件一打开,没有工具栏 解决方案:Tools→Customize Menus and Tools→Palette→Close 参考文档: PowerDesigner如何将消失的工具栏显示出来 ...
- js对象合并
实现js对象大合并,ES6之前就只有循环遍历咯.可以用ES6的话可以用Object.assign(). 以下是Object.assign()示例: var o1 = { a: 1 }; var o2 ...
- js中去掉字符串的空格、回车换行
//例如下面这个json串,中间的\n表示换行 var str = "{' retmsg':'success ',\n' trans_date':' 20170906'}"; co ...
- Git将本地项目上传到GitHub
本文转载于:https://segmentfault.com/a/1190000011909294 https://www.cnblogs.com/cxk1995/p/5800196.html 我们使 ...
- 牛客第二场Dmoney
链接:https://www.nowcoder.com/acm/contest/140/D 来源:牛客网 题目描述 White Cloud has built n stores numbered to ...