Einzelnen Beitrag anzeigen

STaRDoGGCHaMP

Registriert seit: 1. Okt 2007
34 Beiträge
 
#1

SendInput/NtUserSendInput "unhooken"

  Alt 9. Dez 2007, 01:27
Hallo,

Folgendes Problem:
Ich versuche mit Delphi einen hook in User- und Kernelmode zu entfernen. Für den kernel-hook habe ich nen kleinen device driver geschrieben und mittels SSDT Hooking ging das auch ganz easy^^. Mein Problem liegt eher beim Usermode-hook, hierbei handelt es sich um einen ziemlich simplen hook, der einfach die ersten x bytes von einer Funktion (in meinem Fall SendInput) überschreibt. Mit c++ habe ich das ganze schon ziemlich einfach wie folgt gelöst(das funktioniert so einwandfrei, ich denke, wer sich ein wenig mit dem thema auskennt versteht das auch mehr oder weniger auf den ersten blick):

Code:
void _declspec(naked) __stdcall SafeSendInput(UINT cInputs, LPINPUT pInputs, int cbSize){

   __asm
   {
      mov eax, 000011f6h
      mov edx, 7ffe0300h
      call dword ptr [edx]
      retn 00ch
   }
}
So, dann hab ich es in delphi versucht .. und da begann der Spaß dann erst richtig^^. Mein erster Versuch (von dem ich blauäugiger weise davon ausging, dass er auf anhieb funktionieren würde ):

Delphi-Quellcode:
procedure SafeSendInput(nInputs: UINT; pInput: TInput; cbSize: Integer);
begin
  asm
    mov eax, 000011f6h
    mov edx, 7ffe0300h
    call dword ptr [edx]
    ret 00ch
  end;
end;
Klappte nicht .. wie kriegt man in delphi so nen naked function call (_declspec(naked)) hin?


Danach war ich dann total verzweifelt und hab mir ne kleine Funktion geschrieben, die alle 15 Bytes von SendInput in meine SafeInput procedure schreibt. Desweiteren schreibt diese Funktion noch nen Jump von SafeSendInput an die erste Adresse nach der Sendinput funktion. Das sah dann ungefähr so aus:

Delphi-Quellcode:
procedure SafeSendInput(nInputs: UINT; pInputs: TInput; cbSize: Integer);
begin
  asm
    nop //20 nops = 20 Bytes (15 Byte für die Sendinput bytes + 5 bytes
    nop //für den Jump an die erste Adresse nach SendInput)
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
  end;
end;

procedure CopyFunction(dwSource, dwTarget: DWORD);
var i, value: Integer;
    read: DWORD;
begin
  for i := 1 to 15 do begin
    ReadProcessMemory(GetCurrentProcess(), pointer(dwSource), addr(value), 1, read);
    WriteProcessMemory(GetCurrentProcess(), pointer(dwTarget), addr(value), 1, read);
    Inc(dwSource);
    Inc(dwTarget);
  end;
  value := $E9;
  WriteProcessMemory(GetCurrentProcess(), pointer(dwTarget), addr(value), 1, read);
  dwTarget := dwTarget + 5;
  value := dwSource - dwTarget;
  dwTarget := dwTarget - 4;
  WriteProcessMemory(GetCurrentProcess(), pointer(dwTarget), addr(value), 4, read);
end;

procedure TForm1.Button3Click(Sender: TObject);
var SI_Addy: DWORD;
    dwThreadId: DWORD;
    mbi: MEMORY_BASIC_INFORMATION;
    dwOldProtect: DWORD;
begin
  SI_Addy := DWORD(GetProcAddress(LoadLibrary('user32.dll'), 'SendInput'));
  VirtualQuery(Pointer(SI_Addy),&mbi,sizeof(MEMORY_BASIC_INFORMATION));
  VirtualProtect(Pointer(mbi.BaseAddress), mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  CopyFunction(SI_Addy, DWORD(@SafeSendInput));
Nunja .. funktionierte halt auch nicht. Ich finde das nur sehr merkwürdig, denn alle oben erwähnten in Delphi geschriebenen Funktionen erzielen (laut debugger) exakt den selben effekt wie die methode in C++. Ich kann mir das echt nicht erklären, evtl. liegt es ja an dem naked function call(_declspec(naked)), auf jeden fall würde es mich nicht wundern, wenn es irgendwas grundlegendes ist, was ich hier vergessen habe (meine delphi-kentnisse sind himmelschreiend schlecht ..)

Ich bitte Rechtschreibfehler sowie mangelnde Erklärungen und unkommentierten Code zu entschuldigen, es ist schon sehr spät und ich bin sehr frustriet und hoffe, dass mir jemand sagen kann, was ich falsch mache
  Mit Zitat antworten Zitat