c语言中什么函数执行的最早?
main函数吗?不是,还有更早执行的函数,比如初始化全局变量的构造函数。我们都知道,od在反汇编一个exe的时候会停止在oep的位置上,那么有比oep还要更早执行的函数吗?有的,比如TLS。

既然tls比ebp都早,那么我们是否可以利用到它呢?比如反调试,如下图代码

#include<iostream>
#include<tchar.h>
#include"ntdll/ntdll.h"
#include<windows.h>

DWORD isdebug = 0;

//下面这行告诉链接器在PE文件中要创建TLS目录
#pragma comment(linker,"/INCLUDE:_tls_used")

// 这是PIMAGE_TLS_CALLBACK()函数的原型
//其中第一个和第三个参数保留,第二个参数决定函数在那种情况下
void NTAPI my_tls_callback(PVOID h, DWORD reason, PVOID pv)
{
///共有四个选项DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH和DLL_PROCESS_DETACH
//仅在进程初始化创建主线程时执行的代码
if (reason == DLL_PROCESS_ATTACH)
{
//第一个参数L:线程句柄,第二个参数:你想干什么,ThreadHideFromDebugger(终端和内核之间调试信息的联系)
//NtSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, 0, 0);
//第一个参数:线程句柄,第二个参数:查询当前的调试窗口,如果当前是在被调试的话,返回一个PVOID类型的指针(参数3),如果为0则证明没有被调试,如果不为0,则证明被调试了。
NtQueryInformationProcess(GetCurrentThread(), ProccessDebugPort, (PVOID)isDebug, sizeof(DWORD), NULL);
MessageBox(NULL, "hi,this is a callback", "z1in", MB_OK);
}
return;
}

int main()
{
char array2[] = { 0xc7,0xb2,0xa2,0xf1,0xa3,0xd9,0xa9,0xb6,0x10 };
for (int i = 0; i < 9; i++)
{
array[i] = array[i] ^ 0x10 ^ isdebug;
}
MessageBoxA(NULL, "main函数执行", "提示", MB_OK);
system("pause");
}

//新建一段数据,放到TLS这个目录表里面
#pragma data_seg(".CRT$XLX")
PIMAGE_TLS_CALLBACK pTLS_CALLBACKs[] = { TLS_CALLBACK,NULL };
#pragma data_seg()

通过创建一个TLS函数,然后再TLS函数里添加反调试函数,就可以阻止别人调试我们的exe。
这样会改变我们的pe结构,新增一个tls目录,里面存放着tls的结构体,AddressOfCallBacks 存放的就是回调函数的RVA,当然有时候也可能就是VA。TLS函数
在这里插入图片描述
既然可以反调试了,那么我们可以去利用这个反调试,如上代码,通过异或0x10对“注册成功”进行加密,然后再与变量isdebug进行异或运算,如果程序被调试了的话,就会使isdebug不为0,变成返回的指针值,从而使字符串变为乱码。

在这里插入图片描述
关于这里,有一个动态patch tls回调函数的骚操作,可以一直执行tls函数。原理没听懂,麻了。
先留着,以后解决。

花指令:
之前说过jmp实现的恒成立跳转从而实现花指令,也就是恒成立的eip跳转就能实现花指令,所以我们也可以这样实现:

call 00402032
add dword ptr ss:[esp],0x17
retn

这样可以通过call会讲调用的地址压入栈中,然后其增加0x17,再通过retn实现恒成立跳转。

补充:在这里插入图片描述
这种[xxxxxxxx]的都是全局变量。