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:
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;
So weit bin ich nun gekommen. Ich bekomme aber immer eine Zugriffsverletzung,
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