远程线程注入
原理:
打开目标进程以后,将要注入的动态库的路径写入这个地址空间,然后调用开启远程线程的函数,来执行LoadLibraryA或者LoadLibraryW(其实不存在LoadLibrary这个函数,他只是一个宏,如果是UNICODE环境的话会调用LoadLibraryW,否则就是LoadLibraryA)来执行这个动态库,动态库一旦被加载起来,DllMain中的DLL_PROCESS_ATTACH则会被执行,我们将要执行的代码写在DLL_PROCESS_ATTACH分支即可。之所以把LoadLibraryA(W)作为线程函数,是因为它刚好只有1个参数,在不考虑参数类型的情况下,可以认为它的原型与线程函数一样,示例如下:
HMODULE WINAPI LoadLibraryW(
_In_ LPCWSTR lpLibFileName
);
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
注意:由于从Windows Vista 开始,微软为了增强系统的安全性,对系统服务和登录用户进行了会话(Session)隔离,系统服务属于会话0,登录的第一个用户属于会话1,之前系统服务和第一个登录用户都属于会话0。此方法并不能突破SESSION 0隔离。原因是在 CreateRemoteThread 函数中对此进行了检查,如果不在同一会话中,调用 CsrClientCallServer 为新进程进行登记的操作就会失败,这就直接导致了线程创建的失败。
步骤:
- 打开目标进程
- 在目标进程中申请空间
- 将要注入的Dll路径写入刚申请的空间中
- 获取LoadLibrary函数地址
- 在目标进程中创建线程,线程回调函数就是LoadLibrary函数,回调函数参数就是要注入的Dll路径
- 等待线程结束
- 清理环境
代码如下:
BOOL CBiaoBai1Dlg::CreateRemoteThreadInjectDll(DWORD dwProcessId, char* pszDllFileName) { // 1.打开目标进程 HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, // 打开权限 FALSE, // 是否继承 dwProcessId); // 进程PID if (NULL == hProcess) { MessageBox("打开目标进程失败!"); return FALSE; } // 2.在目标进程中申请空间 LPVOID lpPathAddr = VirtualAllocEx( hProcess, // 目标进程句柄 0, // 指定申请地址 strlen(pszDllFileName) + 1, // 申请空间大小 MEM_RESERVE | MEM_COMMIT, // 内存的状态 PAGE_READWRITE); // 内存属性 if (NULL == lpPathAddr) { MessageBox("在目标进程中申请空间失败!"); CloseHandle(hProcess); return FALSE; } // 3.在目标进程中写入Dll路径 SIZE_T dwWriteSize = 0; if (FALSE == WriteProcessMemory( hProcess, // 目标进程句柄 lpPathAddr, // 目标进程地址 pszDllFileName, // 写入的缓冲区 strlen(pszDllFileName) + 1, // 缓冲区大小 &dwWriteSize)) // 实际写入大小 { MessageBox("目标进程中写入Dll路径失败!"); CloseHandle(hProcess); return FALSE; } //获取LoadLibraryA的函数地址 //FARPROC可以自适应32位与64位 FARPROC pFuncProcAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (NULL == pFuncProcAddr) { MessageBox("获取LoadLibrary函数地址失败!"); CloseHandle(hProcess); return FALSE; } // 4.在目标进程中创建线程 HANDLE hThread = CreateRemoteThread( hProcess, // 目标进程句柄 NULL, // 安全属性 NULL, // 栈大小 (PTHREAD_START_ROUTINE)pFuncProcAddr, // 回调函数 lpPathAddr, // 回调函数参数 NULL, // 标志 NULL // 线程ID ); if (NULL == hThread) { MessageBox("目标进程中创建线程失败!"); CloseHandle(hProcess); return FALSE; } // 5.等待线程结束 WaitForSingleObject(hThread, -1); DWORD code; GetExitCodeThread(hThread, &code); code = GetLastError(); // 6.清理环境 VirtualFreeEx(hProcess, lpPathAddr, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); return TRUE; }
直面挫折,顽强生长