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反调试的更多相关文章

  1. WIN10 X64下通过TLS实现反调试

    目录(?)[-] TLS技术简介 1 TLS回调函数 2 TLS的数据结构 具体实现及原理 1 VS2015 X64 release下的demo 2 回调函数的具体实现 21 使用IsDebugger ...

  2. TLS回调函数以及反调试简单使用

    TLS回调函数以及反调试简单使用 0x00  TLS介绍 TLS(Thread Local Storage,线程局部储存),主要用于给线程独立的传值,由于线程不拥有进程的资源,所以几个同一进程的几个线 ...

  3. 基于TLS的反调试技术

    TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...

  4. 通过TLS回调函数的反调试

    下面是TLS数据结构的定义 typedef struct _IMAGE_TLS_DIRECTORY { DWORD StartAddressOfRawData; DWORD EndAddressOfR ...

  5. Windows 32位-调试与反调试

    1.加载调试符号链接文件并放入d:/symbols目录下. 0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/s ...

  6. C/C++ 程序反调试的方法

    C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...

  7. Windows反调试技术(下)

    OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...

  8. 使用KRPano资源分析工具强力加密KRPano项目(XML防破解,切片图保护,JS反调试)

    软件交流群:571171251(软件免费版本在群内提供) krpano技术交流群:551278936(软件免费版本在群内提供) 最新博客地址:blog.turenlong.com 限时下载地址:htt ...

  9. 反调试技术常用API,用来对付检测od和自动退出程序

    在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...

随机推荐

  1. Linux ----> debian中环境的常见配置

    环境: (debian 9)/(lubuntu18.0.4+virtualbox) 1.配置下载源: gedit /etc/apt/sources.list #163 deb http://mirro ...

  2. java异常:java.lang.NullPointerException

    /** * 功能:空指针异常测试 */ /* Object[] parameters1=null; if(parameters1.length>0&&parameters1!=n ...

  3. 利用adb安装apk

    下载adb 网上资源很多,资源自寻. 配置环境变量 先加变量,后加入path.网上很多,不赘述. 安装apk 打开cmd,确保adb已经连接设备 adb install -r <拖动文件至cmd ...

  4. LOJ6072苹果树

    虽然结合了很多算法,但是一步一步地推一下还不算太难的一道题. 首先考虑枚举枚举有用的苹果的集合,然后去算生成树个数. 先考虑怎么计算生成树个数. 发现可以使用matrix-tree. 所有有用点可以和 ...

  5. java类的设计原则

    1.内聚性 类应该描述一个单一的实体,所有的类操作应该在逻辑上相互配合,支持一个连贯性的目标.例如:学生和教职工属于不同的实体,应该定义两个类. 2.一致性 要遵循一定的设计风格和命名习惯.给类.方法 ...

  6. 第二阶段——个人工作总结DAY08

    1.昨天做了什么:昨天就时间轴的问题,已经实现了界面的显示. 2.今天打算做什么:打算继续学习<第一行代码>中关于异步任务,多线程,访问网络等后台的知识. 3.遇到的困难:还不太懂具体的步 ...

  7. call、apply、bind三者的区别

    先构造函数let xiaowang={ name1:"小王", age:", sex:"男", say:function(){ console.log ...

  8. Session重点整理

    首先明确几个概念 (1)JSessionID:通过tomcat运行的Java项目,为新用户生成的随机字符串.(应该是tomcat设置的,我没试过别的服务器,如有错误请指正) (2)Session请求( ...

  9. Qt动态布局

    QVBoxLayout *m_pvLayout = NULL: QWidget *m_pWidgetPlay = NULL: m_pvLayout = new QVBoxLayout(this); m ...

  10. 解决win10打开组策略弹出管理模板对话框问题

    今天win10企业版更新完系统,打开组策略编辑器时弹出管理模板对话框问题 1.问题描述 打开组策略编辑器时弹出管理模板对话框问题 2.解决方法 1)window+x 打开命令提示符(管理员) 2)输入 ...