工具介紹及使用請移步:http://blog.csdn.net/sunflover454/article/details/50441014
本文首發在零日安全論壇:http://www.jmpoep.com/thread-833-1-1.html
使用NtCreateThreadEx + LdrLoadDll方式實現遠程線程注入的特色在於比一般的遠程線程注入穩定,可以注入系統進程,服務進程等。
核心源代碼如下,完整源代碼,請在文章末尾下載。
- //OD跟蹤,發現最后調用的是NtCreateThreadEx,所以這里手動調用
- HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
- {
- HANDLE hThread = NULL;
- FARPROC pFunc = NULL;
- if( IsVistaOrLater())// Vista, 7, Server2008
- {
- pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
- if( pFunc == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 調用失敗!錯誤代碼: [%d]", GetLastError());
- return NULL;
- }
- ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
- if( hThread == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 調用失敗!錯誤代碼: [%d]", GetLastError());
- return NULL;
- }
- }
- else// 2000, XP, Server2003
- {
- hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
- if( hThread == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 調用失敗!錯誤代碼: [%d]", GetLastError());
- return NULL;
- }
- }
- if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 調用失敗!錯誤代碼: [%d]", GetLastError());
- return NULL;
- }
- return hThread;
- }
//OD跟蹤,發現最后調用的是NtCreateThreadEx,所以這里手動調用 HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf) { HANDLE hThread = NULL; FARPROC pFunc = NULL; if( IsVistaOrLater())// Vista, 7, Server2008 { pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx"); if( pFunc == NULL ) { MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 調用失敗!錯誤代碼: [%d]", GetLastError()); return NULL; } ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL); if( hThread == NULL ) { MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 調用失敗!錯誤代碼: [%d]", GetLastError()); return NULL; } } else// 2000, XP, Server2003 { hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL); if( hThread == NULL ) { MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 調用失敗!錯誤代碼: [%d]", GetLastError()); return NULL; } } if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) { MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 調用失敗!錯誤代碼: [%d]", GetLastError()); return NULL; } return hThread; }
- //在目標進程中創建線程並注入dll
- BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
- {
- BOOL bRet = FALSE;
- HANDLE hProcess = NULL, hThread = NULL;
- LPVOID pCode = NULL;
- LPVOID pThreadData = NULL;
- __try
- {
- if(!EnableDebugPrivilege())
- {
- MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 調用失敗!錯誤代碼: [%d]", GetLastError());
- return -1;
- }
- //打開目標進程;
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
- DWORD dwError = GetLastError();
- if (hProcess == NULL)
- __leave;
- //申請空間,把我們的代碼和數據寫入目標進程空間里;
- //寫入數據;
- THREAD_DATA data;
- HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
- data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
- data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
- memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
- data.DllPath = NULL;
- data.Flags = 0;
- data.ModuleHandle = INVALID_HANDLE_VALUE;
- pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
- if (pThreadData == NULL)
- __leave;
- BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
- if (!bWriteOK)
- __leave;
- MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
- //寫入代碼;
- DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
- pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (pCode == NULL)
- {
- MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 調用失敗!錯誤代碼: [%d]", GetLastError());
- __leave;
- }
- bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
- if (!bWriteOK)
- __leave;
- MyOutputDebugStringA("pCode = 0x%p", pCode);
- //創建遠程線程,把ThreadProc作為線程起始函數,pThreadData作為參數;
- hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
- if (hThread == NULL)
- __leave;
- //等待完成;
- WaitForSingleObject(hThread, INFINITE);
- bRet = TRUE;
- }
- __finally
- {
- if (pThreadData != NULL)
- VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
- if (pCode != NULL)
- VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
- if (hThread != NULL)
- CloseHandle(hThread);
- if (hProcess != NULL)
- CloseHandle(hProcess);
- }
- return bRet;
- }
//在目標進程中創建線程並注入dll BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath) { BOOL bRet = FALSE; HANDLE hProcess = NULL, hThread = NULL; LPVOID pCode = NULL; LPVOID pThreadData = NULL; __try { if(!EnableDebugPrivilege()) { MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 調用失敗!錯誤代碼: [%d]", GetLastError()); return -1; } //打開目標進程; hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId); DWORD dwError = GetLastError(); if (hProcess == NULL) __leave; //申請空間,把我們的代碼和數據寫入目標進程空間里; //寫入數據; THREAD_DATA data; HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll"); data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString"); data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll"); memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR)); data.DllPath = NULL; data.Flags = 0; data.ModuleHandle = INVALID_HANDLE_VALUE; pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (pThreadData == NULL) __leave; BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL); if (!bWriteOK) __leave; MyOutputDebugStringA("pThreadData = 0x%p", pThreadData); //寫入代碼; DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc; pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pCode == NULL) { MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 調用失敗!錯誤代碼: [%d]", GetLastError()); __leave; } bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL); if (!bWriteOK) __leave; MyOutputDebugStringA("pCode = 0x%p", pCode); //創建遠程線程,把ThreadProc作為線程起始函數,pThreadData作為參數; hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData); if (hThread == NULL) __leave; //等待完成; WaitForSingleObject(hThread, INFINITE); bRet = TRUE; } __finally { if (pThreadData != NULL) VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE); if (pCode != NULL) VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE); if (hThread != NULL) CloseHandle(hThread); if (hProcess != NULL) CloseHandle(hProcess); } return bRet; }以上是遠程線程注入類的兩個核心函數,下面是調用實例:
- Cx64Inject inject;
- if (inject.InjectDll(g_dwPID,g_szDllPath))
- {
- ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
- }
- else
- {
- ::MessageBox(NULL,L"注入失敗!",L"失敗",MB_ICONERROR);
- }
Cx64Inject inject; if (inject.InjectDll(g_dwPID,g_szDllPath)) { ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION); } else { ::MessageBox(NULL,L"注入失敗!",L"失敗",MB_ICONERROR); }
封裝成類了,使用起來很簡單的。
有一點需要注意的是x64注入的意思是只能將64位dll注入64位進程。
x86注入的意思是32位dll注入32位進程。
源代碼下載:
DLL注入工具x86Inject_v1.2完整源代碼(VS2010)下載地址:http://download.csdn.net/detail/sunflover454/9385421
DLL注入工具x64Inject_v1.1完整源代碼(VS2010)下載地址:http://download.csdn.net/detail/sunflover454/9385408
相關下載:
DLL注入工具成品(x86)下載地址:http://download.csdn.net/detail/sunflover454/9385346
DLL注入工具成品(x64)下載地址:http://download.csdn.net/detail/sunflover454/9385355
轉載請注明出處,謝謝!
原帖地址:http://blog.csdn.net/sunflover454/article/details/50441146
jpg改rar