Windows逆向工程提升之IMAGE_TLS_DIRECTORY

  • 公开视频 -> 链接点击跳转公开课程
  • 博客首页 -> ​​​链接点击跳转博客主页

目录

TLS的作用

TLS的实现

静态 TLS​​

动态 TLS​​

内部实现

回调机制

TLS Directory 的结构


TLS的作用

  • TLS (Thread Local Storage) 是一种用于为多线程应用程序提供线程独立存储空间的机制。在多线程程序中,每个线程可以有自己独特的一组数据,互不干扰。

  • 保存线程状态数据(如线程上下文)。

  • 避免线程之间共享全局变量导致的竞争和冲突。

  • 为每个线程提供独立的缓存、统计等,不需要使用锁机制。

TLS的实现

静态 TLS​​

在编译时分配空间(通过 __declspec(thread) 或 thread_local 关键字)。

  • 通过使用 __declspec(thread) 声明 TLS 数据。

  • 静态 TLS 在编译时分配,系统会自动初始化和清理。

  • 适用于预定义的 TLS 数据场景。

  • #include <windows.h>  
    #include <stdio.h>  // 声明线程局部存储变量  
    __declspec(thread) int tlsData = 0;  // 线程函数  
    DWORD WINAPI ThreadProc(LPVOID lpParameter) {  // 为当前线程初始化 TLS 数据  tlsData = (int)(size_t)lpParameter;  // 使用 TLS 数据  printf("Thread %d: TLS Data = %d\n", GetCurrentThreadId(), tlsData);  // 模拟工作  Sleep(1000);  return 0;  
    }  int main() {  // 创建线程  const int threadCount = 3;  HANDLE threads[threadCount];  for (int i = 0; i < threadCount; ++i) {  threads[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)(size_t)(i + 1), 0, NULL);  }  // 等待线程完成  WaitForMultipleObjects(threadCount, threads, TRUE, INFINITE);  // 清理句柄  for (int i = 0; i < threadCount; ++i) {  CloseHandle(threads[i]);  }  return 0;  
    }

动态 TLS​​

运行时通过 API(如 TlsAlloc, TlsFree)动态管理。

  • 使用 TlsAlloc() 分配一个 TLS 索引,动态管理每个线程的 TLS 数据。

  • 每个线程负责分配、获取和释放自己的数据。

#include <windows.h>  
#include <stdio.h>  // 全局 TLS 索引  
DWORD g_TlsIndex;  // 线程函数  
DWORD WINAPI ThreadProc(LPVOID lpParameter) {  // 为当前线程分配 TLS 数据  int* tlsData = (int*)malloc(sizeof(int));  *tlsData = (int)(size_t)lpParameter; // 将线程传递的参数放入 TLS 数据  TlsSetValue(g_TlsIndex, tlsData);  // 使用 TLS 数据  printf("Thread %d: TLS Data = %d\n", GetCurrentThreadId(), *tlsData);  // 模拟工作  Sleep(1000);  // 释放 TLS 数据  free(tlsData);  return 0;  
}  int main() {  // 1. 分配 TLS 索引  g_TlsIndex = TlsAlloc();  if (g_TlsIndex == TLS_OUT_OF_INDEXES) {  printf("Failed to allocate TLS Index\n");  return 1;  }  // 2. 创建线程  const int threadCount = 3;  HANDLE threads[threadCount];  for (int i = 0; i < threadCount; ++i) {  threads[i] = CreateThread(NULL, 0, ThreadProc, (LPVOID)(size_t)(i + 1), 0, NULL);  }  // 等待线程完成  WaitForMultipleObjects(threadCount, threads, TRUE, INFINITE);  // 3. 清理  for (int i = 0; i < threadCount; ++i) {  CloseHandle(threads[i]);  }  // 释放 TLS 索引  TlsFree(g_TlsIndex);  return 0;  
}

