大家好,我是FISH ,以下代码只是属于思路,都是我自己KEY进去的,有错误很抱歉,我尽量注意,
内容来自Greg hoglund 的<<exploiting online games>> .
给应用程序注入新的代码,最常用的技巧是DLL注入,使用这个方法,可以让远线程加载到你自己
设计的DLL. DLL本身的功能可以是挂钩函数,修改目标程序的内存空间,DLL注入是很隐藏,很方便的
注入手段,(实际上,该方法很容易被发现,有不少常规方法可以发现注入的DLL).
DLL注入的技巧是让目标进程中已存在的一个线程跳到某个代码片段,该代码片段调用
Loadlibiary 来加载模块,这样的思路有很多种实现方法. 比如:使用CreateRemoteThread创建
新的远程线程,这里介绍的技巧没有创建新线程,而是劫持现有的线程进行加载操作.
首先,需要将加载的DLL代码写到远程进程.定义代码如下:
char InjectedcodePage[4096]=
{ 0xb8 ,00,00,00,00
//mov EAX,0h | Pointer to LoadlibraryA() (DWORD)
0xBB,00,00,00,00
//mov EBX,0h | DLLname to inject(DWORD)
0x53, //push EBX
0xff, 0xD0, //call EAX
0x5b, //pop ebx
0xcc /int 3h
//dll name string will be placed here
};
int length_of_injection_code=15;
上述代码有一些占位字节用来填充LoadlibraryA()和需要加载的DLL名指针地址.
对于LoadLibraryA的地址,代码简单的假设被注入远程的LoadLibraryA地址和现在的进程地址相同
作者没有遇到过不同的情况,所以假设这样做是安全的.[评: 实际上,目前对不少游戏这样操作不
能得到正确的地址,原因是KERNEL32.dll]位置被移动了.]
farproc loadlibproc=getprocaddress(
getmodulehandle("kernel32.dll"),
LoadLibraryA};
对于dll名称,可以将DLL名直接写在上述的代码段之后,即代码中偏移为15的地方.下面要计算所有
要用到的偏移.
char *Dllname;
Dword *EAX, *EBX;
DLLname=((char*)((dword)injectedcodepage
+length_of_inject_code);
Eax=(dowrd)(injectedcodepage+1);
ebx=(dword)(injectedcodepage+6);
这样就得到了两处占位字节序列的地址和将要填写的dll名地址. 需要将代码写到远端进程才能
填写这几个地址,因为代码将要在远端执行,而不是本地.
内嵌在代码段中的INT3指令用于和调试器交互,内嵌断点通知调试器,注入代码执行完毕
现在不管这些,先了解一下如何查找dll代码位置.
下面的代码,假设已经打开调试器并发送初始调试信号,如果该操作为附加操作,将会为初始
断点事件创建线程.代码将劫持该线程并利用该线程运行注入的代码片段,在调试时间循环中,使用
如下代码获取线程句柄.
Hthread=fopenthread(
thread_all_access,
false,
dbg_ent.dwthreadtd);
记得使用句柄后关闭句柄
dll名称为dll文件的全路径, hprocess为被调试的团段进程,hmodulebase可以从调试事件循环中
获取,或者可以假定为0x400000 为基地址,(绝大多数情况都是这样).从调试时间循环获取的方法为:
if (dbg_evt.dwdebugEventcode==create_process_debug_event)
{
Hmodulebase=dng_evt.u.createprocessinfo.lpbaseofimage;
}
注入的下一不走为定位远程进程的有效的可执行代码段. 这需要解析pe文件头,查找DOS头:
res=readprocessmemory(
hprocess,
hmodulebase,
&dosdhr,
sizeof(doshdr),
&read);
if ((!res)||(read!=sizeof(doshdr)))
{
printf("could not get dos header/n");
return false;
}
现在通过mz字符串检查文件是否为DOS头.
if (doshdr.e_magic(!=image_dos_signature)
{
printf("could not find mz for dos header/n")'
return false;
}
通过dos头信息查找nt头信息
//get nt header
res=readprocessmemory(
hprocess,
(void*)((dword)hmodulebase+
&NThdr,
sizeof(nthdr),
&read);
if (!res)||(READ!=sizeof(nyhdr)))
printf("could not get nt header/n")'