2012-02-26 121 views
6

我試圖編寫一個程序,使用CreateRemoteThread來注入一個dll。CreateRemoteThread返回ERROR_ACCESS_DENIED - Windows 7 DLL注入

問題是CreateRemoteThread拒絕工作。 GetLastError()返回5,這是ERROR_ACCESS_DENIED。我不知道爲什麼!

我正在從此視頻http://www.youtube.com/watch?v=H3O3hmXkt1I工作。

#include <iostream> 
#include <direct.h> 
#include <Windows.h> 
#include <TlHelp32.h> 

using namespace std; 


char* GetCurrentDir() 
{ 
    char* szRet = (char*)malloc(MAX_PATH); 
    _getcwd(szRet, MAX_PATH); 
    return szRet; 
} 

LPCTSTR SzToLPCTSTR(char* szString) 
{ 
    LPTSTR lpszRet; 
    size_t size = strlen(szString)+1; 

    lpszRet = (LPTSTR)malloc(MAX_PATH); 
    mbstowcs_s(NULL, lpszRet, size, szString, _TRUNCATE); 

    return lpszRet; 
} 

void WaitForProcessToAppear(LPCTSTR lpcszProc, DWORD dwDelay) 
{ 
    HANDLE   hSnap; 
    PROCESSENTRY32 peProc; 
    BOOL   bAppeared = FALSE; 

    while(!bAppeared) 
    { 
     if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE) 
     { 
      peProc.dwSize = sizeof(PROCESSENTRY32); 
      if(Process32First(hSnap, &peProc)) 
       while(Process32Next(hSnap, &peProc) && !bAppeared) 
        if(!lstrcmp(lpcszProc, peProc.szExeFile)) 
         bAppeared = TRUE; 
     } 
     CloseHandle(hSnap); 
     Sleep(dwDelay); 
    } 
} 

DWORD GetProcessIdByName(LPCTSTR lpcszProc) 
{ 
    HANDLE   hSnap; 
    PROCESSENTRY32 peProc; 
    DWORD   dwRet = -1; 

    if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE) 
    { 
     peProc.dwSize = sizeof(PROCESSENTRY32); 
     if(Process32First(hSnap, &peProc)) 
      while(Process32Next(hSnap, &peProc)) 
       if(!lstrcmp(lpcszProc, peProc.szExeFile)) 
        dwRet = peProc.th32ProcessID; 
    } 
    CloseHandle(hSnap); 

    return dwRet; 
} 

BOOL InjectDll(DWORD dwPid, char* szDllPath) 
{ 
    DWORD dwMemSize; 
    HANDLE hProc; 
    LPVOID lpRemoteMem, lpLoadLibrary; 
    BOOL bRet = FALSE; 

    if((hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL) 
    { 
     dwMemSize = strlen(szDllPath); 
     if((lpRemoteMem = VirtualAllocEx(hProc, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE)) != NULL) 
      if(WriteProcessMemory(hProc, lpRemoteMem, szDllPath, dwMemSize, NULL)) 
      { 
       lpLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); 
       if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibrary, lpRemoteMem, 0, NULL) != NULL) 
       { 
        bRet = TRUE; 
       } 
       cout << GetLastError(); 
      } 
    } 
    CloseHandle(hProc); 

    return bRet; 
} 

int main() 
{ 
    char szProc[MAX_PATH], szDll[MAX_PATH]; 
    char* szDllPath = (char*)malloc(MAX_PATH); 
    LPTSTR lpszProc = NULL; 

    for(;;) 
    { 
     cout << "Process: "; 
     cin >> szProc; 
     cout << "DLL: "; 
     cin >> szDll; 

     szDllPath = GetCurrentDir(); 
     strcat_s(szDllPath, MAX_PATH, "\\"); 
     strcat_s(szDllPath, MAX_PATH, szDll); 

     cout << "Waiting for process.. ." << szDllPath << " " << szDll << endl; 
     WaitForProcessToAppear(SzToLPCTSTR(szProc), 100); 
     if(InjectDll(GetProcessIdByName(SzToLPCTSTR(szProc)), szDllPath)) 
      cout << "Injection Succeeded!" << endl; 
     else 
      cout << "Injection Failed!" << endl; 
     cout << "\n"; 

    } 

    return 0; 

經過大量的谷歌搜索後,我無法找到一個原因,爲什麼這不應該工作。

CreateRemoteThread在Windows 7下無法工作? 如果是這樣,我有沒有犯過明顯的錯誤?

我看到
+1

這段代碼有很多bug。即使您沒有從api函數獲得FALSE返回,最相關的一個也會調用GetLastError。 – 2012-02-26 19:29:33

+0

我認爲你還應該確保你以管理員的身份運行你的東西,而不是像普通用戶那樣運行你的東西,因爲UAC可能會與注入過程混淆。 – foxx1337 2012-02-26 22:58:01

+1

與訪問相關的一個問題是,您不應該用'PROCESS_ALL_ACCESS'調用'OpenProcess'。使用所需的最小訪問權限進行調用。背後的原因記錄在這裏:http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx – 2012-02-27 14:11:13

回答

2

迫在眉睫的問題是,你沒有得到應爲這樣做的訪問令牌:

HANDLE hToken; 
TOKEN_PRIVILEGES tp; 
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); 