内部实现

  • 每个线程都会分配一个线程环境块(Thread Environment Block,TEB),TEB 结构中包含一个用于存储 TLS 数据的区域:

  • 动态 TLS 的数据存储在 TEB 的 TlsSlots 数组中,每个槽对应一个 TlsAlloc() 返回的索引。

  • 静态 TLS 的数据在程序加载时由系统内存分配,并初始化到对应的线程。

    特性动态分配 TLS (Win32 API)静态分配 TLS (__declspec(thread))
    易用性手动管理,需自己分配和释放 TLS 数据自动完成线程初始化和销毁,使用方便
    性能每个访问可能需要一层索引查找,性能稍低编译时分配,直接访问内存,性能高
    生命周期动态分配,程序员负责管理生命周期由操作系统控制
    灵活性可以动态创建任意数量的 TLS只能事先声明固定的 TLS 变量

回调机制

  • TLS 提供线程生命周期管理的机制:TLS 回调函数。这些回调函数会在以下情况下被调用:

  • 线程附加(Thread Attach):当线程启动时,初始化 TLS 数据。

  • 线程分离(Thread Detach):当线程结束时,清理 TLS 数据。

#include <windows.h>  #ifdef _WIN64  
#pragma comment (linker, "/INCLUDE:_tls_used")  
#else  
#pragma comment (linker, "/INCLUDE:__tls_used")  
#endif  //#pragma comment (linker, "/INCLUDE:pTLS_CALLBACKs")  _declspec(thread) DWORD dw = 0x12345678;
_declspec(thread) DWORD dw1 = 0xCCCCCCCC;void NTAPI TLS_CALLBACK(PVOID DllHandle, DWORD Reason, PVOID Reserved) //TLS callback function  
{}void NTAPI TLS_CALLBACK1(PVOID DllHandle, DWORD Reason, PVOID Reserved) //TLS callback function  
{}#ifdef _WIN64  
#pragma const_seg(".CRT$XLB")  
EXTERN_C const
#else  
#pragma data_seg(".CRT$XLX")  
#endif  PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK, TLS_CALLBACK1,0 };#ifdef _WIN64  
#pragma const_seg()  
#else  
#pragma data_seg()  
#endif  int main(void)
{return 0;
}

TLS Directory 的结构

TLS 数据由 IMAGE_TLS_DIRECTORY 结构描述,其定义如下

  typedef struct _IMAGE_TLS_DIRECTORY {  ULONGLONG StartAddressOfRawData;   // TLS 数据起始地址(RVA)  ULONGLONG EndAddressOfRawData;     // TLS 数据结束地址(RVA)  ULONGLONG AddressOfIndex;          // TLS 索引表地址  ULONGLONG AddressOfCallBacks;      // TLS 回调数组地址  DWORD SizeOfZeroFill;              // 初始化为零的大小  DWORD Characteristics;            // 保留字段(通常为 0)  
} IMAGE_TLS_DIRECTORY64, *PIMAGE_TLS_DIRECTORY64;  
  • StartAddressOfRawData:

    • 指的是 TLS 初始化数据段的起始地址。

    • 这部分数据会复制到每个线程的 TLS 段中,作为初始化状态。

  • EndAddressOfRawData:

    • TLS 初始化数据段的结束地址。

  • AddressOfIndex:

    • 指向一个 TLS 索引(通常位于线程环境块 TEB 中),用于标识当前线程的 TLS 段。

  • AddressOfCallBacks:

    • 指向一个回调函数指针数组。在线程创建或退出时,这些回调函数会依次被调用。

  • SizeOfZeroFill:

    • 表示未初始化数据的大小,如果存在,则这部分数据会在 TLS 数据段初始化时清零。

  • Characteristics:

    • 通常保留字段,值通常为 0。

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

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

相关文章

云效流水线Flow使用记录

