说起远程线程注入,首先要了解远程线程的一个概念,我们每一个进程中都有很多的线程,如果要在本进程内创建一个线程就可以使用CreateThread
cHANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD SIZE_T dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier );
那么相对应的如果要在其他进程内部创建一个线程,Windows提供了CreateRemoteThread
函数,这个函数除了hProcess
之外,其他参数与CreateThread
完全相同。
cHANDLE CreateRemoteThread( HANDLE hProcess, // handle to process LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD SIZE_T dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier );
另外远程线程注入需要在目标进程中的一个线程调用LoadLibrary
来载入我们想要的Dll。但由于我们不能轻易控制别人进程中的线程,所以这种方法要求我们在目标进程中创建一个线程,由于这个线程完全是由我们来创建的,所以我们就可以执行代码了。
而hProcess
用来表示新创建的线程归哪个进程所有。那线程创建完了,怎么样让这个线程去执行LoadLibrary
呢?
CreateRemoteThread
函数的lpStartAddress
参数是线程回调函数的内存地址。
观察一下lpStartAddress
和LoadLibrary
lpStartAddress
cDWORD WINAPI ThreadProc( LPVOID lpParameter // thread data );
LoadLibrary
cHMODULE LoadLibrary(LPCTSTR lpFileName // file name of module );
都是4个字节,很巧合,而这个巧合就可以让我们把CreateRemoteThread
函数的lpStartAddress
参数填成LoadLibrary
,CreateRemoteThread
函数的lpParameter
参数填成我们的dll路径,那么线程一跑,LoadLibrary
就被调用,我们的dll自然就加载进目标进程了。
但是我们还缺少LoadLibrary
的参数怎么办,Windows为我们提供了VirtualAllocEx
函数,他可以让一个进程在另一个进程中分配内存:
cLPVOID VirtualAllocEx( HANDLE hProcess, // process to allocate memory LPVOID lpAddress, // desired starting address SIZE_T dwSize, // size of region to allocate DWORD flAllocationType, // type of allocation DWORD flProtect // type of access protection );
申请到空间后,我们就需要使用WriteProcessMemory
把我们的dll路径写进目标进程中。
cBOOL WriteProcessMemory( [in] HANDLE hProcess, [in] LPVOID lpBaseAddress, [in] LPCVOID lpBuffer, [in] SIZE_T nSize, [out] SIZE_T *lpNumberOfBytesWritten );
接着我们调用CreateRemoteThread
是将申请到的空间地址作为参数传进去就ok了
上面就是远程线程注入的基本知识点,接着上代码
c# include <iostream> # include <windows.h> using namespace std; int main() { //获取进程句柄 DWORD dwProcId = 0; HWND hWndCalc = ::FindWindow(NULL, "计算器"); ::GetWindowThreadProcessId(hWndCalc, &dwProcId); HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcId); //在目标进程中申请一块内存,用来存储dll的路径 char szDllPath[] = { "E:\\Na1r\\windows\\12\\Dll1\\Debug\\Dll1.dll" }; LPVOID pBuff = VirtualAllocEx( hProc, NULL, //系统自动分配地址 sizeof(szDllPath), MEM_COMMIT, PAGE_READWRITE ); DWORD dwBytesWrited = 0; //写入dll路径 BOOL bRet = WriteProcessMemory( hProc, pBuff, szDllPath, sizeof(szDllPath), &dwBytesWrited); auto pfnLoadLibrary = GetProcAddress( GetModuleHandle("Kernel32"), "LoadLibraryA"); //创建远程线程 HANDLE hThread = CreateRemoteThread( hProc, NULL, 0, (LPTHREAD_START_ROUTINE)pfnLoadLibrary, pBuff, 0, NULL); //退出 WaitForSingleObject(hThread, INFINITE); HMODULE hModDll1 = NULL; GetExitCodeThread(hThread, (PDWORD)&hModDll1); auto pfnFreeLibrary = GetProcAddress( GetModuleHandle("Kernel32"), "FreeLibrary"); HANDLE hThreadFree = CreateRemoteThread( hProc, NULL, 0, (LPTHREAD_START_ROUTINE)pfnFreeLibrary, hModDll1, 0, NULL); //释放句柄 CloseHandle(hProc); CloseHandle(hThread); return 0; }
本文作者:Na1r
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!