[C/C++] Process Injection

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von MasterJulian, 16. Januar 2012 .

Schlagworte:
  1. 16. Januar 2012
    Process Injection

    Ich habe mir letztens noch mal den Beitrag zum Staatstrojaner vom 28C3 angeschaut. Dort wurde gesagt, dass dieser die Verbindung über Injektion des explorers leitet um so durch die Firewall zu kommen. Ich wollte mir mal ansehen, wie sowas von statten geht und habe folgenden Code gefunden: http://www.progamercity.net/c-code/351-process-injection-relocation.html
    Jedoch bekomme ich das nicht ans laufen. Das einzige was passiert ist, dass der zu injezierende Prozess crashed. Egal ob Explorer, Opera, Notepad oder der Windows Rechner. /FIXED:NO ist als Linkeroption gesetzt. Jemand eine Idee woran das liegt oder gibt es irgendwo einen anderes (verständliches) Beispiel wie sowas umgesetzt wird.
     
  2. 16. Januar 2012
    AW: Process Injection

    Hast du die injector.exe als Admin ausgeführt?

    Habe auch früher Injetoren gebastelt, damals für Games ...^^

    Kann dir morgen früh mal meinen Code geben + ne Beep.dll für Notepad.

    Bei 500 Zeichen beept es dann.
     
  3. 16. Januar 2012
    AW: Process Injection

    Die privileges passen. Es geht mir auch nicht daraum eine DLL zu injection, sondern wie in dem Beispiel eine Routine aus dem eigenen Programm.
     
  4. 16. Januar 2012
    AW: Process Injection

    Der Code sieht sehr gut aus, das sollte so funktionieren. Wenn du das in VS 2010 kompilierst ohne CRT DLL Abhängigkeiten (Linker Optionen Multithreaded) sollte es funktionieren.

    32-bit exe kannst du nur in 32-bit Prozess injecten.
     
  5. 16. Januar 2012
    AW: Process Injection

    Danke für den Hinweis. Leider ändert auch die Einstellung Multithreded nichts an dem Problem. Die Architektur der Prozesse stimmt überein. Die Programme in die ich injezieren möchte schmieren einfach ab.
    Mein Code sieht wie folgt aus:
    Spoiler
    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <tlhelp32.h>
     
    #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (addValue) )
    
    BOOL Inject(DWORD dwPid, LPTHREAD_START_ROUTINE lpStartProc, LPVOID lpParam);
    DWORD WINAPI RemoteThread(LPVOID lpParam);
    BOOL PerformRebase(LPVOID lpAddress, DWORD dwNewBase);
    BOOL EnablePriv(LPCSTR lpszPriv);
    DWORD GetProcessIdByName(char* name);
    
    int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
     DWORD dwPid;
     char msg[13];
    
     EnablePriv(SE_DEBUG_NAME);
     //hWnd = FindWindow("Progman", NULL);
     //GetWindowThreadProcessId(hWnd, &dwPid);
     dwPid = GetProcessIdByName("notepad.exe");
     sprintf(msg, "ProcessID: %u", dwPid);
     MessageBox(0, msg, "", MB_OK);
     Inject(dwPid, (LPTHREAD_START_ROUTINE)RemoteThread, NULL);
     return 0;
    }
     
    DWORD WINAPI RemoteThread(LPVOID lpParam)
    {
     char filename[MAX_PATH], msg[MAX_PATH];
     GetModuleFileName(GetModuleHandle(NULL), filename, MAX_PATH);
     sprintf(msg, "I am now inside of the remote process: %sn", filename);
     MessageBox(0, msg, "", MB_OK);
     ExitThread(0);
     return 0;
    }
     
    BOOL Inject(DWORD dwPid, LPTHREAD_START_ROUTINE lpStartProc, LPVOID lpParam)
    {
     HMODULE hModule;
     LPVOID hNewModule;
     DWORD dwSize;
     HANDLE hProcess;
     
     PIMAGE_DOS_HEADER pDH;
     PIMAGE_NT_HEADERS pPE;
     
     if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) == NULL)
     return FALSE;
     
     hModule = GetModuleHandle(NULL);
     
     pDH = (PIMAGE_DOS_HEADER)hModule;
     pPE = (PIMAGE_NT_HEADERS) ((LPSTR)pDH + pDH->e_lfanew);
     
     dwSize = pPE->OptionalHeader.SizeOfImage;
     
     LPVOID lpNewAddr = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
     if (lpNewAddr == NULL)
     return FALSE;
     
     CopyMemory(lpNewAddr, hModule, dwSize);
     
     hNewModule = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     if (hNewModule == NULL)
     return FALSE;
     
     PerformRebase(lpNewAddr, (DWORD)hNewModule);
     
     if (WriteProcessMemory(hProcess, hNewModule, lpNewAddr, dwSize, NULL) == 0)
     return FALSE;
     
     DWORD dwThread = (DWORD)lpStartProc - (DWORD)hModule + (DWORD)hNewModule;
     
     if (CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)dwThread, lpParam, 0, NULL) == NULL)
     return FALSE;
     
     return TRUE;
    }
     
    BOOL PerformRebase(LPVOID lpAddress, DWORD dwNewBase)
    {
     PIMAGE_DOS_HEADER pDH = (PIMAGE_DOS_HEADER)lpAddress;
     
     if (pDH->e_magic != IMAGE_DOS_SIGNATURE)
     return FALSE;
     
     PIMAGE_NT_HEADERS pPE = (PIMAGE_NT_HEADERS) ((char *)pDH + pDH->e_lfanew);
     
     if (pPE->Signature != IMAGE_NT_SIGNATURE)
     return FALSE;
     
     DWORD dwDelta = dwNewBase - pPE->OptionalHeader.ImageBase;
     
     DWORD dwVa = pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
     DWORD dwCb = pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
     
     PIMAGE_BASE_RELOCATION pBR = MakePtr(PIMAGE_BASE_RELOCATION, lpAddress, dwVa);
     
     UINT c = 0;
     while (c < dwCb)
     {
     c += pBR->SizeOfBlock;
     int RelocCount = (pBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
     LPVOID lpvBase = MakePtr(LPVOID, lpAddress, pBR->VirtualAddress);
     WORD *areloc = MakePtr(LPWORD, pBR, sizeof(IMAGE_BASE_RELOCATION));
     
     for (int i = 0; i < RelocCount; i++)
     {
     int type = areloc[i] >> 12;
     if (type == 0)
     continue;
     if (type != 3)
     return FALSE;
     
     int ofs = areloc[i] & 0x0fff;
     
     DWORD *pReloc = MakePtr(DWORD *, lpvBase, ofs);
     if (*pReloc - pPE->OptionalHeader.ImageBase > pPE->OptionalHeader.SizeOfImage)
     return FALSE;
     
     *pReloc += dwDelta;
     }
     pBR = MakePtr(PIMAGE_BASE_RELOCATION, pBR, pBR->SizeOfBlock);
     }
     pPE->OptionalHeader.ImageBase = dwNewBase;
     
     return TRUE;
    }
    
    BOOL EnablePriv(LPCSTR lpszPriv) // by Napalm
    {
     HANDLE hToken;
     LUID luid;
     TOKEN_PRIVILEGES tkprivs;
     ZeroMemory(&tkprivs, sizeof(tkprivs));
     
     if(!OpenProcessToken(GetCurrentProcess(), (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY), &hToken))
     return FALSE;
     
     if(!LookupPrivilegeValue(NULL, lpszPriv, &luid)){
     CloseHandle(hToken); return FALSE;
     }
     
     tkprivs.PrivilegeCount = 1;
     tkprivs.Privileges[0].Luid = luid;
     tkprivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     
     BOOL bRet = AdjustTokenPrivileges(hToken, FALSE, &tkprivs, sizeof(tkprivs), NULL, NULL);
     CloseHandle(hToken);
     return bRet;
    }
    // Called as: EnablePriv(SE_DEBUG_NAME);
    
    
    DWORD GetProcessIdByName(char* name)
    {
     DWORD pid = NULL;
     PROCESSENTRY32 entry;
     entry.dwSize = sizeof(PROCESSENTRY32);
     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    
     if (Process32First(snapshot, &entry) == TRUE)
     {
     while (Process32Next(snapshot, &entry) == TRUE)
     {
     if (stricmp(entry.szExeFile, name) == 0)
     { 
     pid = entry.th32ProcessID;
     }
     }
     }
    
     CloseHandle(snapshot);
     return pid;
    }
    Die Befehele für Compiler und Linker (laut Projekteigenschaften):
    Spoiler
    Compiler:
    Linker:
     
  6. 16. Januar 2012
    AW: Process Injection

    Achso du kompilierst es als x64 Code. Das funktioniert nicht, der Quellcode ist nicht bereit für x64. Da musst du einige Änderungen vornehmen bezüglich den Pointern.
     
  7. 16. Januar 2012
    AW: Process Injection

    Ah ok. Ich habs mal mit 32Bit versucht (also injector und target). Bis auf dass sich jetzt mein Virenscanner beschwert gleiches Problem (bei deaktiviertem Scanner). Ich seh schon ist gar nicht so einfach.
     
  8. 16. Januar 2012
    AW: Process Injection

    Code:
    sprintf(msg, "I am now inside of the remote process: %sn", filename); //stack corruption
    Tja

    Deshalb ist VS so geil:
     
  9. 16. Januar 2012
    AW: Process Injection

    Tatsächlich. sprintf_s lässt mein Programm (bzw das zu injezierende) allerdings auch crashen. Mit strcpy und strcat dagegen gehts wunderbar. Übrigens funktioniert das ganze (zumindest mit so einer simplen injection) auch mit 64bit.
     
  10. 17. Januar 2012
    AW: Process Injection

    Ich glaub du hast es falsch verstanden. Die msg Variable ist zu klein für den String. Es kommt zu einem Buffer Overflow. Da msg eine lokale Variable ist wird sie auf dem Stack angelegt, deswegen kommt es zu einem kaputten Stack und der lässt dann eben das Programm so böse crashen.

    sprintf_s hat einen Buffer check integriert, deswegen wird damit nicht der Speicher kaputt gemacht.
     
  11. 17. Januar 2012
    AW: Process Injection

    Hmm ok aber wieso? Sowohl filename als auch msg werden mit der Größe MAX_PATH angelegt, welches laut VS mit 260 definiert ist. Der String "I am now inside of the remote process: C:\Winodws\EXPLORER.EXE" Hat jedoch nur 63 Zeichen (plus Endekennung).
    Code:
    strcpy(msg,"I am now inside of the remote process: ");
    GetModuleFileName(GetModuleHandle(NULL), filename, MAX_PATH);
    strcat(msg,filename);
    Funktioniert ja. Ich muss zugeben ich habe noch nicht mit sprintf_s gearbeitet, aber auch "sprintf_s(msg, MAX_PATH, "I am now inside of the remote process: %s", filename);" führt zum crash.

    PS: Welches Tool hast du zum debuggen verwendet? Wenn ich beim Crash den VS Debugger auswähle bekomme ich nur "Unbehandelte Ausnahme bei 0x00000000 in explorer.exe: 0xC0000005: Zugriffsverletzung bei Position 0x0000000000000000."
     
  12. 17. Januar 2012
    AW: Process Injection

    Ok sorry, du hast recht. Ich hatte einen sehr langen exe Pfad bei mir und da hab ich zu schnell geurteilt.

    Dann kann das Problem nur bei den Relocations liegen. Der MS CRT Code verursacht dann die Probleme.

    Glaub da gibt es nur 2 Möglichkeiten um das 100% kompatibel zu machen http://www.benshoof.org/blog/minicrt/ oder Verzicht auf die MS Funktionen.

    Das mit dem x64 funktioniert nur aus Glück. x64 arbeitet mit 8 Byte Pointer/Adressen und z.B. hier:
    PerformRebase(lpNewAddr, (DWORD)hNewModule);

    Typecastest du einen 8 Byte Pointer in einen 4 Byte Pointer. Dadurch wird er einfach abgeschnitten, weil es nur der obere Teil der Adresse ist der fehlt geht das oft gut.
     
  13. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.