Einzelnen Beitrag anzeigen

sk0r

Registriert seit: 1. Mai 2007
181 Beiträge
 
Delphi 7 Enterprise
 
#1

Detours : Routinen hooken

  Alt 30. Sep 2007, 17:12
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
  Mit Zitat antworten Zitat