/*
一直都有人说只用C/C++写的代码,在远程线程中重定位很难,我一直怀疑是否纯C代
码真的实现不了重定位.经过二个小时的思考,下面给出一个例子,用纯C代码实现
重定位,进一步说明了一个问题,说某个问题实现不了的时候,你自己是否真的了解
了问题本身!
VC++ 6.0 SP5编译通过,WinXP SP2及Win2k SP4调试运行通过
重定位基址后所有的变量和函数都用这样的方式引用:
pValue=Addr+(Value-RelocThread);
pfnFunc=Addr+(Func-RelocThread);
(Value-RelocThread)或(Func-RelocThread)会被编译成常量,所以没有多余计算
代码就像在汇编中一样高效,代码在用户态内存的什么位置运行都应该没有问题.
其实这里主要就是你要了解call指令的机器代码格式及C/C++怎么安排堆栈.
在我的机器上程序输出了下面内容:
In RelocThread:
I can Found My start address myself=0x00401000
and Global Value Msg=0x408030
Hello C++! I Love you forever!
In function main:
RelocThread=0x00401000,Msg=0x00408030
可以很清楚的看到重定位完全没有问题.最后调用ExitThread返回,是因为堆栈给
我们玩的不平衡了,直接返回会出错
可以将一个线程函数和它要用的子函数及变量放在一个C文件中编译,然后用blink
将这个C文件生成的obj文件连接成二进制代码,没有PE结构之类的纯代码,做成
shellcode一样的数组最后可以用远程线程直接将这段代码插入到目标进程运行.
当然同样要解决的是怎么取得API地址.
我是怎么知道这样做的?哈哈,我昨晚上睡觉时想起来的,堆栈?我熟啊!汇编?我熟啊!
C/C++?我更熟啊!呵呵!自吹一下.^_-
Code by kruglinski(kruglinski@gmail.com)
Blog:Kruglinski.blogchina.com
*/
#include "stdio.h"
#include "conio.h"
#include "windows.h"
char Msg[]="Hello C++! I Love you forever!";
int __stdcall RelocThread(int Param)
{
int Addr=0;
char *pMsg=NULL;
if(!Param)
{
Addr=((int(__stdcall*)(void))RelocThread)();//想想如果故意让堆栈不平衡会怎么样
Addr=5+Addr+*(int*)(Addr+1);
pMsg=(char*)(Addr+(int)&Msg-(int)&RelocThread);
printf("In RelocThread:\n");
printf("I can Found My start address myself=0x%08X\nand Global Value Msg=0x%X\n",Addr,pMsg);
printf("%s\n",pMsg);
ExitThread(0);
}
return (*(int*)((int)&Param-4))-5;
}
void main(void)
{
HANDLE hThread=CreateRemoteThread(GetCurrentProcess(),NULL,0,RelocThread,0,0,NULL);
WaitForSingleObject(hThread,INFINITE);
printf("In function main:\nRelocThread=0x%08X,Msg=0x%08X\n",RelocThread,Msg);
getch();
}
参考资料:
《Developing Your Own Unix-Like OS on IBM PC》-《Stack in C/C++》