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