pe文件結構(TLS)

TLS


什么是TLS?

TLS是 Thread Local Storage 的縮寫,線程局部存儲。主要是為了解決多線程中變量同步的問題

如果需要要一個線程內部的各個函數調用都能訪問,但其它線程不能訪問的變量(被稱為static memory local to a thread 線程局部靜態變量),就需要新的機制來實現,這就是TLS

用途1:

TLS變量

線程A去修改TLS變量時,線程B不會受影響,因為每個線程都擁有一個TLS變量的副本

創建TLS變量

__declspe(thread) int g_tls = 1000;

用途2:

在安全領域中,TLS常被用于處理如反調試,搶占執行等操作

TLS回調函數

#include<iostream>
#include<Windows.h>
// 首先加上編譯選項 
_declspec(thread) int g_tlsNum = 100;
#ifdef _WIN64
#pragma comment(linker, "/INCLUDE:_tls_used")
#else
#pragma comment(linker, "/INCLUDE:__tls_used")
#endifDWORD WINAPI threadProc(LPVOID lparam) {g_tlsNum = 300;printf("g_tlsNum=%d\n",g_tlsNum);return 0;
}void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Reserved);/*注冊TLS函數,.CRT$XLX的作用CRT表示使用C Runtime庫X表示標識名隨機L表示 TLS Callback sectionX也可以換成B~Y任意一個字符*/
// 注冊 TLS 回調
#ifdef _WIN64
#pragma const_seg(".CRT$XLX") // x64 下用 const_seg(只讀段)
EXTERN_C const // 禁用 C++ 的名稱修飾 
#else
#pragma data_seg(".CRT$XLX") // x86 下用 data_seg(可讀寫段)
#endif//存儲回調函數地址 PIMAGE_TLS_CALLBACK pTLS_CALLBACKs,寫了幾個回調函就要往里面添加幾個,最后必須要有一個0
PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { t_TlsCallBack_A,0 };#ifdef _WIN64
#pragma const_seg()
#else
#pragma data_seg()
#endif// 編寫Tls回調函數 參數1:模塊加載基址 參數2:調用的原因 參數3:保留
void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Reserved) {switch (Reason) {case DLL_PROCESS_ATTACH:printf("Hello Tls\n");break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}
}int main() {// 創建線程CreateThread(NULL, NULL, threadProc,NULL,NULL,NULL);return 0;
}

何時被調用

  • #define DLL_PROCESS_ATTACH 1 // 進程創建時
  • #define DLL_THREAD_ATTACH 2 // 線程創建時
  • #define DLL_THREAD_DETACH 3 // 線程銷毀時
  • #define DLL_PROCESS_DETACH 0 // 進程銷毀時

在這里插入圖片描述

查看執行結果,我們會發現TLS是最先執行的,這樣我們就可以用這個回調函數來反調試一些調試器的加載,一般來說調試器在加載一個程序的時候,程序最先執行的代碼是OEP(Original Entry Point),但TLS在OPE之前執行

我們來修改一下代碼來寫一個簡單的反調試程序

