DLL Injection



  • nö weil ich den Code rauskopiert habe und der damals schon funktioniert hat also ist im Code kein Fehler:
    Injector:

    #include <windows.h>
    #include <cstdio>
    typedef HINSTANCE (*fpLoadLibrary)(char*);
    typedef LPVOID (*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()
    {
    }
    int main()
    {
       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;
    printf("ID: ");
    scanf("%d", &id);
       hProc = OpenProcess(PROCESS_ALL_ACCESS, false, id);
       printf("Prozess Handle:       %x\n", hProc);
    start = VirtualAllocEx(hProc, 0, funcsize+sizeof(INJECTSTRUCT), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    printf("Memory:               %x\n", start);
    WriteProcessMemory(hProc, start, (LPVOID)&is, sizeof(INJECTSTRUCT), NULL);
    thread = (LPVOID)((DWORD)start+sizeof(INJECTSTRUCT));
    WriteProcessMemory(hProc, thread, (LPVOID)threadstart, funcsize, NULL);
    CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)thread, start, 0, 0);
       CloseHandle(hProc);
    	return 0;
    }
    

    DLL

    #include <windows.h>
    
    extern "C" void __declspec(dllexport) Funktion()
    {
        Beep(1000, 1000);
    }
    
    BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
    {
       return TRUE;
    }
    

    natürlich ist die DLL in C\\ und beides ist mit Multi Byte Compiliert.
    Wäre super wenn wer weiß woran das liegen könnte.



  • Hi,

    wie wärs mit den Prozess Debuggen in den du die DLL läds!?

    Gruß Pingu



  • Markymark schrieb:

    audacia schrieb:

    Markymark schrieb:

    crashed der zielprozess. woran liegt das?

    Du hast einen Fehler im Code.

    **
    nö weil ich den Code rauskopiert habe** und der damals schon funktioniert hat

    Genial! It compiles! Now ship it! 👍

    Markymark schrieb:

    also ist im Code kein Fehler

    Aber in den Kompilereinstellungen. Niemals vergessen: 99,95 % aller WinAPI-Funktionen sind __stdcall's.



  • Hi,

    wie wärs mit den Prozess Debuggen in den du die DLL läds!?

    Gruß Pingu



  • was muss ich den umstellen? WINAPI == __stdcall



  • Markymark schrieb:

    ...
    funcsize = (DWORD)threadend-(DWORD)threadstart;
    ..
    

    Wollt nur noch schnell anmerken daste mit diesm Konstrukt ziemlich leicht auf die Schnauze fallen kannst.
    z.B. wenn ich mit Visual C++ 2008 im Debug Modus zB. folgendes übersetzte:

    BOOL __declspec(naked) SetCursorPosA(int x, int y)
    {
       __asm
       {
          mov  edi, edi
          push ebp
          mov  ebp, esp
          jmp [DLLFunc]
       }
    }
    void blub()
    {
    	printf("hallo");
    	return;
    }
    
    int main(int argc, TCHAR** argv)
    {
    
    	unsigned char test = -1;
    
    	printf("%c",test);
    	SetCursorPosA(10,10);
    	blub();
    
    	return 0;
    }
    

    entsteht folgendes:

    /*Main function*/
    00411AA2   |.  E8 34F7FFFF       CALL FindWind.004111DB
    00411AA7   |.  83C4 08           ADD ESP,8
    00411AAA   |.  E8 36F7FFFF       CALL FindWind.004111E5
    
    ....
    
    004111D6    . /E9 D5010000       JMP FindWind.SetCursorPosA
    004111DB    $ |E9 D0010000       JMP FindWind.SetCursorPosA
    004111E0    . |E9 2F020000       JMP FindWind.printf                                                       ;  JMP to MSVCR90D.printf
    004111E5    $ |E9 D6010000       JMP FindWind.blub
    

    Gruß Pingu



  • wenn man die funktion als static deklariert, funktioniert das
    (visual 2008 getestet)



  • Markymark schrieb:

    was muss ich den umstellen? WINAPI == __stdcall

    Falls das Fettgedruckte eine Kompilereinstellung ist, dann wäre sie genau die richtige.

    Prinzipiell mußt du nur dafür sorgen, daß der Kompiler folgende Deklarationen

    typedef HINSTANCE (*fpLoadLibrary)   (char*);
    typedef LPVOID    (*fpGetProcAddress)(HINSTANCE, char*);
    

    als __stdcall's betrachtet und entsprechenden Assemblercode generiert. Genaueres dazu hier.

    "Per Hand" geht das so:

    typedef HINSTANCE __stdcall (*fpLoadLibrary)   (char*);
    typedef LPVOID    __stdcall (*fpGetProcAddress)(HINSTANCE, char*);
    

    🙂



  • eher so

    typedef HINSTANCE (__stdcall *fpLoadLibrary)   (char*);
    typedef LPVOID    (__stdcall *fpGetProcAddress)(HINSTANCE, char*);
    


  • vielen Dank für die Hilfe besonders an helferlein.
    Mit deinem Code funktioniert es perfekt. Mich wundert es jedoch
    da ich es früher nie so gemacht habe und es geklappt hat aber wayne.
    Warum steht im Tutorial unten dass diese Methode bei nicht vielen Prozessen klappt und man darum noch das Fortgeschrittene Tut machen soll? Bei mir geht das überall



  • und warum läuft der Code nicht mit UNICODE?
    Ich habe alle char durch TCHAR ersetzt unt strcpy durch die TCHAR routine.
    Ich kann es zwar kompilieren aber der Zielprocess crashed mit unicode.



  • helferlein schrieb:

    eher so

    Hängt vom Kompiler ab. Meiner schluckt beides. "__stdcall" ist ja kein Schlüsselwort sondern nur eine Kompilererweiterung (oder auch -verwässerung). 🙂

    Markymark schrieb:

    Warum steht im Tutorial unten dass diese Methode bei nicht vielen Prozessen klappt ...

    Hab das Tutorial zwar nicht gelesen aber das liegt nicht an der Methode sondern an WinXP sein Rechtemanagement.
    Jemand der als "User" eingeloggt ist, hat z.B. nur Zugriff auf alle Prozesse, die er selbst gestartet hat usw.

    Markymark schrieb:

    und warum läuft der Code nicht mit UNICODE?

    Weil du die "A(nsi)"-Version von LoadLibrary benutzt. Probier das mal mit LoadLibraryW.



  • geht leider auch nicht aber dann muss ich wohl mit Ansi arbeiten.
    Warum bekomme ich bei der DLL einen Linker Error, dass sie nicht ansi zeichen benutzt oder so und deshalb möglicherweiße nur auf meinem PC verwendet werden kann?

    #include <windows.h>
    
    extern "C" void __declspec(dllexport) Funktion()
    {
        Beep(1000, 1000);
    }
    
    BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
    {
       return TRUE;
    }
    

    Habs mit Multi und Unicode probiert.
    Und noch was: wie bekomme ich die Rückgabewerte der Funktion aus der Dll, bzw wie kann ich ihr Parameter aus dem Main programm übergeben?



  • Markymark schrieb:

    geht leider auch nicht aber dann muss ich wohl mit Ansi arbeiten.

    alle chars umgestellt? auch das kopieren mit strcpy?

    prinzipiel sollte das auch mit unicode gehen.

    Markymark schrieb:

    Warum bekomme ich bei der DLL einen Linker Error, dass sie nicht ansi zeichen benutzt oder so und deshalb möglicherweiße nur auf meinem PC verwendet werden kann?

    welchen fehler? poste den bitte ich kann leider nicht so gut hellsehen 😃

    Markymark schrieb:

    Und noch was: wie bekomme ich die Rückgabewerte der Funktion aus der Dll, bzw wie kann ich ihr Parameter aus dem Main programm übergeben?

    du musst einen weiteren speicherbereich in dem zielprozess VirtualAllociren,
    die parameter reinschreiben und die addresse des bereiches an die funktion
    übergeben. allerdings kannst du nicht auf daten des eigenen prozesses über
    zeiger zuggreifen also alles was du brauchst kopieren.

    die addresse kannst du einfach als parameter übergeben, also der deklaration
    in der DLL und in der main einfach ein parameter, z.b. void *, hinzufügen.

    dieser wert wiederrum wird auch in der INJECTSTRUCT gespeichert.



  • Markymark schrieb:

    Und noch was: wie bekomme ich die Rückgabewerte [...]

    Ganz einfach - GetExitCodeThread.

    DWORD __stdcall RemoteThreadProc(MYDATA *data)
    {
    	return 12345; // oder ExitThread(12345);
    }
    
    void inject()
    {
    	HANDLE hThread = CreateRemoteThread();
    
    	DWORD dwExitCode;
    	GetExitCodeThread(hThread, &dwExitCode);
    	// dwExitCode = STILL_ACTIVE, also warte noch
    	WaitForSingleObject(hThread, INFINITE);
    	GetExitCodeThread(hThread, &dwExitCode);
    	// dwExitCode ist 12345
    }
    

    Du kannst auch eine variable in MYDATA setzen um thread status (und mehr) mitteilen:

    DWORD __stdcall RemoteThreadProc(MYDATA *data)
    {
    	data->return_value = 12345;
    	return 0;
    }
    
    void inject()
    {
    	MYDATA data;
    	void *pData = VirtualAllocEx(hProcess, 0, sizeof(MYDATA), MEM_COMMIT, PAGE_READ_WRITE);
    	WriteProcessMemory(hProcess, pData, &data, sizeof(data), &cch);
    
    	HANDLE hThread = CreateRemoteThread(..., pCode, pData, ...);
    	WaitForSingleObject(hThread, INFINITE);
    	ReadProcessMemory(hProcess, pData, &data, sizeof(data), &cch);
    	// data.return_value ist 12345
    }
    


  • ich glaube es war umsonst, kann man in DLLs keine Dialoge verwenden? Denn ich wollte mein ganzes Programm in diese DLL auslagern.

    #include <windows.h>
    #include "resource.h"
    
    BOOL CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
    
    extern "C" void __declspec(dllexport) Funktion()
    {
        DialogBox(GetModuleHandle(0), MAKEINTRESOURCE(IDD_DIALOG1), 0, MainDlg);
    	MessageBox(0, "lol", "lol", 0); // geht
    }
    
    BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
    {
       return TRUE;
    }
    
    BOOL CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch(message)
    	{
    	case WM_INITDIALOG:
    		Beep(2000, 4000);
    		 return TRUE;
    
    	case WM_COMMAND:
    		 switch(LOWORD(wParam))
    		 {
    	     case IDCANCEL:
      			  EndDialog(hDlg, 0);
    			  return TRUE;
    
    		 }
    	}
    
    	return FALSE;
    }
    

    leider wird kein Dialog erzeugt oO er ist auf sichtbar gestellt usw.
    aber warum sehe ich diesen nicht?



  • Leider GetModuleHandle(0) liefert EXE BASE und nicht DLL BASE. Du brauchst die hInst von DllMain in eine globale g_hinstance Variabe speichern, und dann...

    DialogBox(g_hinstance,
    

    Aber manchmal klappt das nicht, dann must du DialogBoxIndirect benutzen (mithilfe Find/Load/LockResource).



  • natüllich klappt das, wieso soll das nich klappen lolzen



  • dankeschön, dass klappt. Und noch was anderes:
    kann ich wirklich mein ganzes Programm mit vielen Dialogen funktionen Threads usw von der DLL in den Prozess laden oder gibt es da eine begrenzung?



  • Markymark schrieb:

    gibt es da eine begrenzung?

    quatsch wieso sollte es


Anmelden zum Antworten