加强网站建设工作,德州建设网站,做了网站应该如何推广,建设部网站监理注销查询TLS
代码逆向分析领域中#xff0c;TLS#xff08;Thread Local Storage#xff0c;线程局部存储#xff09;回调函数#xff08;Callback Function#xff09;常用反调试。TLS回调函数的调用运行要先于EP代码的执行#xff0c;该特征使它可以作为一种反调试技术的使用…TLS
代码逆向分析领域中TLSThread 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; // PDWORDULONGLONG 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; // PDWORDDWORD 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 0example
#includeWindows.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 sectionX也可以换成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回调函数
扩大最后一个节修改PE头保证扩展正确增加TLS的目录表增加TLS的结构体放在扩大的节里根据结构体所指的数组中的地址添加TLS回调函数代码
1、2扩大节、修改PE节表
3、添加TLS目录表
4、去RVAC200处添加TLS结构体内容
5、添加TLS函数代码
结果 载入od调试就是触发这个弹窗