参考了http://www.docin.com/p-472081682.html这篇论文。
本文为原创,转载请注明出处。
在反破解中可能需要把一段已经在内存中的函数代码拷贝出来,到另一个地方运行。在远程注入中也会遇到拷贝内存中的代码作为shellcode的情况。比如这段代码:
long __stdcall TrulyUnloadDLL(long a)
{
long c=1;
printf("\nKKK\n");
return a+c;
}
void LoadHooks()
{
void* p=malloc(100);
memcpy(p,TrulyUnloadDLL,100);
DWORD oldpro;
VirtualProtect(p,100,PAGE_EXECUTE_READWRITE,&oldpro);
typedef long (__stdcall *ptFun)(long a);
ptFun pFun=(ptFun)p;
pFun(1);
}
在VS2010中默认情况下会运行失败。有两个注意点:
1 关闭增量连接开关
通常认为函数指针直接指向内存中的函数体指令。但是在vs中,如果打开了增量编译,函数指针指向的是一个跳转表,由跳转表的jmp指令跳转到真正的地址。(这个跳转表叫做ILT,增量连接表,为了方便编译而存在)。
在工程的属性-连接器-启用增量连接-否关闭之。
2 关闭基本运行时检查-堆栈帧检查
在调用函数后,VC编译器会自动加上调用_CRT_checkESP检查堆栈。但是在我们的代码副本中的_CRT_checkESP地址竟然是错误的(原因未知,是地址重定位过了?)
在属性-C/C++ - 基本运行时检查选择未初始化变量(也就是去掉了堆栈帧检查)