【逆向工程核心原理:TLS回调函数】

news2024/9/21 4:34:38

TLS

代码逆向分析领域中,TLS(Thread Local Storage,线程局部存储)回调函数(Callback Function)常用反调试。TLS回调函数的调用运行要先于EP代码的执行,该特征使它可以作为一种反调试技术的使用。

TLS是各线程的独立的数据存储空间,使用TLS技术可在线程内部独立使用或修改进程的全局数据或静态数据,就像对待自身的局部变量一样。

  • PE中的TLS
    若在编程中启用了TLS功能,PE头文件中就会设置TLS表(TLS Table)项目
    IMAGE_NT_HEADERS
    IMAGE_OPTIONAL_HEADER
    IMAGE_DATA_DIRECTORY[9]
    在这里插入图片描述上图多了TLS结构的索引,通过这个地址可以找到TLS结构。

看一下TLS结构体定义。
TLS结构有32位和64位两个版本,其属性个数相同,只是属性的长度发生了变化

typedef struct _IMAGE_TLS_DIRECTORY64 {
    ULONGLONG StartAddressOfRawData;
    ULONGLONG EndAddressOfRawData;
    ULONGLONG AddressOfIndex;         // PDWORD
    ULONGLONG AddressOfCallBacks;     // PIMAGE_TLS_CALLBACK *;
    DWORD SizeOfZeroFill;
    union {
        DWORD Characteristics;
        struct {
            DWORD Reserved0 : 20;
            DWORD Alignment : 4;
            DWORD Reserved1 : 8;
        } DUMMYSTRUCTNAME;
    } DUMMYUNIONNAME;

} IMAGE_TLS_DIRECTORY64;




typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;
    DWORD   EndAddressOfRawData;
    DWORD   AddressOfIndex;             // PDWORD
    DWORD   AddressOfCallBacks;         // PIMAGE_TLS_CALLBACK *
    DWORD   SizeOfZeroFill;
    union {
        DWORD Characteristics;
        struct {
            DWORD Reserved0 : 20;
            DWORD Alignment : 4;
            DWORD Reserved1 : 8;
        } DUMMYSTRUCTNAME;
    } DUMMYUNIONNAME;

} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;

通过这个目录表,可以找到TLS结构体,关注这个变量,就可以找到一个数组,数组里是回调函数地址的数组,以全零结尾
在这里插入图片描述

这就是找到了回调函数的地址数组,这里只有一个地址

在这里插入图片描述

TLS回调函数运行时机

所谓TLS回调函数是指,每当创建/终止进程的线程时会自动调用执行的函数。有意思的是,创建进程的主线程时,也会自动调用回调函数,且其调用执行先于EP代码。反调试技术利用的就是TLS回调函数的这一特征。


请注意,创建或终止某线程时,TLS回调函数都会自动调用执行,前后共2次。
执行进程的主线程(运行线程的EP代码)前,TLS回调函数会被先调用执行,许多逆向分析人员将该特征应用于程序的反调试技术。

// IMAGE_TLS_CALLBACK结构
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
    PVOID DllHandle,
    DWORD Reason,
    PVOID Reserved
    );

DllHandle为模块句柄,Reason是调用的原因:

// 进程主线程main执行前调用
#define DLL_PROCESS_ATTACH 1
// main开始执行,main开始创建线程前调用
#define DLL_THREAD_ATTACH 2
// 子线程结束后调用
#define DLL_THREAD_DETACH 3
// 子线程执行完毕,main也结束后调用
#define DLL_PROCESS_ATTACH 0

example:

#include<Windows.h>

// 通知链接器使用TLS
#pragma comment(linker,"/INCLUDE:__tls_used")

void  print_console(const  char* szMsg)
{
	HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	WriteConsole(hStdout, szMsg, strlen(szMsg), NULL, NULL);
 }

void NTAPI TLS_CALLBACK1(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
	char szMsg[80] = { 0, };
	wsprintfA(szMsg, "TLS_CALLBACK1():DllHandle=%X,Reason=%d\n", DllHandle, Reason);
	print_console(szMsg);
}

void NTAPI TLS_CALLBACK2(PVOID DllHandle, DWORD Reason, PVOID Reserved)
{
	char szMsg[80] = { 0, };
	wsprintfA(szMsg, "TLS_CALLBACK2():DllHandle=%X,Reason=%d\n", DllHandle, Reason);
	print_console(szMsg);
}

// 注册TLS函数,.CRT$XLX的作用:CRT表示使用C Runtime 机制,X表示表示名随机,L表示TLS Callback section,X也可以换成B~Y任意一个字符
// 在这里用数组存放TLS回调函数地址
#pragma data_seg(".CRT$XLX")
PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK1,TLS_CALLBACK2,0 };

