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. FertigDie 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 nichtint64 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 dankeHab 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"?