日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/10 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TLS回调函数以及反调试简单使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TLS回調函數以及反調試簡單使用

0x00 ?TLS介紹

??TLS(Thread Local Storage,線程局部儲存),主要用于給線程獨立的傳值,由于線程不擁有進程的資源,所以幾個同一進程的幾個線程需要獨立賦值時的需要通過TLS技術。每個線程創建時都會分配一個index所以,這個索引index是全局變量,線程根據index來獲取其他線程傳過來的返回值。TLS有一個特點,就是它通常在程序EP前就要運行,所以起始TLS才是個程序真正的開始。利用這一特點,可以用來進行的程序的反調試。

0x01 TLS調用過程

??下面我們來創建一個TLS調用實例來看看這個過程會發生什么。

程序如下:

#include "pch.h"

#include <iostream>

#include<windows.h>

//聲明要使用TLS

#pragma comment(linker,"/INCLUDE:__tls_used")

//#pragma comment(linker,"/INCLUDE:__tls_used")

?

//

void print_consoleA(const char *szMsg)

{

HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

WriteConsoleA(hStdout, szMsg, strlen(szMsg), NULL, NULL);

?

}

?

//定義兩個TLS回調函數

//注意一下這個回調函數的參數表,和DLLmain一樣的

//Reason的值分別有四種

// #define DLL_PROCESS_ATTACH ??1

// #define DLL_THREAD_ATTACH ???2

//#define DLL_THREAD_DETACH ???3

//#define DLL_PROCESS_DETACH ??0

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_consoleA(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_consoleA(szMsg);

}

//在數據段注冊兩個TLS回調函數

#pragma data_seg(".CRT$XLX")

PIMAGE_TLS_CALLBACK pTLS_CALLBACK[] = { TLS_CALLBACK1,TLS_CALLBACK2 ,0 };

#pragma data_seg()

?

//新建線程

DWORD WINAPI ThreadProc(LPVOID lParam)

{

print_consoleA("ThreadProc() start\n");

?

print_consoleA("ThreadProc() end\n");

return 0;

}

?

int main()

{

HANDLE hThread = NULL;

print_consoleA("main() start\n");

hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

WaitForSingleObject(hThread, 60 * 1000);

CloseHandle(hThread);

print_consoleA("main() end\n");

?

?

}

編譯程序,記住要在debug模式下編譯,不然無法打印出完整的日志信息。

Cmd運行得到如下:

D:\>TLSTest1.exe

TLS_CALLBACK1():DllHandle =BE0000,Reason=1

TLS_CALLBACK2():DllHandle =BE0000,Reason=1

main() start

TLS_CALLBACK1():DllHandle =BE0000,Reason=2

TLS_CALLBACK2():DllHandle =BE0000,Reason=2

ThreadProc() start

ThreadProc() end

TLS_CALLBACK1():DllHandle =BE0000,Reason=3

TLS_CALLBACK2():DllHandle =BE0000,Reason=3

main() end

TLS_CALLBACK1():DllHandle =BE0000,Reason=0

TLS_CALLBACK2():DllHandle =BE0000,Reason=0

由上述log信息可以知道TLS回調函數是在進程或者線程開始前就已經執行了,在進程或者線程結束后也結束。

0x00 使用c++編寫簡單的反調試程序

程序如下:

#include "pch.h"

#include <iostream>

#include<windows.h>

//聲明使用TLS回調函數

#pragma comment(linker,"/INCLUDE:__tls_used")

//定義回調函數

void NTAPI TLS_CallBack(PVOID Dllhandle, DWORD Reason, PVOID Reserved)

{

//發現被調試就退出,使用這個API來偵察反調試已經完全不管用了

//吾愛的OD和看雪的OD已經可以屏蔽這個API了,所以起不到反調試的作用,API僅做原理演示用

?

if (IsDebuggerPresent())

{

MessageBoxA(NULL, "Debugger detect!!", "TLS_CALLBACK", MB_OK);

ExitProcess(1);

}

?

}

//注冊TLS回調函數

#pragma data_seg(".CRT$XLX")

PIMAGE_TLS_CALLBACK pTls_CallBack[] = { TLS_CallBack,0 };

#pragma data_seg()

?

?

?

?

int main(void)

{

MessageBoxA(NULL, "hello !", "main()", MB_OK);

}

