CreateRemoteThread Technik schlägt im Debug Mode fehl



  • Hallo

    Ich habe meinen Code bisher immer im Release Mode verwendet, aber im Debug Mode klappt er leider nicht. Ich hätte aber gerne, dass es mit beiden läuft. Also erst ist VirtualAllocEx fehlgeschlagen, mit GetLastError = Invalid Parameter.
    Hat wohl was mit der funcsize zu tun. Dann habe ich threadstart und end static gemacht, nun läuft es zwar, aber die Zielapplikation crashed wenn CreateRemoteThread ausgeführt wird. Wie gesagt, im Release Mode läuft alles einwandfrei, sogar ohne static vor den Funktionen. Ich weiß langsam nicht mehr weiter, und sowas kann man ja auch extrem schlecht debuggen 😞
    Vielleicht hat jemand eine Idee woran das liegen könnte oder wie ich das behebe?

    #ifdef UNICODE
    #define LoadLibraryGeneric  "LoadLibraryW"
    #else
    #define LoadLibraryGeneric  "LoadLibraryA"
    #endif
    
    typedef HINSTANCE (__stdcall *fpLoadLibrary)(TCHAR*);
    typedef void* (__stdcall *fpGetProcAddress)(HMODULE, LPCSTR);  
    typedef void (*fpFunktion)(void);
    
    struct INJECTSTRUCT
    {
    	fpLoadLibrary LoadLibrary;
    	fpGetProcAddress GetProcAddress;
    	TCHAR path[255];
    	char func[255];
    };
    
    static 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;
    }
    
    static void threadend()
    {
    }
    
    bool EnableDebugPrivilege()
    {
    	HANDLE hThis = GetCurrentProcess();
    	HANDLE hToken;
    	OpenProcessToken(hThis, TOKEN_ADJUST_PRIVILEGES, &hToken);
    	LUID luid;
    	LookupPrivilegeValue(0, TEXT("seDebugPrivilege"), &luid);
    	TOKEN_PRIVILEGES priv;
    	priv.PrivilegeCount = 1;
    	priv.Privileges[0].Luid = luid;
    	priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    	AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0);
    	CloseHandle(hToken);
    	CloseHandle(hThis);
    	return true;
    }
    
    HANDLE InjectDll(unsigned ProcessId, string DllFile, std::string ExportedFunctionName, stringstream& ErrorStream)
    {
    
    	INJECTSTRUCT is;
    	_tcscpy_s(is.path, DllFile.c_str());
    	strcpy_s(is.func, ExportedFunctionName.c_str());
    	unsigned funcsize = (unsigned)threadend - (unsigned)threadstart;
    
    	EnableDebugPrivilege();
    
    	HINSTANCE hDll = LoadLibrary(TEXT("KERNEL32"));
    	if(hDll == NULL)
    	{
    		ErrorStream << TEXT("LoadLibrary failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	is.LoadLibrary = (fpLoadLibrary)GetProcAddress(hDll, LoadLibraryGeneric);
    	is.GetProcAddress = (fpGetProcAddress)GetProcAddress(hDll, "GetProcAddress");
    	if(is.LoadLibrary == NULL || is.GetProcAddress == NULL)
    	{
    		ErrorStream << TEXT("GetProcAddress failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessId);
    	if(hProc == NULL)
    	{
    		ErrorStream << TEXT("OpenProcess failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	void* start = VirtualAllocEx(hProc, 0, funcsize + sizeof(INJECTSTRUCT), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	if(start == NULL)
    	{
    		ErrorStream << TEXT("VirtualAllocEx failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	if(WriteProcessMemory(hProc, start, (LPVOID)&is, sizeof(INJECTSTRUCT), NULL) == 0)
    	{
    		ErrorStream << TEXT("WriteProcessMemory failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	void* thread = (void*)((unsigned)start + sizeof(INJECTSTRUCT));
    
    	if(WriteProcessMemory(hProc, thread, (LPVOID)threadstart, funcsize, NULL) == 0)
    	{
    		ErrorStream << TEXT("WriteProcessMemory failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	HANDLE threadID = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0);
    	if(threadID == NULL)
    	{
    		ErrorStream << TEXT("CreateRemoteThread failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	if(CloseHandle(hProc) == 0)
    	{
    		ErrorStream << TEXT("CloseHandle failed! Error Code: ") << GetLastError();
    		return 0;
    	}
    
    	return threadID;
    }
    




  • darauf habe ich meinen Code ja aufgebaut 😞



  • Gib mal "funcsize" zweimal aus: einmal im DebugMode und einmal im ReleaseMode.

    Falls DebugMode-funcsize größer ist als ReleaseMode-funcsize, dann wird im DebugMode zusätzlicher (Debugger)Code in die "threadstart" mit eingebaut, welcher dann im Zielprozess fatal sein kann.

    Woraus zu folgern wäre, daß dein Programm auch nur im ReleaseMode funktionieren wird.



  • 🙂 vielen Dank für die Antwort.
    Also im Debug mode hat die funcsize 0xB0 und im Release 0x30. Meinst du das könnte der Fehler sein? Kann ich das Problem lösen, ohne Compiler und Linkereinstellungen, sondern mit Code Änderung?



  • Das wird der "Fehler" sein:

    static DWORD WINAPI threadstart(LPVOID addr)
    {
    // |------------------------------------------|
    //  Der DebugCode sitzt u.a. genau hier.
    //  Mit Codeänderungen wird sich nichts erreichen lassen.
    // |------------------------------------------|
        HINSTANCE hDll;
        fpFunktion funktion;
        INJECTSTRUCT *is = (INJECTSTRUCT*)addr;      
        hDll = is->LoadLibrary(is->path);
    (...)
    


  • kann ich vielleicht irgendwie abfragen, ob es im Debug Mode ist und wenn ja, dass der dann nicht optimieren soll? Das Abfragen des Debug Modes wäre ja klein Problem, aber was müsste ich umstellen, dass er das nicht mehr tut?



  • Überleg noch mal, ob du den Debug-Build so dringend brauchst.
    Mir hat das für Code für fremde Prozesse noch nie was gebracht, da kann man eh nicht richtig debuggen.
    Schau einfach, dass du den Code gewissenhaft schreibst, überdenke alles genau und noch genauer.



  • kann ich die Größe nicht einfach auf eine fixe Größe setzen?



  • Ja, geht. Aber das Problem mit dem extra Debuggercode in der threadstart bleibt. Der extra Debuggercode im DebugMode hat leider nichts mit "Optimierungen" zutun und kann nur durch Kompilieren im ReleaseMode "beseitigt" werden.



  • debugg0r vielen Dank für deine Hilfe. Also naja wenn sich da nix machen lässt, muss ich wohl oder übel im Release Mode arbeiten.


Anmelden zum Antworten