Detours 64bit - Der Versuch eines Anfangs



  • Hallo,
    zunächst einmal sorry falls das das falsche Forum ist!

    Habe gerade angefangen eine Funktion zu detouren (ich bin dabei es zu versuchen...). Unter 32bit ist das kein Problem, aber 64bit macht meine Nerven kaputt... 😞
    Naja, als ich mich so durch Internet gewühlt habe, ist mir klar geworden, warum Microsoft für eine DetourLib ca. 10.000$ verlangt...

    Whatever, meine Theorie:
    1. Adresse der Ziel-Funktion holen
    2a. Am anfang der Funktion den Speicher durch einen absoluten Jump zur neuen Funktion ersetzen.
    2b. Wie 2a, nur das der Jump relativ ist.
    3. Fertig

    Die Sicherung des alten Speichers ist mir (jetzt noch) egal.
    Naja, das Problem beginnt beim Opcode für Jmp(Absolut), bzw. Jmp(Relativ) für x64. Im Internet lese ich dazu nämlich verschiedene...die Opcodes für 32bit kann ich ja nur verwenden, wenn ich mich im Bereich von 2GB bewege !?
    Auch den Abstand der Funktionen bekomme ich nicht

    int64 Abst = ((int64)Funk1 - (int64)Funk2); // falscher Abstand
    

    Kann das so überhaupt funktionieren oder bin ich da auf dem Holzweg 😕

    Danke schonmal !



  • Unter x64 git es auch nur 32Bit relativ Offsets:

    jmp OFFSET NewFnc - (OFFSET OrgFnc+5)
    
    -> 0xE9 ?? ?? ?? ??
    

    So könnte man es z.B. mit jWasm machen:

    fn GetModuleHandle,"user32.dll"
    fn GetProcAddress,rax,"MessageBoxA"
    mov rdi,rax
    
    invoke VirtualProtect,rdi,5,PAGE_EXECUTE_READWRITE,ADDR dwProtect
    
    mov BYTE ptr [rdi],0E9h
    mov eax,edi
    add eax,5
    mov edx,OFFSET NewFunction
    sub edx,eax
    
    mov SDWORD ptr [rdi+1],edx
    
    invoke MessageBoxA,0,0,0,0
    


  • Vielen dank erstmal !

    Ja gut, aber mit 32bit kann ich nicht über 2gb hinaus... müsste ich da eine far call machen?

    BTW: Weißt du warum Microsoft dafür 10k$ haben will? Würde mich echt interessieren, das muss ja ziemlich komplex sein...



  • __username schrieb:

    Vielen dank erstmal !Ja gut, aber mit 32bit kann ich nicht über 2gb hinaus... müsste ich da eine far call machen?

    Nein, man muss einen Sprung mit einer absoluten Addresse machen. z.B.:

    mov rax,imm64
    jmp rax
    

    __username schrieb:

    BTW: Weißt du warum Microsoft dafür 10k$ haben will? Würde mich echt interessieren, das muss ja ziemlich komplex sein...

    Ganz einfach: Microsoft stellt Software her und verkauft dies dann - sollte doch als Erklärung reichen?
    Trivial ist es die Sache nicht: Du brauchst eine disassembler damit du die überschriebenen Befehle rettet bzw in einer, wie es bei Detours heißt, Trampolinfunktion benutzen kannst.



  • mov rax,imm64
    jmp rax
    

    Kennst du das, wenn einem plötzlich das Brett vor dem Kopf wegfällt? 🙄

    Wegen den "verlorenen Befehlen":
    Kann ich nicht den überschriebenen Speicher (z.B. einfach mal 50Bytes), nachdem meine Funktion aufgerufen worden ist, zurückschreiben?
    Das ist nämlich der Punkt, wo ich gerade noch das nächste Brett vor dem Kopf habe...

    Noch ein kleines Problem:

    void func(void)
    {
    	int x; //Platz-
    	x = 1; //Füller
    	cout << "func" << endl;
    }
    void blub(void)
    {
    	int x; //Platz-
    	x = 1; //Füller
    	cout << "blub" << endl;
    }
    void detour(void)
    {
    	long long addr1 = 0;
    	long long addr2 = 0;
    	long long len = 0;
    
    	len = ((long long)blub - (long long)func - 5); //len = -10
        len = ((long long)func- (long long)blub - 5); //len = 0
    	int x; //Nur für Breakpoint
    }
    int main(int argc, char* argv[])
    {
    	func();
    	detour();
    	func();
    	system("PAUSE");
    	return 1;
    }
    

    Wo steckt der Fehler? Code wird nicht optimiert...
    BTW: Assembler kommt wenn "alles läuft" 😉

    EDIT:
    Adresse von blub:
    000000013F3D1019 E9 42 01 00 00 jmp blub (13F3D1160h)
    Adresse von func:
    000000013F3D101E E9 ED 00 00 00 jmp func (13F3D1110h)

    Daher also die seltsame Länge 🙄
    Weiter komme ich trotzdem nicht, sorry dass ich mich gerade so blöd anstelle



  • __username schrieb:

    Wegen den "verlorenen Befehlen": Kann ich nicht den überschriebenen Speicher (z.B. einfach mal 50Bytes), nachdem meine Funktion aufgerufen worden ist, zurückschreiben?

    Das könnte man machen, ist aber eine sehr schlechte Lösung.

    __username schrieb:

    Wo steckt der Fehler?

    Du musst beachten, dass ein Debug Build andern Code erzeugt als ein Release Build: Funktionen werden z.B. über eine jump table aufgerufen.



  • Und sieh an, es funktioniert!
    Du glaubst nicht wie sehr ich dir danke 👍 👍 👍

    Hab es jetzt folgendermaßen realisiert:

    BYTE b[] = {0x48, 0xB8, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xE0}; //mov RAX, adresse_von_blub | jmp RAX
    VirtualProtect
    MemCopy //adresse_von_blub nach b[2]
    VirtualProtect //zurück
    //läuft
    

    Ich muss nur noch den alten Speicher sichern/später wiederherstellen, aber das ist kein Problem mehr.

    Geht das so in Ordnung, oder gibts noch einen fatalen "Fehler"?


Anmelden zum Antworten