#include <windows.h>
#include "tchar.h"
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL, hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL;
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc;
// #1. 通过进程ID,打开进程,并获得进程句柄
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
{
_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
return FALSE;
}
// #2. 在目标进程中开辟虚拟空间,目的是在目标进程中写入参数。
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
// #3. LoadLibraryW函数原型
//HMODULE LoadLibraryW(
//[in] LPCWSTR lpLibFileName
//);
//在目标进程中写入参数,这个参数也就是LoadLibrary传入的动态链接库。
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
// #4. 见下面详细分析
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
// #5. 在目标进程创建远程线程,通过目标进程函数地址(pThreadProc),启动远程线程函数pThreadProc,并传入参数pRemoteBuf
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
调用
int main()
{
InjectDll(进程id, L"dll路径");
}
下面对于上面的第四点进行详细分析
目的是在目标进程注入(载入)我们自己写的dll。
首先,目标进程并非我们自己写的程序。
其次,载入dll可以用LoadLibrary函数。
思路:只有调用目标进程中LoadLibrary函数,传入我们写好的dll作为参数,不就可以在目标进程载入我们的dll了吗。
如何获得目标进程的LoadLibrary函数是问题的核心。
①、LoadLibrary是系统api,并且封装在kernel32.dll中
②、只要是Dll只会载入物理内存一次,其它应用程序都会共享此Dll,在系统中所有调用此Dll的进程,都会把Dll放到相同的虚拟地址空间中,看下面两个例子。
第一个举例进程
第二个举例进程
用两个截图例子,再次解释,同一个dll被载入不同进程中,占用相同的开始虚拟地址,那么LoadLibraryW函数地址在每个进程中的虚拟地址也是一样的了,所以在本进程中GetProcAddress(hMod, "LoadLibraryW")得到的LoadLibraryW函数地址,同样也是LoadLibraryW函数地址在目标进程中的地址。
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");