原理分析:
远程线程注入是很常见且古老的注入方式之一。其原理是根据Win32函数CreateRemoteThread在目标进程中创建一个线程,然后加载注入DLL。无巧不成书,创建线程的所需的回调函数恰恰与LoadLibrary声明结构几乎一模一样。
//Thread PROC
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter);
//显式加载DLL函数
HMODULE LoadLibraryA(LPCSTR lpLibFileName);
HMODULE LoadLibraryW(LPCWSTR lpLibFileName);
操作步骤:
- 查找窗口句柄
- 根据窗口句柄获取进程ID
- 根据进程ID获取进程句柄
- 使用VirtualAllocEx在目标进程中申请空间,存放注入DLL路径
- 使用CreateRermoteThread函数创建远程线程,其回调例程为LoadLibrary,参数为上一步骤写入的DLL路径
注意事项:
- 32位的进程只能注入32位的DLL,64位同理
- LoadLibrayW和LoadLibraryA与写入进程的字符有关
- DLL路径需要转义,路径如 "C:\TestDLL.dll",需要转义为"C:\\TestDLL.dll"
源代码示例:
//1.查找窗口句柄
HWND hwnd=::FindWindowW(L"Notepad",NULL);
//2.根据窗口句柄获取进程Id
DWORD tid = 0;
::GetWindowThreadProcessId(hwnd,&tid);
//3.根据进程ID,获取进程句柄
HANDLE handle=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,tid);
//4.在目标进程中申请空间,存放注入的DLL路径
LPVOID addr=::VirtualAllocEx(handle,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if(addr==NULL){
//申请内存失败
return ;
}
TCHAR szBuf[MAX_PATH] = L"C:\\TestDLL.dll";
SIZE_T size=0;
BOOL bRet = WriteProcessMemory(handle,addr,szBuf,MAX_PATH,&size);
if(!bRet){
//写入内存失败
return;
}
//5.远程开启线程,注入DLL
if(::CreateRemoteThread(handle,NULL,0(LPTHREAD_START_ROUTINE)LoadLibrary,addr,0,NULL)){
//注入成功
}