大家好,我是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")'