#pragma data_seg()

DWORD WINAPI ThreadProc(LPVOID lPram) {
	print_console("ThreadProc() start\n");
	
	print_console("ThreadProc() end\n");
	
	return 0;
}

int main(void)
{
	
	HANDLE hThread = NULL;

	print_console("main()start\n");
	
	hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
	
	WaitForSingleObject(hThread, 60 * 1000);
	
	CloseHandle(hThread);

	print_console("main() end\n");
	system("pause");
	return 0;
}

在这里插入图片描述

调试TLS

开始调试前,要设置System breakpoint
2.x也可以直接设置TLS ballback
在这里插入图片描述

断下后,去AddressofCallback去找存放回调函数地址的数组,这里写了一个数据0x401000

在这里插入图片描述
在这里就是TLS回调函数内容
在这里插入图片描述

手工添加TLS

调试可以,也可以通过修改PE文件,给没有TLS的程序添加TLS回调函数

  1. 扩大最后一个节
  2. 修改PE头,保证扩展正确
  3. 增加TLS的目录表
  4. 增加TLS的结构体(放在扩大的节里)
  5. 根据结构体所指的数组中的地址,添加TLS回调函数代码

1、2:扩大节、修改PE节表
在这里插入图片描述

3、添加TLS目录表
在这里插入图片描述

4、去RVA=C200处,添加TLS结构体内容
在这里插入图片描述

5、添加TLS函数代码
在这里插入图片描述

  • 结果
    载入od调试,就是触发这个弹窗
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/536087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【经验总结】你想知道的BGA焊接问题都在这里

BGA是一种芯片封装的类型&#xff0c;英文 (Ball Grid Array)的简称&#xff0c;封装引脚为球状栅格阵列在封装底部&#xff0c;引脚都成球状并排列成一个类似于格子的图案&#xff0c;由此命名为BGA。 主板控制芯片诸多采用此类封装技术&#xff0c;采用BGA技术封装的内存&am…

聚焦 TimescaleDB VS TDengine 性能对比报告,五大场景全面分析写入与查询

基于第三方基准性能测试平台 TSBS&#xff08;Time Series Benchmark Suite&#xff09; 标准数据集&#xff0c;TDengine 团队分别就 TSBS 指定的 DevOps 中 cpu-only 五个场景&#xff0c;对时序数据库&#xff08;Time Series Database&#xff0c;TSDB&#xff09;Timescal…

ACT:非对称协同训练的半监督域自适应医学图像分割

文章目录 ACT: Semi-supervised Domain-Adaptive Medical Image Segmentation with Asymmetric Co-training摘要本文方法实验结果 ACT: Semi-supervised Domain-Adaptive Medical Image Segmentation with Asymmetric Co-training 摘要 作者建议以统一的方式利用标记的源域和…

nginx实现正向代理

1.下载nginx nginx: download 选择自己需要的版版本下载下来 2.解压文件修改ngixn.conf配置文件 events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout…

MySQL基础(三十六)其他数据库日志

千万不要小看日志。很多看似奇怪的问题&#xff0c;答案往往就藏在日志里。很多情况下&#xff0c;只有通过查看日志才能发现问题的原因&#xff0c;真正解决问题。所以&#xff0c;一定要学会查看日志&#xff0c;养成检查日志的习惯&#xff0c;对提升你的数据库应用开发能力…

【星戈瑞】Sulfo-CY3-COOH磺化/水溶性Cyanine3羧酸1121756-11-3

Sulfo-CY3 COOH是一种荧光染料&#xff0c;其分子结构中含有COOH官能团&#xff0c;最大吸收波长为550纳米左右&#xff0c;可以通过分光光度计等设备进行检测。Sulfo-CY3 COOH是一种带有羧基的荧光染料&#xff0c;可以与含有氨基的生物分子通过偶联反应形成共价键&#xff0c…

TMP的阴影性能如何

1&#xff09;TMP的阴影性能如何 ​2&#xff09;CommandBuffer.DrawMeshInstanced无法画阴影问题 3&#xff09;Unity编辑器在Require大量加载Lua文件时&#xff0c;经常报出not enough memory 4&#xff09;场景制作的时候&#xff0c;2D资源受后处理调色影响比较大 这是第33…

JVM面试题(一)

JVM内存分哪几个区&#xff0c;每个区的作用是什么? java虚拟机主要分为以下几个区: JVM中方法区和堆空间是线程共享的&#xff0c;而虚拟机栈、本地方法栈、程序计数器是线程独享的。 &#xff08;1&#xff09;方法区&#xff1a; a. 有时候也成为永久代&#xff0c;在该区内…

开始梳理大学课程体系(一)--万字C语言总结上

