好友
阅读权限 10
听众
最后登录 1970-1-1
wzb
发表于 2011-7-11 09:48
TLS是线程局部存储的意思。用TLS可以干很多你想干的,像PE感染、PE文件自校验、调试器检测(附件里就是一个用TLS做调试器检测的小例子)
但是TLS Callback用C++不是很好写,编译设置有些麻烦,在这我介绍一下TLS如何用C++写
TLS Callback的原理是:
1、在链接时,链接器要在PE文件中创建TLS目录。
2、在创建线程时,加载器会从TEB(线程环境块,通过FS寄存器可以获取TEB的位置)中获取一个指向TLS回调函数数组的指针。
3、如果在TLS回调函数数组不是一个空的数组,加载器就会顺序执行这个数组中的各个回调函数(在入口函数之前加载)。
所以我们第一步就要分配一个TLS段
#pragma data_seg(".tls") //分配一个TLS段
然后告诉编译器,生成TLS目录
#pragma comment(linker, "/INCLUDE:__tls_used") //下面这行告诉链接器在PE文件中要创建TLS目录
接下来初始化TLS目录:
nt _tls_index=0;
int _tls_start=0;
int _tls_end=0;
int __xl_a=0;
int __xl_z=0;
extern PIMAGE_TLS_CALLBACK tls_callbacktbl[]; //TLS回调函数数组
IMAGE_TLS_DIRECTORY32 _tls_used=
{
(DWORD)&_tls_start,
(DWORD)&_tls_end,
(DWORD)&_tls_index,
(DWORD)tls_callbacktbl,
0,
0
};
下面是一些编译设置:
#pragma data_seg(".tls$ZZZ")
#pragma data_seg(".CRT$XLA") //.CRT表明是使用C RunTime机制,$后面的XLA中X表示随机的标识,L表示是TLS callback section,A是任意的
#pragma data_seg(".CRT$XLZ")
#pragma data_seg(".rdata$T")
上面这些代码,放到一个.c文件中,在工程属性中选去掉预编译头
然后就可以开始我们的正题TLS函数的编写了:
函数声明是:
void NTAPI my_tls_callback(PVOID h, DWORD reason, PVOID pv);
其中第一和第三个参数不用管它,是保留的
第二个参数有下面几个可能的值:
DLL_PROCESS_ATTACH,是指新进程创建时,在初始化主线程时执行
DLL_THREAD_ATTACH,是指在新进程初始化时执行,但是不包括主线程
DLL_THREAD_DETACH,是指在所有的线程终止时执行,但是同样不包括主线程
DLL_PROCESS_DETACH,是指在进程终止时执行
TLS函数一般是这样的格式:
Void NTAPI tls_callback(PVOID h, DWORD reason, PVOID pv)
{
if(reason==DLL_PROCESS_ATTACH)
{
......................
}
if(reason==DLL_THREAD_ATTACH)
{
......................
}
...................
return;
};
填上自己的代码就可以了。
最后要写TLS回调函数数组:
extern "C" PIMAGE_TLS_CALLBACK tls_callbacktbl[] = {tls_callback,0};
有几个TLS回调函数就写几个,以0结尾。
附件是一个例子,用TLS做调试器检测。
测试的时候要把反调试的插件都去掉啊!
TLS.rar
4.04 KB, 下载次数: 103, 下载积分: 吾爱币 -1 CB
发帖前要善用【论坛搜索 】 功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。