概述 最近在频繁使用阿里云云效的几款产品&#xff0c;如流水线。之前写过一篇&#xff0c;参考云效流水线缓存问题。 这篇文章来记录更多问题。 环境变量 不管是云效流水线Flow还是应用交付AppStack&#xff08;基于流水线&#xff0c;后文不再赘述&#xff09;&#xff0…

Android中获取控件尺寸进阶方案

在Android开发中,很多场景都需要获取控件(View)的宽高信息,比如动态布局调整、动画效果实现等。然而,直接在Activity的onCreate()中调用控件的getWidth()或getHeight()`方法,得到结果却是0,因为控件还没完成布局测量。 本文总结了几种获取控件大小的实用方法,并对各方…

android 输入系统

一、输入系统的核心角色与分层架构 Android 输入系统的本质是桥梁&#xff1a;一端连接硬件驱动产生的原始事件&#xff0c;另一端将事件精准派发给应用窗口。整个过程涉及三层架构和多个关键组件&#xff0c;可类比为 “快递分拣系统”&#xff1a; 1. 硬件与内核层&#xf…

ubuntu中,c和c+程序,预编译、编译、链接和运行命令

目录 安装编译器一.c编译运行&#xff08;粗暴简单&#xff09;1.编写 C 程序&#xff1a;2. 预处理&#xff1a;3.编译&#xff1a;4. 汇编&#xff1a;5. 链接&#xff1a;6.运行 二.c编译运行&#xff08;粗暴简单&#xff09;1.编写 C 程序&#xff1a;2.预处理&#xff1a…

【FastAPI】--2.进阶教程(一)

【FastAPI】--基础教程-CSDN博客 app.get和post的参数&#xff1a; 参数类型说明pathstr路由路径&#xff08;如 "/marks"&#xff09;&#xff0c;必填。response_modelType[T]定义响应数据的模型&#xff08;如 percent&#xff09;&#xff0c;会自动校验和序列…

KT6368A通过蓝牙芯片获取手机时间详细说明,对应串口指令举例

一、功能简介 KT6368A双模蓝牙芯片支持连接手机&#xff0c;获取手机的日期、时间信息&#xff0c;可以同步RTC时钟 1、无需安装任何app&#xff0c;直接使用系统蓝牙即可实现 2、同时它不影响音频蓝牙&#xff0c;还支持一些简单的AT指令进行操作 3、实现的方式&#xff1…

【平面波导外腔激光器专题系列】用于光纤传感的低噪声PLC外腔窄线宽激光器

----翻译自Mazin Alalusi等人的文章 摘要 高性价比的 1550 nm DWDM平面外腔 &#xff08;PLANEX&#xff09; 激光器是干涉测量、布里渊、LIDAR 和其他光传感应用的最佳选择。其线宽<3kHz、低相位/频率噪声和极低的RIN。 简介 高性能光纤分布式传感技术是在过去几年中开发…

企业微信内部网页开发流程笔记

背景 基于ai实现企微侧边栏和工作台快速问答小助&#xff0c;需要h5开发&#xff0c;因为流程不清楚摸索半天&#xff0c;所以记录一下 一、网页授权登录 1. 配置步骤 1.1 设置可信域名 登录企业微信管理后台 进入"应用管理" > 选择开发的具体应用 > “网…

WORD 转 PDF 工具:排版 / 图片 / 表格批量转换提升办公效率

各位办公小能手们&#xff0c;今天来聊聊文档工具里的WORD转PDF工具&#xff01;这玩意儿到底是干啥的呢&#xff1f;咱来好好说道说道。 先说核心功能。第一个就是格式转换&#xff0c;能把Word文档转换成PDF&#xff0c;不管是格式、排版&#xff0c;还是图片、表格啥的&…

从逆流监测到智慧用电:ADL200N-CT系列单相导轨表赋能家庭绿色能源

在新能源浪潮席卷全球的当下&#xff0c;阳台光伏以及家庭储能&#xff08;户储&#xff09;系统逐渐成为众多追求绿色生活、渴望实现能源自主家庭的新选择。它不仅能有效利用太阳能等清洁能源&#xff0c;还能在用电高峰时段为家庭提供稳定电力支持&#xff0c;降低用电成本。…

std::thread的说明与示例

源于通义千问 在 C 中&#xff0c;std::thread 支持传递多种类型的函数作为线程入口点。你可以传递普通函数、类的成员函数、Lambda 表达式、函数对象&#xff08;仿函数&#xff09;等。以下是详细的说明和示例。 1. 传递普通函数 普通函数是最简单的用法。 示例 #include…

【Day38】

DAY 38 Dataset和Dataloader类 对应5. 27作业 知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图片 import …

RabbitMQ 集群与高可用方案设计(三)

五、高可用方案设计与实现 &#xff08;一&#xff09;负载均衡与代理 1. HAProxy 配置 HAProxy 是一款广泛应用的开源负载均衡器和代理服务器&#xff0c;它能够实现对 RabbitMQ 集群节点的负载均衡和健康检查&#xff0c;有效提高系统的可用性和性能。以下是使用 HAProxy …

机器学习第二十四讲:scikit-learn → 机器学习界的瑞士军刀

机器学习第二十四讲&#xff1a;scikit-learn → 机器学习界的瑞士军刀 资料取自《零基础学机器学习》。 查看总目录&#xff1a;学习大纲 关于DeepSeek本地部署指南可以看下我之前写的文章&#xff1a;DeepSeek R1本地与线上满血版部署&#xff1a;超详细手把手指南 Scikit-…

百度ocr的简单封装

百度ocr地址 以下代码为对百度ocr的简单封装,实际使用时推荐使用baidu-aip 百度通用ocr import base64 from enum import Enum, unique import requests import logging as logunique class OcrType(Enum):# 标准版STANDARD_BASIC "https://aip.baidubce.com/rest/2.0…

Ubuntu20.04 gr-gsm完整安装教程

gr-gsm完整安装教程 安装gnuradio3.8安装依赖项指定gnuradio源安装gnuradio 安装gr-gsm安装依赖项安装gr-gsm修改环境变量 安装成功 安装gnuradio3.8 安装依赖项 sudo apt install git cmake g libboost-all-dev libgmp-dev swig python3-numpy python3-mako python3-sphinx …

(自用)Java学习-5.15(模糊搜索,收藏,购物车)

1. 模糊搜索商品功能 前端实现&#xff1a; 通过解析URL参数&#xff08;如search联想&#xff09;获取搜索关键字&#xff0c;发送AJAX GET请求到后端接口/product/searchGoodsMessage。 动态渲染搜索结果&#xff1a;若结果非空&#xff0c;循环遍历返回的商品数据&#xff…

STM32 TIM 定时器深度剖析:结构、时基、中断与应用开发(超形象详解)

文章目录 定时器&#xff08;TIM&#xff09;定时器种类与分布定时器的基本结构时基单元时基单元基本结构计数器计数方向时基单元时钟来源计算寄存器预加载机制 自制延时函数获取单片机当前时间实现延迟函数初始化定时器3的时基单元配置中断编写中断响应函数测试延迟函数 定时器…

Java使用minio上传整个目录下的所有内容

目录 1、添加相关配置 2、添加依赖 3、实现方法 1️⃣基础版&#xff1a; 2️⃣优化版&#xff08;推荐使用&#xff09;&#xff1a; 3️⃣上传远程主机上的目录内容&#xff1a; 4️⃣直接上传远程主机中的目录内容 业务背景&#xff1a;需要需要minio进行上传指定目录下所有…

Python的分布式网络爬虫系统实现

1. 系统架构概述 一个典型的分布式网络爬虫系统通常包含以下几个核心组件&#xff1a; 1.主节点&#xff08;Master Node&#xff09;&#xff1a; 任务调度&#xff1a;负责将抓取任务分配给各个工作节点。URL 管理&#xff1a;维护待抓取的 URL 队列和已抓取的 URL 集合&a…