2012-02-26 8 views
6

Sto provando a scrivere un programma che utilizza CreateRemoteThread per iniettare una dll.CreateRemoteThread return ERROR_ACCESS_DENIED - Windows 7 DLL Injection

Il problema è che CreateRemoteThread si rifiuta di funzionare. GetLastError() restituisce 5 che è ERROR_ACCESS_DENIED. Non riesco a capire perché!

Sto lavorando da questo video 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; 

Dopo una discreta quantità di googling, non riesco a trovare una ragione per cui questo non dovrebbe funzionare.

Does CreateRemoteThread non funziona con Windows 7? Se sì, ho fatto degli errori evidenti?

problemi
+1

Ci sono molti bug in questo codice. Il più rilevante chiama GetLastError anche se non si ottiene un ritorno FALSE dalla funzione api. –

+0

Penso che dovresti anche assicurarti di eseguire le tue cose come amministratore, e non come utente normale, dato che UAC probabilmente ha problemi con il processo di iniezione. – foxx1337

+1

Un problema relativo all'accesso è che non si dovrebbe chiamare 'OpenProcess' con' PROCESS_ALL_ACCESS'. Chiamalo con l'insieme minimo di diritti di accesso richiesti. Il motivo alla base di ciò è documentato qui: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx –

risposta

2

immediati che vedo sono che non si ottiene il token di accesso che dovrebbe essere fatto in modo da:

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); 

Non ho tempo per guardare attraverso tutto il codice in questo momento, ma qui è qualcosa Ho estratto uno dei miei progetti precedenti:

// 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; 
} 

Vedere se è utile. Tornerò a guardare più tardi.

0

ritengo CreateRemoteThread() metodo di iniezione DLL non può funzionare in finestre 7.

Il quarto parametro del CreateRemoteThread() è un indirizzo. Nel tuo caso è l'indirizzo LoadLibraryA. Tuttavia, in Windows 7, l'indirizzo di base di Kernel32.dll/LoadLibraryA varierà in diversi processi; Pertanto, CreateRemoteThread() non funzionerà poiché l'indirizzo non è quello che ci si aspetta. Questa è la mia opinione personale, spero che possa essere d'aiuto. :)

2

OK, il tuo codice è destinato a fallire in Windows 7 e Vista a causa di "Processi protetti", cioè processi che possono essere manipolati solo da altri processi protetti, come explorer.exe, ecc ... In Windows 7 x32 c'è un modo: dato che sei in grado di caricare driver non firmati, ... beh, hai finito (cerca Alex Ionescu in google). In Windows 7 x64, però, non è possibile (duh!)

"Il quarto parametro della CreateRemoteThread() è un indirizzo. Nel tuo caso è l'indirizzo LoadLibraryA. Tuttavia, in Windows 7, Kernel32 .dll/LoadLibraryUn indirizzo di base vari in diversi processi; "

Bene, non è vero in remoto, perché le DLL sono condivise con gli stessi indirizzi in ogni processo, nonostante ASLR. Le DLL possono essere ridefinite, tuttavia, ma è possibile chiamare GetProcAddress prima di chiamare CreateRemoteThread, quindi è molto improbabile che la DLL venga reimpostata nel frattempo.

14

Il motivo per cui non funziona è perché il codice è a 32 bit e il processo di destinazione è a 64 bit.

Non importa quanti privilegi possiedi. Windows non permetterà che ciò accada.

Ho avuto lo stesso problema. O si genera un sistema exe a 32 bit e si inietta o si porta il codice a 64 bit (il che significa che non funzionerà su sistemi a 32 bit).

EDIT

Molto tempo fa, ho trovato un bel modo di iniettare codice in e da qualsiasi processore modalità bersaglio. Coinvolge dinamicamente la modalità del processore a quella di (qualsiasi) la destinazione. Soprannominato "porta del paradiso". Per fare questo devi usare l'assemblaggio in linea. Quindi in pratica è possibile avere sia il codice a 64 bit che a 32 bit in un exe a 32 bit, rilevare se la macchina è a 64 bit, quindi passare alla modalità a 64 bit ed eseguire il codice a 64 bit. Dovresti quindi eseguire le importazioni per trovare ntdll e caricare kernel.dll a 64 bit e altre librerie. Ecco un link agli esempi per chiunque sia interessato: http://bit.ly/19P0Lh3

+0

Perché utilizzare il montaggio in linea ?? Puoi andare con 'Wow64DisableWow64FsRedirection' – ST3

+0

Wow64DisableWow64FsRedirection crea più problemi, specialmente quando i processi di spawning. Dopo tutto, è disponibile solo da XP Pro. 64 bit. Qualunque cosa sotto non funzionerà. Questo metodo è lì da un po 'di tempo. Wow64DisableWow64FsRedirection non ti consente di eseguire codice a 64 bit all'interno di un 32 bit. È solo un reindirizzamento del file system. Leggi i commenti qui: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365743(v=vs.85).aspx – TheRealChx101

0

La funzione CreateRemoteThread non funziona in Win Vista/7. Devi usare la funzione NTCreateThread, che non è documentata, per quello.

+0

[This] (http://msdn.microsoft.com/en -us/library/windows/desktop/ms682437% 28v = vs.85% 29.aspx) sembra indicare che funziona su tutto WinXP e versioni successive. Ho visto personalmente che funziona anche su Win7. –

+1

CreateRemoteThread potrebbe funzionare per Win VIsta/7, ma quello che volevo dire era UIPI, implementato in Vista e in seguito, impedisce ai processi a livelli di integrità inferiori di scrivere su processi a livello di integrità più elevato, sebbene sia possibile eludere l'IL. – user101847