Ring3下的DLL注入(NtCreateThreadEx + LdrLoadDll方式實現,可以注入系統進程)


工具介紹及使用請移步:http://blog.csdn.net/sunflover454/article/details/50441014

本文首發在零日安全論壇:http://www.jmpoep.com/thread-833-1-1.html


使用NtCreateThreadEx + LdrLoadDll方式實現遠程線程注入的特色在於比一般的遠程線程注入穩定,可以注入系統進程,服務進程等。


核心源代碼如下,完整源代碼,請在文章末尾下載。

 

  1. //OD跟蹤,發現最后調用的是NtCreateThreadEx,所以這里手動調用  
  2. HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)  
  3. {  
  4.         HANDLE hThread = NULL;  
  5.         FARPROC pFunc = NULL;  
  6.         if( IsVistaOrLater())// Vista, 7, Server2008  
  7.         {  
  8.                 pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");  
  9.                 if( pFunc == NULL )  
  10.                 {  
  11.                         MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 調用失敗!錯誤代碼: [%d]", GetLastError());  
  12.                         return NULL;  
  13.                 }  
  14.                 ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);  
  15.                 if( hThread == NULL )  
  16.                 {  
  17.                         MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 調用失敗!錯誤代碼: [%d]", GetLastError());  
  18.                         return NULL;  
  19.                 }  
  20.         }  
  21.         else// 2000, XP, Server2003  
  22.         {  
  23.                 hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);  
  24.                 if( hThread == NULL )  
  25.                 {  
  26.                         MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 調用失敗!錯誤代碼: [%d]", GetLastError());  
  27.                         return NULL;  
  28.                 }  
  29.         }  
  30.         if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )  
  31.         {  
  32.                 MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 調用失敗!錯誤代碼: [%d]", GetLastError());  
  33.                 return NULL;  
  34.         }  
  35.         return hThread;  
  36. }  
//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;
}

  1. //在目標進程中創建線程並注入dll  
  2. BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)  
  3. {  
  4.         BOOL bRet = FALSE;  
  5.         HANDLE hProcess = NULL, hThread = NULL;  
  6.         LPVOID pCode = NULL;  
  7.         LPVOID pThreadData = NULL;  
  8.         __try  
  9.         {  
  10.                 if(!EnableDebugPrivilege())  
  11.                 {  
  12.                         MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 調用失敗!錯誤代碼: [%d]", GetLastError());  
  13.                         return -1;  
  14.                 }  
  15.                 //打開目標進程;  
  16.                 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);  
  17.                 DWORD dwError = GetLastError();  
  18.                 if (hProcess == NULL)  
  19.                         __leave;  
  20.                 //申請空間,把我們的代碼和數據寫入目標進程空間里;  
  21.                 //寫入數據;  
  22.                 THREAD_DATA data;  
  23.                 HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");  
  24.                 data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");  
  25.                 data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");  
  26.                 memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));  
  27.                 data.DllPath = NULL;  
  28.                 data.Flags = 0;  
  29.                 data.ModuleHandle = INVALID_HANDLE_VALUE;  
  30.                 pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);  
  31.                 if (pThreadData == NULL)  
  32.                         __leave;  
  33.                 BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);  
  34.                 if (!bWriteOK)  
  35.                         __leave;  
  36.                 MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);  
  37.                 //寫入代碼;  
  38.                 DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;  
  39.                 pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);  
  40.                 if (pCode == NULL)  
  41.                 {  
  42.                         MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 調用失敗!錯誤代碼: [%d]", GetLastError());  
  43.                         __leave;  
  44.                 }                  
  45.                 bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);  
  46.                 if (!bWriteOK)  
  47.                         __leave;  
  48.                 MyOutputDebugStringA("pCode = 0x%p", pCode);  
  49.                 //創建遠程線程,把ThreadProc作為線程起始函數,pThreadData作為參數;  
  50.                 hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);  
  51.                 if (hThread == NULL)  
  52.                         __leave;  
  53.                 //等待完成;  
  54.                 WaitForSingleObject(hThread, INFINITE);  
  55.                 bRet = TRUE;  
  56.         }  
  57.         __finally  
  58.         {  
  59.                 if (pThreadData != NULL)  
  60.                         VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);  
  61.                 if (pCode != NULL)  
  62.                         VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);  
  63.                 if (hThread != NULL)  
  64.                         CloseHandle(hThread);  
  65.                 if (hProcess != NULL)  
  66.                         CloseHandle(hProcess);  
  67.         }  
  68.    
  69.         return bRet;  
  70. }  
//在目標進程中創建線程並注入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;
}
以上是遠程線程注入類的兩個核心函數,下面是調用實例:

 

 

  1. Cx64Inject inject;  
  2. if (inject.InjectDll(g_dwPID,g_szDllPath))  
  3. {  
  4.         ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);  
  5. }  
  6. else  
  7. {  
  8.         ::MessageBox(NULL,L"注入失敗!",L"失敗",MB_ICONERROR);  
  9. }  
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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM