远程线程注⼊
原理:
  打开⽬标进程以后,将要注⼊的动态库的路径写⼊这个地址空间,然后调⽤开启远程线程的函数,来执⾏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 为新进程进⾏登记的操作就会失败,这就直接导致了线程创建的失败。
步骤:
1. 打开⽬标进程
2. 在⽬标进程中申请空间
3. 将要注⼊的Dll路径写⼊刚申请的空间中
4. 获取LoadLibrary函数地址
5. 在⽬标进程中创建线程,线程回调函数就是LoadLibrary函数,回调函数参数就是要注⼊的Dll路径
6. 等待线程结束
7. 清理环境
代码如下:
BOOL CBiaoBai1Dlg::CreateRemoteThreadInjectDll(DWORD dwProcessId, char* pszDllFileName)waitforsingleobject函数
{
// 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;
}