Dll-Injektion & Explorer
-
Hi,
ich arbeite an einer DLL-Injektion die weitergegeben werden soll. Das klappt bisher auch problemlos, nur wenn der Explorer (also explorer.exe mit DLL-Injektion) ein Programm aufruft, dann stürzt dieses ab
Ich habe aber keine Ahnung was an dem Code falsch sein könnte

Ich wäre sehr dankbar, wenn das mal jemand durchschauen könnte.
Aber auch für Tipps diesbezüglich wäre ich euch dankbar
Lg,
Darkclass dHook { private: string mDll,mName; unsigned mOverridefunk; int check(HWND a,LPCTSTR b,LPCTSTR c,UINT d); unsigned msgbox_addr; void hook_function(unsigned source_function, unsigned new_adress, unsigned instead_call, DWORD process_id); unsigned Xnew_adress[10]; void unhook_function(unsigned source_function, unsigned new_adress, unsigned instead_call, DWORD process_id); unsigned sprungoffset(unsigned absprung, unsigned ziel); public: dHook (LPCSTR dll, LPCSTR name,unsigned overridefunk); void xhook(); void xunhook(); }; void dHook::hook_function(unsigned source_function, unsigned new_adress, unsigned instead_call, DWORD process_id) { unsigned char byte; //Für Opcodes DWORD rw = 0; HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id); unsigned temp_adress[10]; //Um Adressen zwischenzuspeichern temp_adress[0] = source_function; temp_adress[1] = new_adress; /* Liest x Bytes von source_function ein,überschreibt sie mit NOPs und sichert sie in new_adress */ for(int i = 0; i < 5; i++) { //Liest von der SourceFunktion ein Byte nach "byte" ReadProcessMemory(hproc, (LPCVOID)source_function, &byte, sizeof(byte), &rw); //Schreibt das Byte an die neue Adresse und inkrementiert sie WriteProcessMemory(hproc, (LPVOID)new_adress++, &byte, sizeof(byte), &rw); //Schreibt den NOP-Opcode in Byte byte = 0x90; //Schreibt das NOP an die Source-Funktion und inkrementiert die Adresse WriteProcessMemory(hproc, (LPVOID)source_function++, &byte, sizeof(byte), &rw); } /* Schreibt in die vorher geschaffenen NOPs einen JMP zu instead_call um alle aufrufe umzuleiten */ source_function = temp_adress[0]; //Stellt die Adresse von source_function wieder her byte = 0xE9; //schiebt den Opcode für einen JMP nach "byte" /* Schreibt an den Anfang der zu Hookenden Funktion den Jump zu unserer Funktion, das gleiche haben wir im ersten Beispiel schon gemacht ;) */ WriteProcessMemory(hproc, (LPVOID)source_function, &byte, sizeof(byte), &rw); temp_adress[3] = sprungoffset(source_function,instead_call); WriteProcessMemory(hproc, (LPVOID)++source_function, &temp_adress[3], sizeof(temp_adress[3]), &rw); CloseHandle(hproc); } void dHook::unhook_function(unsigned source_function, unsigned new_adress, unsigned instead_call, DWORD process_id) { unsigned char byte; //Für Opcodes DWORD rw = 0; HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id); unsigned temp_adress[10]; //Um Adressen zwischenzuspeichern temp_adress[0] = source_function; temp_adress[1] = new_adress; /* Liest x Bytes von source_function ein,überschreibt sie mit NOPs und sichert sie in new_adress */ for(int i = 0; i < 5; i++) { //Liest von der SourceFunktion ein Byte nach "byte" ReadProcessMemory(hproc, (LPCVOID)new_adress, &byte, sizeof(byte), &rw); new_adress++; WriteProcessMemory(hproc, (LPVOID)source_function, &byte, sizeof(byte), &rw); source_function++; } new_adress=temp_adress[1] ; source_function=temp_adress[0]; CloseHandle(hproc); } unsigned dHook::sprungoffset(unsigned absprung, unsigned ziel) { unsigned weg; absprung += 5; weg = ziel - absprung; return weg; } dHook::dHook (LPCSTR dll, LPCSTR name,unsigned overridefunk) { mOverridefunk=overridefunk; mDll=dll; mName=name; HINSTANCE hDLL = LoadLibrary(dll); msgbox_addr = (unsigned)GetProcAddress(hDLL, name); MEMORY_BASIC_INFORMATION mbi; DWORD dwOldProtect; VirtualQuery((void*)msgbox_addr,&mbi,sizeof(MEMORY_BASIC_INFORMATION)); VirtualProtect((PDWORD)mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); } void dHook::xhook() { hook_function((unsigned)msgbox_addr, (unsigned)&Xnew_adress, mOverridefunk, GetCurrentProcessId()); } void dHook::xunhook() { unhook_function((unsigned)msgbox_addr, (unsigned)&Xnew_adress, mOverridefunk, GetCurrentProcessId()); } typedef HINSTANCE (__stdcall *fpLoadLibrary)(char*); typedef LPVOID (__stdcall *fpGetProcAddress)(HINSTANCE, char*); typedef void (*fpFunktion)(void); struct INJECTSTRUCT { fpLoadLibrary LoadLibrary; fpGetProcAddress GetProcAddress; char path[255]; char func[255]; }; DWORD WINAPI threadstart(LPVOID addr) { HINSTANCE hDll; fpFunktion funktion; INJECTSTRUCT * is = (INJECTSTRUCT*)addr; hDll = is->LoadLibrary(is->path); funktion = (fpFunktion)is->GetProcAddress(hDll, is->func); funktion(); return 0; } void threadend() { } bool inject(DWORD dwProcessId) { bool bb=false; DWORD id1=getProcessID(L"csrss.exe"); DWORD id2=getProcessID(L"smss.exe"); DWORD id3=getProcessID(L"winlogon.exe"); DWORD id4=getProcessID(L"services.exe"); DWORD id5=getProcessID(L"verclsid.exe"); DWORD id6=getProcessID(L"Isass.exe"); if(dwProcessId==4 || dwProcessId==id1 || dwProcessId==id2 || dwProcessId==id3 ||dwProcessId==id4||dwProcessId==id5||dwProcessId==id6) { return bb; } EnableDebugPrivilege(); HANDLE hProc; LPVOID start, thread; DWORD funcsize, written; HINSTANCE hDll; INJECTSTRUCT is; DWORD id; hDll = LoadLibrary("KERNEL32"); is.LoadLibrary = (fpLoadLibrary)GetProcAddress(hDll, "LoadLibraryA"); is.GetProcAddress = (fpGetProcAddress)GetProcAddress(hDll, "GetProcAddress"); strcpy(is.path, "C:\\DLL.dll"); strcpy(is.func, "Funktion"); funcsize = (DWORD)&threadend-(DWORD)&threadstart; id=dwProcessId; hProc = OpenProcess(PROCESS_ALL_ACCESS, false, id); printf("Prozess Handle: %x\n", hProc); if(hProc) { start = VirtualAllocEx(hProc, 0, funcsize+sizeof(INJECTSTRUCT), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(start) { if(WriteProcessMemory(hProc, start, (LPVOID)&is, sizeof(INJECTSTRUCT), NULL)) { thread = (LPVOID)((DWORD)start+sizeof(INJECTSTRUCT)); if( WriteProcessMemory(hProc, thread, (LPVOID)&threadstart, funcsize, NULL)) { if(CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0)) { bb=true; } } } } CloseHandle(hProc); } return bb; }die Funktionen aus der DLL:
BOOL __stdcall CreateProcessW2( LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { hookCreateProcess->xunhook(); BOOL b=CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); ProcessPause(lpProcessInformation->dwProcessId); inject(lpProcessInformation->dwProcessId) ProcessUnPause(lpProcessInformation->dwProcessId); hookCreateProcess->xhook(); return b; } extern "C" void __declspec(dllexport) Funktion() { hookCreateProcess=new dHook("kernel32.dll","CreateProcessW",(unsigned)&CreateProcessW2); hookCreateProcess->xhook(); }
-
kA, ich kann dir nur zu MS Detours raten
-
DWORD WINAPI threadstart(LPVOID addr) { HINSTANCE hDll; fpFunktion funktion; INJECTSTRUCT * is = (INJECTSTRUCT*)addr; hDll = is->LoadLibrary(is->path); funktion = (fpFunktion)is->GetProcAddress(hDll, is->func); //Hier! funktion(); return 0; }Es scheint an dieser Zeile zu liegen, wenn sie von der (an den explorer angehängten) DLL ausgeführt wird.
Die Fehlermeldung im JIT-Debugger heißt immer "Memory at Adress 0000000 is not readable" oder so.
Zur Erklärung:
"addr" ist die adresse auf dem die übergeben struct liegt
"is->path" der pfad zur dll
"is->func" der funktionsname"is->LoadLibrary" und "is->GetProcAddress" die adressen der gleichnamigen funktionen aus der kernel32.dll. da diese für alle prozesse gleich sind, werden sie übergeben.
oder habe ich da was falsch gemacht?
-
Jo, du nutzt irgendwelche Frickeleien anstatt was fertiges, sicheres, einfaches.
-
Ja, weil ich halt die Funktionsweise verstehen will...

Und externe Bibliotheken versuche ich eigentlich auch immer zu vermeiden
-
Schlechte Angewohnheit :p
(Hab früher auch so gedacht)
-
Ich habe jetzt zwar eine andere Umsetzung, aber mich würde halt interessieren, warum dieser Fehler auftritt...
Wenn mein (Haupt-)Programm immer im Hintergrund läuft und auf Anfrage in die gerade gestarteten Prozesse injiziert klappt es ja. Nur wenn mein (Haupt-)Programm beendet wird, dann werden die Anfragen nicht mehr bearbeitet und alle gestarteten Prozesse werden eingefroren (da sie vom Hauptprogramm nicht mehr 'aufgetaut' werden)

-
DarkShadow44 schrieb:
Ja, weil ich halt die Funktionsweise verstehen will...

Und externe Bibliotheken versuche ich eigentlich auch immer zu vermeidenFalscher Ansatz!
1. Kann es sein, dass Du niemals auf eine richtig gute Lösung kommst.
2. Kann es sein, dass es Leute gibt die es besser machen, weil Siemehr davon verstehen.
3. Lernt man IMHO am meisten wenn man den Source Code anderer "guter" Entwickler liest.Bei Detours ist der Source-Code dabei. Wenn Du verstehen willst wie man es richtig macht lies diesen Source Code.
-
3. Lernt man IMHO am meisten wenn man den Source Code anderer "guter" Entwickler liest.
Bei Detours ist der Source-Code dabei. Wenn Du verstehen willst wie man es richtig macht lies diesen Source Code.
Schon, aber dabei gibt es halt gleich alles auf einmal. Ich meine, ein kleines Beispiel wäre ja einfach, aber das sind halt gleich 200KB Code auf einen Schlag.

Da tue ich mich dann schon etwas schwer das zu durchsteigen...'Mein' Beispiel ist ja auch aus einem Tutotial, es klappt ja auch. Nur explorer.exe macht Probleme.
Und da jeder Code wohl etwas anders funktioniert, würde mich halt interessieren, was genau bei dem von mir gepostetem Beispiel falsch ist.
Lg,
Dark
-
explorer.exe ruft (bzw. lässt aufrufen via shell32.dll) CreateProcessW mit dwCreationFlags u.a. mit CREATE_SUSPENDED auf.
Folglich ist in dem "neuen" Prozess noch nicht mal kernel32.dll geladen, sondern nur die exe und vielleicht noch ntdll.dll.
Also muß ja in "CreateProcessW2" alles, besonders "inject", nach Aufruf von CreateProcessW schief gehen.
-
3. Lernt man IMHO am meisten wenn man den Source Code anderer "guter" Entwickler liest.
LANGWEILLIG das kann ja jeder !
Selbst ist der gute Programmierer !

-
@HellShadow
Und wenn mein Programm einen Prozess startet klappt das ? Ich meine, ich rufe ja sofort die inject-Methode auf - es klappt wunderbar... oder zumindest stürzt das programm nicht ab und mein code wird ausgeführt
Jetzt bin ich schon ein bischen verwirrt...

-
In einem mit CREATE_SUSPENDED gestarteten Prozess funktionieren viele "bewährte" Sachen nicht, z.B. der ganze Toolhelpsnapshot-Kram.
Versuch einfach mal das Flag zu löschen:
BOOL __stdcall CreateProcessW2( ... { // CREATE_SUSPENDED 0x00000004 dwCreationFlags &= ~4; BOOL b=CreateProcessW( ... }
-
Kleiner Nachtrag: Deine inject-Methode setzt voraus, daß kernel32.dll bereits geladen ist (wg. LoadLibrary, GetProcAddress). Das ist aber in einem mit CREATE_SUSPENDED gestarteten Prozess (noch) nicht der Fall.
Irgendwo in den Untiefen der shell33.dll ruft explorer.exe auch ResumeThread auf.

-
Doch. ntdll.dll und kernel32.dll sind dann bereits geladen.