void NTAPI t_TlsCallBack_A(PVOID DllHandle, DWORD Reason, PVOID Reserved) {switch (Reason) {case DLL_PROCESS_ATTACH:{BOOL result = FALSE;HANDLE hRealProcess = NULL;DuplicateHandle(GetCurrentProcess(),         // 當前進程GetCurrentProcess(),         // 偽句柄 (HANDLE)-1GetCurrentProcess(),         // 目標進程(仍為當前進程)&hRealProcess,               // 存儲真實句柄NULL, FALSE, DUPLICATE_SAME_ACCESS);CheckRemoteDebuggerPresent(hRealProcess, &result); // 這種只是最簡單的,現代調試器都會有反反調試的手段if (result) {MessageBox(NULL, L"檢測到有調試器加載", L"Warning", MB_OK | MB_ICONWARNING);ExitProcess(0);}break;}case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}
}

直接雙擊運行程序發現是沒有問題的

在這里插入圖片描述

我們來測試下有調試器加載的情況(由于目前市面上常用的調試器都有反反調試的功能,我們這個簡單的反調試肯定是不會被檢測出來的,所以我們用Visual Studio自帶的調試器來看一下)

在這里插入圖片描述
可以看到我們main函數還沒執行之前就已經觸發了檢測


TLS表

在我們的pe文件當中,有這么一張表,就是用來告訴Tls函數和變量在哪里存放著

在我們16張表中第10張表就是我們的Tls表對應存放的虛擬地址

// IMAGE_TLS_DIRECTORY64結構體 
typedef struct _IMAGE_TLS_DIRECTORY64 {ULONGLONG StartAddressOfRawData;	// Tls初始化數據的起始地址ULONGLONG EndAddressOfRawData;		// Tls初始化數據的結束地址 (這個范圍存放初始化的值)ULONGLONG AddressOfIndex;         	// Tls索引的位置ULONGLONG AddressOfCallBacks;     	// PIMAGE_TLS_CALLBACK * (Tls回調函數的數組指針)DWORD SizeOfZeroFill;				// 填充0的個數union {DWORD Characteristics;struct {DWORD Reserved0 : 20;DWORD Alignment : 4;DWORD Reserved1 : 8;} DUMMYSTRUCTNAME;} DUMMYUNIONNAME;} IMAGE_TLS_DIRECTORY64;
// 獲取Tls表信息
void getTlsInfo(const char* peFileBuffer) {// 獲取Tls表地址TableAddress repositionAddress = g_tableAddress[IMAGE_DIRECTORY_ENTRY_TLS];// 通過Rva得到文件地址DWORD fileAddress = rvaToFoa(repositionAddress.myVirtualAddress);// 解析結構體PIMAGE_TLS_DIRECTORY64 tlsDirectory = (PIMAGE_TLS_DIRECTORY64)(peFileBuffer + fileAddress);printf("Tls初始化數據的起始地址:0x%llX\n", tlsDirectory->StartAddressOfRawData);printf("Tls初始化數據的結束地址:0x%llX\n", tlsDirectory->EndAddressOfRawData);printf("Tls索引的位置:0x%llX\n", tlsDirectory->AddressOfIndex);printf("Tls回調函數的數組指針:0x%llX\n", tlsDirectory->AddressOfCallBacks);printf("填充0的個數:%d\n", tlsDirectory->SizeOfZeroFill);}

在這里插入圖片描述

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84158.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84158.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84158.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Electron簡介(附電子書學習資料)

一、什么是Electron&#xff1f; Electron 是一個由 GitHub 開發的 開源框架&#xff0c;允許開發者使用 Web技術&#xff08;HTML、CSS、JavaScript&#xff09; 構建跨平臺的桌面應用程序&#xff08;Windows、macOS、Linux&#xff09;。它將 Chromium瀏覽器內核 和 Node.j…

如何使用DeepSeek幫助自己的工作?(Java開發)

如何使用DeepSeek幫助自己的工作&#xff1f; 作為Java開發者&#xff0c;你可以通過以下方式高效利用DeepSeek提升工作效率&#xff08;附具體操作示例&#xff09;&#xff1a; 一、日常編碼加速 1. 代碼生成與補全 // 輸入需求描述&#xff1a; "生成SpringBoot分頁…

Uniapp 二維碼生成與解析完整教程

前言 使用Uniapp開發多平臺應用&#xff0c;二維碼生成采用uQRCode插件&#xff0c;非常nice&#x1f601;&#xff01; Coding 原理 使用canvas繪制 生成二維碼數據 繪制到canvas上 使用 <uqrcoderef"uqrcodeRef"canvas-id"qrcode":value"qr…

Vue ⑤-自定義指令 || 插槽

自定義指令 自定義指令&#xff1a;自己定義的指令, 可以封裝一些 dom 操作&#xff0c; 擴展額外功能。 全局注冊 語法&#xff1a; Vue.directive(指令名, {"inserted" (el) {// 可以對 el 標簽&#xff0c;擴展額外功能el.focus()} })局部注冊 語法&#xff…

Java HttpClient實現簡單網絡爬蟲

今天我將使用Java的HttpClient&#xff08;在Java 11及以上版本中內置&#xff09;來編寫一個入門級的網絡爬蟲示例。 這個示例將演示如何發送HTTP GET請求&#xff0c;獲取響應內容&#xff0c;并處理可能出現的異常。 以下是一個基于Java HttpClient&#xff08;Java 11&…

圖表類系列各種樣式PPT模版分享

圖標圖表系列PPT模版&#xff0c;柱狀圖PPT模版&#xff0c;線狀圖PPT模版&#xff0c;折線圖PPT模版&#xff0c;餅狀圖PPT模版&#xff0c;雷達圖PPT模版&#xff0c;樹狀圖PPT模版 圖表類系列各種樣式PPT模版分享&#xff1a;圖表系列PPT模板https://pan.quark.cn/s/20d40aa…

Sonic EVM L1:沉睡的雄獅已蘇醒

Sonic 鏈 , 是 Fantom 基金會升級后的Layer-1區塊鏈&#xff0c;繼承了 Fantom Opera 的高性能特性&#xff0c;并通過全面技術優化成為EVM兼容的高吞吐量公鏈。 官方網站 : https://www.soniclabs.com 一、Sonic 鏈概述 1. 為什么從 Fantom 更名為 Sonic Sonic 鏈是 Fant…

籃球杯軟件賽國賽C/C++ 大學 B 組補題

3.gcd 模擬 map<pair<int,int>,int>m; void solve(){int n;cin>>n;forr(i,1,n){int ux,uy,vx,vy;cin>>ux>>uy>>vx>>vy;int dxvx-ux,dyvy-uy;if(dx!0&&dy!0){int gabs(__gcd(dx,dy));dx/g,dy/g;//dxdy中除去公共部分(gcd) 就…

技術棧RabbitMq的介紹和使用

目錄 1. 什么是消息隊列&#xff1f;2. 消息隊列的優點3. RabbitMQ 消息隊列概述4. RabbitMQ 安裝5. Exchange 四種類型5.1 direct 精準匹配5.2 fanout 廣播5.3 topic 正則匹配 6. RabbitMQ 隊列模式6.1 簡單隊列模式6.2 工作隊列模式6.3 發布/訂閱模式6.4 路由模式6.5 主題模式…

項目部署到Linux上時遇到的錯誤(Redis,MySQL,無法正確連接,地址占用問題)

Redis無法正確連接 在運行jar包時出現了這樣的錯誤 查詢得知問題核心在于Redis連接失敗&#xff0c;具體原因是客戶端發送了密碼認證請求&#xff0c;但Redis服務器未設置密碼 1.為Redis設置密碼&#xff08;匹配客戶端配置&#xff09; 步驟&#xff1a; 1&#xff09;.修…

Linux邊緣智能:物聯網的終極進化

Linux邊緣智能&#xff1a;物聯網的終極進化 從數據中心到萬物終端的智能革命 引言&#xff1a;邊緣計算的范式轉變 隨著物聯網設備的爆炸式增長&#xff0c;傳統的云計算架構已無法滿足實時性、隱私保護和帶寬效率的需求。邊緣智能應運而生&#xff0c;將計算能力從云端下沉到…

Linux Shell 中的 dash 符號 “-”

Shell中的-&#xff1a;小符號的大智慧 在Unix/Linux系統中&#xff0c;-符號是一個約定俗成的特殊標記&#xff0c;它表示命令應該使用標準輸入或標準輸出而非文件。這個看似簡單的短橫線&#xff0c;完美詮釋了Unix"一切皆文件"的設計哲學。 作為標準輸入/輸出的…

JMeter 實現 MQTT 協議壓力測試 !

想象一下&#xff0c;你的智能家居系統連接了上千個設備&#xff0c;傳感器數據通過 MQTT 協議飛速傳輸&#xff0c;但突然服務器崩潰&#xff0c;燈光、空調全失控&#xff01;如何確保你的 MQTT 經紀人能承受高負載&#xff1f;答案是 JMeter&#xff01;通過安裝 MQTT 插件&…

CKA考試知識點分享(6)---PriorityClass

CKA 版本&#xff1a;1.32 第六套題是涉及PriorityClass相關。 注意&#xff1a;本文不是題目&#xff0c;只是為了學習相關知識點做的實驗。僅供參考 實驗目的 創建一套PriorityClass &#xff0c;驗證PriorityClass的運作策略。 1 環境準備 創建2個pc&#xff0c;一個為高…

暴力破解篇補充-字典

在皮卡丘靶場的第二期&#xff0c;暴力破解模塊中&#xff0c;我相信大家短暫的接觸了字典這個概念&#xff0c;字典事實上就是包含了大量弱口令的txt文本文件 所以這篇文章用于分享一些字典&#xff1a;https://wwhc.lanzoue.com/ihdl12ybhbhi&#xff08;弱口令字典&#xff…

關于VS2022中C++導入第三方庫的方式

首先&#xff0c;新建一個Cpp項目(控制臺項目即可&#xff0c;其他項目也無所謂)&#xff0c;右鍵點擊項目名稱(Test1)選擇屬性或者在VS2022工具欄選擇調試標簽->屬性按鈕打開屬性頁。 注意點: 在開始其他操作前請注意先進行 配置和平臺選項框的選擇。配置選框選定了是配置…

C++中vector類型的介紹和使用

文章目錄 一、vector 類型的簡介1.1 基本介紹1.2 常見用法示例1.3 常見成員函數簡表 二、vector 數據的插入2.1 push_back() —— 在尾部插入一個元素2.2 emplace_back() —— 在尾部“就地”構造對象2.3 insert() —— 在任意位置插入一個或多個元素2.4 emplace() —— 在任意…

在Vue或React項目中使用Tailwind CSS實現暗黑模式切換:從系統適配到手動控制

在現代Web開發中&#xff0c;暗黑模式(Dark Mode)已成為提升用戶體驗的重要功能。本文將帶你使用Tailwind CSS在React項目(Vue項目類似)中實現兩種暗黑模式控制方式&#xff1a; 系統自動適配 - 根據用戶設備偏好自動切換手動切換 - 通過按鈕讓用戶自由選擇 一、項目準備 使…

Linux C語言網絡編程詳細入門教程:如何一步步實現TCP服務端與客戶端通信

文章目錄 Linux C語言網絡編程詳細入門教程&#xff1a;如何一步步實現TCP服務端與客戶端通信前言一、網絡通信基礎概念二、服務端與客戶端的完整流程圖解三、每一步的詳細講解和代碼示例1. 創建Socket&#xff08;服務端和客戶端都要&#xff09;2. 綁定本地地址和端口&#x…

Tomcat 安裝和配置

一、Tomcat官網 Apache Tomcat - Welcome! 選擇解壓到任意一個盤&#xff01;&#xff01; 二、Tomcat配置 1&#xff09;在系統變量處新建一個變量CATALINA_HOME。CATALINA_HOME環境變量的值&#xff0c;設置為Tomcat的解壓安裝目錄 2&#xff09;找到系統變量Path&#xff0…