线程局部存储技术:
线程局部存储技术(Thread Local Storage)很好的解决了多线程程序设计中变量的同步问题。同时,TLS回调函数也适用于反调试技术。使用TSL技术,可以让进程拥有同一个全局变量,但是在不同的线程却对应着不同的值,这些变量只是对应特定的线程才是有意义的
两个前提知识:
线程环境块(TEB):
TEB指的是线程环境块,该结构体里面包含一个线程的基本信息,进程的每一个线程都对应的一个这样的TEB数据结构。
TEB的数据结构:
|
|
TEB的重要成员:
|
|
- ProcessEnvirnmentBlock是一个指向PEB的指针。
TEB的第一个成员是_NT_Tib(线程信息块)的结构体。
TIB的信息如下:
1234567891011121314typedef struct _KPCR_TIB{PVOID ExceptionList; //重点PVOID StackBase;PVOID StackLimit;PVOID SubSystemTib;_ANONYMOUS_UNION union{PVOID FiberData;DWORD Version;}DUMMYUNIONNAME;PVOID ArbitraryUserPointer;struct _NT_TIB *Self; //重点} KPCR_TIB, *PKPCR_TIB;ExceptionList用于指向EXCEPTION_REGISTRATION_RECORD结构体链表(指向SEH)
- self成员是TIB的自用指针,指向TIB的第一个成员,也是TEB的第一个成员。
TEB的访问方法:
- FS:[0X00]=SEH的起始地址
- FS:[0x18]=TEB的起始地址
- FS:[0x30]=PEB的起始地址
进程环境块(PEB):
PEB(Process Environment Block,进程环境块)存放进程信息,每个进程都有自己的PEB信息。位于用户地址空间。在Win 2000下,进程环境块的地址对于每个进程来说是固定的,在0x7FFDF000处,这是用户地址空间,所以程序能够直接访问。准确的PEB地址应从系统 的EPROCESS结构的0x1b0偏移处获得,但由于EPROCESS在系统地址空间,访问这个结构需要有ring0的权限。还可以通过TEB结构的偏 移0x30处获得PEB的位置,FS段寄存器指向当前的TEB结构.
PEB的信息如下:
|
|
PEB的重要成员:
- 1.PEB.BeingDebugged //程序是否处于调试状态
- 2.ImageBaseAddress //表示进程的基地址
- 3.PEB.Ldr //指向PEB_LDR_DATA的指针,该结构体可以获取模块(dll)加载的基地址
- 4.PEB.ProcessHeap&&PEB.NtGlobalFlag //用于反调试
PEB的访问方法:
- FS:[0X30]=PEB
- 先获得TEB的地址,在偏移0x30得到PEB
TLS技术
动态TLS技术
四个API函数:
TLsAlloc //获取索引
TlsGetValue //获取索引值
TlsSetVaule //设置索引值
TisFree //释放索引
静态TLS技术
预先将变量定义在PE文件内部,一般实验.tls节即可。通过查看TLS节区,而已看到程序是否使用TLS反调试技术
TSL回调函数—-反调试技术的基石
TSL函数是指,每当创建或者终止进程的线程的时候,就会自动调用的函数,一共调用2次。有意思的是,进程创建主线程的时候也会自动的调用TSL回调函数,并且调用函数优先执行于EP代码(应该是主线程调用后,但是线程函数的尚未执行之前)。一点扩展利用TLS回调函数在调试器加载前执行Anti-Debug函数保护软件不被恶意修改,关键部分依旧是具体实现反调试部分的代码编写。比如传统的检测断点,检测进程,检测调试器等等。反调试技术就是利用这一特征。
如果使用单纯的调试器(VS),就容易被TSL回调函数检测到,由于od的工具自动免疫了TSL的反调试机制,所以只会出现正常的状态(假的)。
- 解决反调试的方法:
- 1)OD插件
- 2)PE或者IDA查找TSL的回调函数的入口地址和大小,然后转换成文件偏移,最后用工具00填充掉就行。