C语言 前言第一章 初识C语言1.1 C语言的起源1.2 选择C语言的理由1.3 使用C语言的7个步骤 第二章 数据和C2.1 变量和常量2.1.1变量定义2.1.2 常量的定义 2.2 数据类型关键字 第三章 运算符、表达式和语句3.1 基本运算符3.1.1 算术运算符3.1.2 关系运算符3.1.3 逻辑运算符3.1.3 赋…

关于接口可维护性的一些建议 | 京东云技术团队

作者&#xff1a;D瓜哥 在做新需求开发或者相关系统的维护更新时&#xff0c;尤其是涉及到不同系统的接口调用时&#xff0c;在可维护性方面&#xff0c;总感觉有很多地方差强人意。一些零星思考&#xff0c;抛砖引玉&#xff0c;希望引发更多的思考和讨论。总结了大概有如下几…

TOB企业生态体系构建的核心要素有哪些?

To B市场作为一个非常庞大的领域&#xff0c;其复杂度和多元化水平&#xff0c;要远远要高于针对于消费者群体推进的市场。尤其近年来&#xff0c;消费互联网成为过去式&#xff0c;爆发式增长的时代结束&#xff0c;让资本、媒体的目光开始聚焦到以B2B企业所代表的产业互联网身…

人工智能与机器人|机器学习

原文链接&#xff1a; https://mp.weixin.qq.com/s/PB_n8woxdsWPtrmL8BbehA 机器学习下包含神经网络、深度学习等&#xff0c;他们之间的关系表示如图2-7所示。 图2-7 关系图 那么什么是机器学习、深度学习、他们的区别又是什么呢&#xff1f; 2.7.1 什么是机器学习&#x…

Unity中Camera.main和Camera.current的区别

在Unity中&#xff0c;Camera.main和Camera.current都是用来获取相机&#xff0c;那到底有什么区别呢&#xff1f; 一、异同及注意事项 1、相同点&#xff1a; Camera.main和Camera.current都是用于获取相机的属性。它们都是静态属性&#xff0c;可以通过Camera类访问。它们…

【Redis】Redis set类型实现点赞功能

文章目录 set 数据类型介绍不排序实现排序实现 set 数据类型介绍 Redis中的set类型是一组无序的字符串值。 set通过其独特的数据结构和丰富的命令提供了在存储和处理集合元素方面的一些非常有用的功能。下面列出了主要的set类型命令&#xff1a; SADD key member1 [member2]&a…

国产 API 工具天花板,用来搞项目真的不错

一、API爆炸的时代 随着最近行业的移动化、物联网化、数字化转型、微服务等多种概念的提出&#xff0c;对应的 API 数量已经呈现出爆炸式增长&#xff0c;由此带来的问题就是前后端的接口对接问题越来越来突出&#xff0c;我们能很难找到一个合适的技术工具提高我们的效率。由此…

irq_domain msi_domain 的 使用和关系

文章目录 如何创建一个 irq_domain如何创建一个 msi_domainirq domain 和 msi domain 的关系MSI对IRQdomain打的补丁变量结构体API初始化时的API申请IRQ时的API 实例 GICV3-ITS & GICV3-ITS-PCI 相关结构体变量所在文件 如何创建一个 irq_domain 内核文档说,我们可以调用如…

基于 FPGA 的彩色图像灰度化的设计实现

文章目录 前言一、系统整体设计二、各模块的功能三、彩色图像灰度化处理模块的设计1.基本原理2.彩色图像灰度化处理方法介绍方法 1&#xff1a;分量法方法 2&#xff1a;最大值法方法 3&#xff1a;平均值法平均值法的实现方法 4 加权平均法加权平均法的实现rgb2gray 模块rgb2g…

LeetCode965. 单值二叉树,100. 相同的树

965. 单值二叉树&#xff0c;100. 相同的树 965描述示例解题思路以及代码 100描述示例解题思路以及代码 965 描述 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff1b;否则返回 fals…

获得GitHub Copilot并结合VS Code使用

一、什么是GitHub Copilot GitHub Copilot是一种基于AI的代码生成工具。它使用OpenAI的GPT&#xff08;生成式预训练Transformer&#xff09;技术来提供建议。它可以根据您正在编写的代码上下文建议代码片段甚至整个函数。 要使用GitHub Copilot&#xff0c;您需要在编辑器中…

(四)Photon Voice2 的使用

一、入门 1.Voice简介 Photon Voice 2 是一个 SDK&#xff0c;可以轻松地向 Unity 应用程序添加高质量的低延迟语音聊天。它建立在 Photon Realtime 之上&#xff0c;并继承了它的所有功能&#xff0c;包括配对和兴趣小组。客户端加入房间并创建传出流&#xff08;本地语音&a…