远程的DLL注入进程的实现
进程注入的原理就是让目标进程执行一段自己的代码,而这个实现的前提是
1.让目标进程可以访问我们自己写的代码
2.让目标进程跳到我们的代码入口执行
3.执行完成后可以正常退出,不引发进程的crash。
这里采用的是DLL远程注入方式.
大概原理是基本上所有的进程都会依赖kernel32.dll,而这个DLL中有2个导出函数LoadLibraryA和LoadLibraryW,其实这2个函数没啥 区别,一个是多字节的接口,一个是宽字节的接口,而多字节的会在内部对多字节进行转换成宽字节,再调用宽字节继续执行。
而windows为了节省内存,所有的动态库都会加载到同一物理内存地址,同时为了便于内存管理,这些物量内存也会引映射到不同进程的内一虚执地址空间。所以A进程中的某个API函数和另一个进程的地址的样同。
而为了让这个目标进程能正常调用我们的代码,可以采用开线程的方式来实现,这样不影响进程原有的运行。
这样我们可以采用API函数CreateRemoteThread来产生远程线程,而线程的入口函数使用LoadLibraryA(W),参数为DLL的路径。
所以为了实现以上功能,需要解决2个问题,CreateRemoteThread的入口地址LoadLibraryA(W)和LoadLibraryA(W)的存储路径,且这个路径地址必须为目标进程的地址。
第一个问题可按上面说的,用协注入进程来获取LoadLibraryA(W)的地址。
第二个问题可以采用打开目标进程,使用API函数VirtualAllocEx来申请一段目标进程内存地址,然后将LoadLibraryA(W)的存储路径复制进去,然后将这个地址传给CreateRemoteThread远程线程函数即可。
BOOL InjectProcessByPID(DWORD dwPId, TCHAR *szDllName)
{
HANDLE hProcess = NULL;
LPVOID pRemoteBuf = NULL;
FARPROC pThreadProc = NULL;
DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPId)))
{
printf("[ERROR] OpenProcess(%d) failed!!! [%d]", dwPId, GetLastError());
return FALSE;
}
TCHAR path[MAX_PATH] = {0};
GetModuleFileNameEx(hProcess, NULL, path, MAX_PATH + 1);
for (unsigned int i = 0; i < m_WhiteList.size(); i++)
{
if (_tcsstr(path, m_WhiteList[i].c_str()))
{
_tprintf(TEXT("white list :%s"), m_WhiteList[i].c_str());
return FALSE;
}
}
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);
#ifdef UNICODE
pThreadProc = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryW");
#else
pThreadProc = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
#endif
if (!ExecuteRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pThreadProc, pRemoteBuf))
{
printf("[ERROR] ExecuteRemoteThread() failed!!!");
}
VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);
CloseHandle(hProcess);
return TRUE;
}
BOOL ExecuteRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
HANDLE hThread = NULL;
FARPROC pFunc = NULL;
if (IsVistaOrLater()) // Vista, 7, Server2008
{
#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF)
pFunc = GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtCreateThreadEx");
if (pFunc == NULL)
{
printf(" MyCreateRemoteThread() : GetProcAddress("NtCreateThreadEx") failed!!! [%d]
", GetLastError());
return FALSE;
}
INT_PTR rtn = ((_NtCreateThreadEx)pFunc)(&hThread, THREAD_ALL_ACCESS, NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL);
if (hThread == NULL)
{
printf("win7 MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]", GetLastError());
return FALSE;
}
}
else
{
hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
if (hThread == NULL)
{
printf("xp MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]", GetLastError());
return FALSE;
}
}
if (WAIT_FAILED == WaitForSingleObject(hThread, INFINITE))
{
printf("MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]", GetLastError());
return FALSE;
}
return TRUE;
}