![]() |
Detours : Routinen hooken
Hi,
ich möchte gerne eine Routine durch einen Detour hooken. Nur leider klappt es bei mir nicht. Ich möchte die ersten fünf Bytes der zu hookenden Routine mit einem jmp + address überschreieben, welche zu einem allozierten Speicher zeigt. In diesem allozierten Speicherbereich habe ich mir zehn Bytes reserviert: Die ersten fünf sind noch von der Routine, denn sie müssen ja auch ausgeführt werden. Danach kommt ein jmp zu einer neuen Adresse und zwar zu der neuen Routine. Um dann in der gehookten Routine auch die alte Routine ausführen zu können, rufe ich die originale einfach auf, aber überspringe die ersten fünf Bytes, damit ich nicht in einer Endlosschleife lande. So sieht die Theorie aus, aber in der Praxis funktioniert es nicht. :( Im folgenden Beispiel möchte ich die API-Prozedur Sleep() hooken.
Delphi-Quellcode:
So weit bin ich nun gekommen. Ich bekomme aber immer eine Zugriffsverletzung,
type T_Sleep = procedure(dwMilliseconds: Cardinal);stdcall;
var pSleep: T_Sleep; //Neue Sleep Prozedur procedure NewSleep(dwMilliseconds: Cardinal);stdcall; begin MessageBox(0, 'Test', 'Q', 0); pSleep(dwMilliseconds); end; function DetourHook(lpModule, lpRoutine: PChar; pTargetAddr, pNewAddr: Pointer):Pointer; var pBackupAddr: Pointer; dwFiveBytes: DWord; pResultAddr: Pointer; dwJmpCode: DWord; dwJmpGateway: DWord; hAlloc: Pointer; bVProtect: Boolean; dwvProtect: DWord; const DETOUR_JMP = $E9; DETOUR_SIZE = $05; begin result := nil; pBackupAddr := GetProcAddress(GetModuleHandle(lpModule), lpRoutine); //Adresse der Routine einholen, zur weiteren Verwendung pResultAddr := Pointer(Cardinal(pBackupAddr) + (DETOUR_SIZE)); //Originale Adresse + fünf Bytes speichern, damit er nicht mehr den Jump Code ausführt (wird dann der result Wert) CopyMemory(@dwFiveBytes, pTargetAddr, DETOUR_SIZE); //Die Bytes, welche gleich überschrieben werden, kopieren. dwJmpCode := dwFiveBytes + DWord(DETOUR_JMP) + DWord(pNewAddr^); //Die zu überschreibenden 5 Bytes + Jump opcode + die Adresse, auf die gesprungen werden soll hAlloc := VirtualAlloc(0, DETOUR_SIZE*2, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE); //Irgendwo im Bereich des Prozesses Speicher allozieren if hAlloc <> nil then begin bVProtect := VirtualProtect(hAlloc, DETOUR_SIZE*2, PAGE_READWRITE, dwvProtect); //Zugriffsrechte für Lesen und Schreiben einholen if bVProtect then begin CopyMemory(hAlloc, @dwJmpCode, DETOUR_SIZE*2); //Den Jump Code in den Bereich schreiben dwJmpGateway := DWord(DETOUR_JMP) + DWord(hAlloc); //Jump + Adresse des neuen allozierten Speicherbereichs if VirtualProtect(pTargetAddr, DETOUR_SIZE, PAGE_READWRITE, dwvProtect) then //Schreib - und Leserechte an der originalen Adresse einholen begin CopyMemory(pTargetAddr, @dwJmpGateway, DETOUR_SIZE); //Den Jump Code zum Gateway an die originale Adresse kopieren result := pResultAddr; end; end; end; end; procedure TForm1.FormCreate(Sender: TObject); var lol, retaddr: Pointer; begin lol := GetProcAddress(GetModuleHandle('kernel32.dll'), 'Sleep'); if lol <> nil then begin retaddr := DetourHook('kernel32.dll', 'Sleep', lol, @NewSleep); if retaddr <> nil then begin ShowMessage('Detoured'); pSleep := retaddr; //Backup Adresse zum Backup zuweisen //Sleep(2007); end else begin ShowMessage('Error'); end; end; end; wenn ich dann Sleep() aufrufen will. Deshalb nun meine Frage: Weiß jemand, wo denn mein Fehler liegt? Ich weiß einfach nicht, was ich falsch mache... Ich bedanke mich im Voraus für Hilfe. MfG: sk0r |
Re: Detours : Routinen hooken
Jo du darst keine halben Befehle ausführen. Wer sagt denn, dass bei 5 Bytes die genaue größe ist? Du musst dir einen Disassembler schreiben der den Code analysiert und dann die entsprechende richtige Anzahl kopiert.
|
Re: Detours : Routinen hooken
Naja, es ist schon die richtige Größe.
Wenn ich z.B. Sleep aus der kernel32.dll hooken möchte, dann bestehen die Bytes, die ich überschreibe aus dem stdcall. Dies rekonstruiere ich bei der neuen Sleep wieder. Falls es jemand anderen noch interessiert, hier der Code mit Beispiel.
Delphi-Quellcode:
Ja, ich weiß, ich brauch gar keinen Speicherbereich allozieren, es geht auchvar origSleep: Pointer; procedure NewSleep(dwMilliseconds: Cardinal);stdcall; begin MessageBox(0, 'Hallo aus der neuen Prozedur.', 'NewSleep', MB_ICONINFORMATION); asm jmp origSleep end; end; function DetourHook(lpModule, lpRoutine: PChar; pNewAddr: Pointer):Pointer; type TDetourRec = packed record bJmpOpcode: Byte; dwAddress: DWord; end; var lpDetourCode: TDetourRec; lpGatewayCode: TDetourRec; pTargetAddr: Pointer; pJmpGateway: Pointer; dwTargetProtect: DWord; const DETOUR_JMP = $E9; DETOUR_SIZE = $05; begin result := nil; pTargetAddr := GetProcAddress(GetModuleHandle(lpModule), lpRoutine); if pTargetAddr = nil then exit; pJmpGateway := VirtualAlloc(0, DETOUR_SIZE, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE); if pJmpGateway <> nil then begin lpDetourCode.bJmpOpcode := DETOUR_JMP; lpDetourCode.dwAddress := DWord(pNewAddr) - DWord(pJmpGateway) - DETOUR_SIZE; CopyMemory(pJmpGateway, @lpDetourCode, DETOUR_SIZE); lpGatewayCode.bJmpOpcode := DETOUR_JMP; lpGatewayCode.dwAddress := DWord(pJmpGateway) - DWord(pTargetAddr) - DETOUR_SIZE; if VirtualProtect(pTargetAddr, DETOUR_SIZE, PAGE_EXECUTE_READWRITE, dwTargetProtect) then begin CopyMemory(pTargetAddr, @lpGatewayCode, DETOUR_SIZE); result := Pointer(DWord(pTargetAddr) + DETOUR_SIZE); end; end; end; begin origSleep := DetourHook('kernel32.dll', 'Sleep', @NewSleep); if origSleep = nil then ExitProcess(0); Sleep(2007); MessageBox(0, 'I slept 2007 milliseconds', 'EntryPoint', MB_ICONINFORMATION); end. mit weniger Code, bzw. einfacher, aber das kann ja jeder selbst ändern. |
Re: Detours : Routinen hooken
Also bei mir fängt kernel32.Sleep so an:
Code:
Dein Detour überschreibt die ersten 5 Bytes - diese sind aber wichtig, da sie den Stackframe erzeugen.
8BFF mov edi, edi
55 push ebp 8BEC mov ebp, esp 6A00 push 0 Wie Brechi schon schrieb: du kannst nicht einfach Maschinencode überschreiben, ohne ihn analysiert zu haben. Dazu brauchst du einen Disassembler oder zumindest ein vereinfachte Abwandlung davon (z.B. ![]() Du musst also mehr oder minder wissen, was der Code macht, den du überschreibst - dann kannst du den überschriebenen Bereich sichern (und ggf. relozieren) und ab einer gewissen Stelle im Originalcode weitermachen. |
Re: Detours : Routinen hooken
Das denke ich ja auch, mir wurde aber gesagt, dass in diesem Fall, also obigen Beispiel, man
das nicht beachten muss, da die Bytes für stdcall benutzt werden. Man überschreibt also quasi das stdcall, welches aber in der neuen Prozedur rekonstruiert wird, somit also kein Verlust entsteht. So habe ich das verstanden, was mit von jemanden aus einem anderen Forum erklärt wurde. Ich zitiere ihn mal: Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz