#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. + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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: + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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: + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren
#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." + Multi-Zitat Zitieren
#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. + Multi-Zitat Zitieren