tp.PrivilegeCount = 1; 
LookupPrivilegeValue(NULL, _T("SeDebugPrivilege"), &tp.Privileges[0].Luid); 
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken); 

AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL); 
CloseHandle(hToken); 

我沒有時間通過​​所有的代碼看的權利,但這裏是什麼我撕掉了我以前的項目之一:

// returns open process handle 
HANDLE InjectDLL(DWORD dwPID, LPCWSTR szDLLPath, HMODULE* lphInjected) { 
    int  cszDLL; 
    LPVOID lpAddress; 
    HMODULE hMod; 
    HANDLE hThread; 
    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | 
     PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | 
     PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID); 

    if(hProcess == NULL) { 
    return NULL; 
    } 

    cszDLL = (wcslen(szDLLPath) + 1) * sizeof(WCHAR); 

    // Injection 
    lpAddress = VirtualAllocEx(hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    if(lpAddress == NULL) { 
    return NULL; 
    } 

    WriteProcessMemory(hProcess, lpAddress, szDLLPath, cszDLL, NULL); 

    hMod = GetModuleHandle(L"kernel32.dll"); 
    if(hMod == NULL) { 
    return NULL; 
    } 

    hThread = CreateRemoteThread(hProcess, NULL, 0, 
     (LPTHREAD_START_ROUTINE)(GetProcAddress(hMod, 
     "LoadLibraryW")), lpAddress, 0, NULL); 

    // Locate address our payload was loaded 
    if(hThread != 0) { 
    WaitForSingleObject(hThread, INFINITE); 
    GetExitCodeThread(hThread, (LPDWORD)lphInjected); 
    VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE); 
    CloseHandle(hThread); 
    } 

    return hThread != 0 ? hProcess : NULL; 
} 

看看是否有幫助。稍後再看。

0

我認爲CreateRemoteThread的()dll注入方法不能在窗口7

的CreateRemoteThread的(的第四個參數工作)是一個地址。在你的情況下,它是LoadLibraryA地址。但是,在Windows 7中,Kernel32.dll/LoadLibraryA基地址會在不同的進程中有所不同;因此,CreateRemoteThread()將不起作用,因爲地址不符合您的預期。這是我自己的看法,希望它會有所幫助。 :)

2

好的,你的代碼很可能在Windows 7和Vista中失敗,因爲「受保護的進程」,也就是隻能被其他受保護進程操縱的進程,比如explorer.exe等......在Windows 7 x32有一種方法:由於您可以加載未簽名的驅動程序,所以您已完成(在Google中搜索Alex Ionescu)。在Windows 7 64位系統,但是,你不能(咄!)

「的CreateRemoteThread的()的第四個參數是一個地址。在你的情況下,它是LoadLibraryA地址。然而,在Windows 7中,Kernel32中.dll/LoadLibraryA的基地址會在不同的過程中有所不同;「

好吧,這並不是真的,因爲儘管有ASLR,但DLL在每個進程中的相同地址共享。不過,DLL可以重新定義,但是在調用CreateRemoteThread之前可以調用GetProcAddress,所以它不太可能在同一時間內重新生成DLL。

14

它失敗的原因是因爲你的代碼是32位,你的目標進程是64位。

你擁有多少特權並不重要。 Windows不會讓這種情況發生。

我有同樣的問題。您可以生成一個32位的系統exe,然後將其注入或將您的代碼移植到64位(這意味着它不適用於32位系統)。

EDIT

很久以前,我發現代碼注入,並從任何處理器模式目標的一個很好的辦法。它涉及動態地將處理器模式切換到(任何)目標的模式。被稱爲「天堂之門」。要做到這一點,你必須使用內聯彙編。因此,基本上,您可以在32位exe文件中同時使用64位和32位代碼,檢測機器是否爲64位,然後跳轉到64位模式並運行64位代碼。然後,您可以通過導入來查找ntdll並加載64位kernel.dll和其他庫。下面是任何一個有興趣的人的例子的鏈接:http://bit.ly/19P0Lh3

+0

爲什麼要使用內聯彙編?你可以使用'Wow64DisableWow64FsRedirection' – ST3 2014-09-24 13:59:04

+0

Wow64DisableWow64FsRedirection會產生更多問題,尤其是在產卵過程時。畢竟,它只能從XP Pro獲得。 64位。低於此值的任何東西都不會起作用。這種方法已經有一段時間了。無論如何,Wow64DisableWow64FsRedirection不會讓你在32位內部執行64位代碼。這只是一個文件系統重定向。請在這裏閱讀評論:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365743(v=vs.85).aspx – TheRealChx101 2014-10-09 02:32:23

0

CreateRemoteThread函數在Win Vista/7中不起作用。你必須使用NTCreateThread函數,這是沒有記錄的。

+0

[This](http://msdn.microsoft.com/zh-cn/ -us/library/windows/desktop/ms682437%28v = vs.85%29.aspx)似乎表明它適用於WinXP及其後的所有版本。我個人也看到它在Win7上的工作。 – 2014-02-11 04:19:01

+1

CreateRemoteThread可能適用於Win VIsta/7,但我實際上的意思是在Vista和更高版本的操作系統中實現的UIPI,可以防止以較低的完整性級別寫入進程的較高完整性級別的進程,儘管可以實現IL。 – user101847 2014-02-25 06:03:53