22.4 使用远程线程来注入DLL
在目标进程中创建一个新线程,并让此线程加载需要插入的DLL。
1.在另一个进程中创建线程
Windows提供了一个称为CreateRemoteThread的函数,使我们能够非常容易地
在另一个进程中创建线程:
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId
);
CreateRemoteThread与CreateThread很相似,差别在于它增加了一个参数 hProcess。该参数指明拥有新创建线程的进程。参数 pfnStartAddr指明线程函数的内存地址。当然,该内存地址与远程进程是相关的。线程函数的代码不能位于你自己进程的地址空间中。
2.必须执行的操作步骤做一个归纳:
1)使用VirtualAllocEx函数,分配远程进程的地址空间中的内存。
2)使用WriteProcessMemory函数,将DLL的路径名拷贝到第一个步骤中已经分配内存中。
3)使用GetProcAddress函数,获取LoadLibraryA或LoadLibratyW函数的实地址(在Kernel32.dll中)。
4)使用CreateRemoteThread函数,在远程进程中创建一个线程,它调用正确的LoadLibrary函数,为它传递第一个步骤中分配的内存的地址。这时,DLL已经被插入远程进程的地址空间中,同时DLL的DllMain函数接收到一个DLL_PROCESS_ATTACH通知,并且能够执行需要的代码。当DllMain函数返回时,远程线程从它对LoadLibrary的调用返回到BaseThreadStart函数(第6章中已经介绍)。然后BaseThreadStart调用ExitThread,使远程线程终止运行。
现在远程进程拥有第一个步骤中分配的内存块,而DLL则仍然保留在它的地址空间中。若要将它删除,需要在远程线程退出后执行下面的步骤:
5)使用VirtualFreeEx函数,释放第一个步骤中分配的内存。
6)使用GetProcAddress函数,获得FreeLibrary函数的实地址(在Kernel32.dll中)。
7)使用CreateRemoteThread函数,在远程进程中创建一个线程,它调用FreeLibrary函数,传递远程DLL的HINSTANCE。
这就是它的基本操作步骤。这种插入DLL的方法存在的唯一一个不足是,Windows98并不支持这样的函数。只能在Windows2000上使用这种方法。