debug模式下編譯生成TLSantidubug.exe文件。我們將其拖入吾愛的odf9運行。如下圖:

?

我們發現并沒有彈出調試信息,看來吾愛的OD已經繞過去了,沒辦法,使用原版OD再來測試以下,如下圖:

?

上圖可以看出,TLS已經先調用來檢測是否被調試。

0x03 使用匯編來編寫TLS反調試程序。

??我們先編寫一個沒有調用TLS的程序,程序的功能很簡單,就是彈出一個messageBox

代碼如下:

#include?"windows.h"

?

void?main()

{

????MessageBoxA(NULL, "Hello :)", "main()", MB_OK);

}

編譯生成Hello.exe。運行如下圖:

?

下面使用工具PEview和hexworkshop以及od來編寫TLS程序。編寫程序前,先用PEview來查看沒有使用TLS的文件結構。我們在IMAGE_OPTIONAL_HEADER.DIRECTORY[9]找到TLS選項。如下圖:

?

兩個值都是零。添加TLS步驟如下:

1)選址,一共有三個地址可選,最后段尾,段中的空白區域或者新建分段。我們就選擇在段尾插入一塊空白區域,來實現。下圖為最后段.rsrc分段信息:

由上圖可以知道整個文件大小為9200。我們將.rsrc段增到400h,即在91ff處插入200h空白區域。如下圖:

?

?記得把.rsrc的大小改為400h,并把屬性改為可讀寫,可執行即E00060。

2)修改IMAGE_OPTIONAL_HEADER.DIRECTORY[9]D的TLS的地址和大小。如下圖:

?

地址RVA=C200就是fileoffset=9200處大小為18h。

3)編寫IMAGE_TLS_DIRECTORY結構體。

IMAGE_TLS_DIRECTORY結構的定義如下:

typedef struct _IMAGE_TLS_DIRECTORY32 {

????DWORD StartAddressOfRawData;

????DWORD EndAddressOfRawData;

????PDWORD AddressOfIndex;

????PIMAGE_TLS_CALLBACK *AddressOfCallBacks;

????DWORD SizeOfZeroFill;

????DWORD Characteristics;

????} IMAGE_TLS_DIRECTORY32;

????其中PIMAGE_TLS_CALLBACK如下:

????typedef VOID

????(NTAPI *PIMAGE_TLS_CALLBACK) (

????PVOID DllHandle,

????DWORD Reason,

????PVOID Reserved

);

編寫的位置就是剛剛插入的位置即9200處,如下圖:

?

這里函數就先寫一個無功能的RERN 0C 具體的匯編指令要等到保存后使用OD編寫。

4)使用OD編寫具體的匯編指令

如果沒有編寫錯誤的話,od載入修改后的程序將會停在40c230處,因為程序先運行TLS,而40c230正是我們編寫的TLS函數的EP處。

將下列代碼填入以40c230開始處:

0040C230 ???837C24 08 01 ???cmp dword ptr ss:[esp+0x8],0x1

0040C235 ???75 28 ??????????jnz short 0040C25F

0040C237 ???64:A1 30000000 ?mov eax,dword ptr fs:[0x30]

0040C23D ???8078 02 00 ?????cmp byte ptr ds:[eax+0x2],0x0

0040C241 ???74 1C ??????????je short 0040C25F

0040C243 ???6A 00 ??????????push 0x0

0040C245 ???68 70C24000 ????push 0x40C270 ???????????????????????????; ASCII "TLS Callback"

0040C24A ???68 80C24000 ????push 0x40C280 ???????????????????????????; ASCII "DebuggerDetected!"

0040C24F ???6A 00 ??????????push 0x0

0040C251 ???FF15 E8804000 ??call dword ptr ds:[0x4080E8]

0040C257 ???6A 01 ??????????push 0x1

0040C259 ???FF15 28804000 ??call dword ptr ds:[0x408028]

0040C25F ???C2 0C00 ????????retn 0xC

0040C262 ???90 ?????????????nop

如下圖:

?

保存修改,至此完成。

5)載入原版的od。如下圖:

?

編寫的TLS反調試起作用了。

?

轉載于:https://www.cnblogs.com/2f28/p/10051042.html

總結

以上是生活随笔為你收集整理的TLS回调函数以及反调试简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。