内容摘要:windows在创建线程时回先调用TLS回调函数,如果我们在回调函数中加入调试器探测代码就可以方便的探测调试器的存在。
TLS回调函数是指,每当创建/终止进程的线程时会自动调用执行的函数。创建的主线程也会自动调用回调函数,且其调用执行先于EP代码。
IMAGE_DATA_DIRECTORY[9]:IMAGE_TLS_DIRECTORY
typedef struct _IMAGE_TLS_DIRECTORY64 {
ULONGLONG StartAddressOfRawData;
ULONGLONG EndAddressOfRawData;
ULONGLONG AddressOfIndex; // PDWORD
ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *;
DWORD SizeOfZeroFill;
DWORD Characteristics;
} IMAGE_TLS_DIRECTORY64;
typedef IMAGE_TLS_DIRECTORY64* PIMAGE_TLS_DIRECTORY64typedef struct _IMAGE_TLS_DIRECTORY32 {
DWORD StartAddressOfRawData;
DWORD EndAddressOfRawData;
DWORD AddressOfIndex; // PDWORD
DWORD AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *;
DWORD SizeOfZeroFill;
DWORD Characteristics;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32* PIMAGE_TLS_DIRECTORY32;
修改步骤:
1、在资源节去最后添加一块区域用于存放TLS回调函数和IMAGE_TLS_DIRECTORY结构体。
2、修改资源节去头相关信息(Size of Raw Data和Characteristics)(修改一个节区内容的时候要修改相应节去头)
3、修改NT头(RVA of TLS Table和Size of TLS Table) (一般修改节区内容时还要修改相应NT头中IMAGE_OPTIONAL_HEADER中相应内容)
4、修改好头部之后正式编辑IMAGE_TLS_DIRECTORY结构体并设置最关键的IMAGE_TLS_DIRECTORY结构体中的TLS Callback Function
好!下面进入图形步骤:
1、在资源节去最后添加一块区域用于存放TLS回调函数和IMAGE_TLS_DIRECTORY结构体。用十六进制(如win hex)工具往资源节去添加200H字节(自定义可调),由于虚拟内存文件对齐一般是1000H,所以9200H—A000H都是可以使用的范围。
2、修改资源节去头相关信息(Size of Raw Data和Characteristics)(修改一个节区内容的时候要修改相应节去头)
3、修改NT头(RVA of TLS Table和Size of TLS Table=18H)(一般修改节区内容时还要修改相应NT头中IMAGE_OPTIONAL_HEADER中相应内容)
4、修改好头部之后正式编辑IMAGE_TLS_DIRECTORY结构体并设置最关键的IMAGE_TLS_DIRECTORY结构体中的TLS Callback Function。
设置的函数比较简单,就是判断目前是否处于调试状态,是就跳出,否则继续。
反应到文件中就是下图
注意图中的地址是9230H而内存中VA是40C230,地址转换可以手动计算也可以用PEview查看,另外从图中还能看出,MessageBox和ExitProcess函数的调用是用了IAT中函数地址(这个每次调用不一定是同一地址,具体使用是需要实际查看)
至此,修改结束,保存运行如下
小结:
此方法来自于《逆向工程核心原理》,和之前修改PE文件头来达到PE注入目的,思路类似,所以不详细记录,这种反调试的方法也可以通过编码改成自动化修改,不过在实际使用中,这种技巧也不太实用,吾爱破解版OD或者看雪中有的OD已能够自动绕过这种机制,但是用于学习相关原理还是有必要的。