Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   SetWindowsHookEx innerhalb der DLL selbst (https://www.delphipraxis.net/173899-setwindowshookex-innerhalb-der-dll-selbst.html)

hedie 23. Mär 2013 10:22

SetWindowsHookEx innerhalb der DLL selbst
 
Hallo zusammen

Ich würde gerne prüfen ob irgendwo eine bestimmte Tastenkombination gedrückt worden ist.

Dazu habe ich versucht innerhalb einer DLL selbst, einen Hook zu setzen.

Hier mein Code:

Delphi-Quellcode:

var
MainHook : HHOOK;
//...

function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): Longint; stdcall;
begin
  MessageBox(HWND_DESKTOP,Pchar('Wir sind im Hook!'),'Message',MB_ICONINFORMATION);
end;

//....


MainHook := SetWindowsHookEx(WH_KEYBOARD, KeyboardHook, hinstance, 0);

  if MainHook = 0 then begin
    MessageBox(HWND_DESKTOP,Pchar('Fehlerhafter Hook!'),'Message',MB_ICONINFORMATION);
  end
  else begin
     MessageBox(HWND_DESKTOP,Pchar('Hook erfolgreich!'),'Message',MB_ICONINFORMATION);
  end;
Dieser Code wird automatisch beim Laden der DLL ausgeführt.

Ich bekomme auch die Meldung : Hook erfolgreich
aber leider bekomme ich nie die Meldung: Wir sind im Hook!

Es scheint so, als ob ich keinen echten Hook gesetzt hätte. Woran liegt das?

Danke schonmal

Sir Rufo 23. Mär 2013 10:30

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Geht es um einen KeyboardHook oder um einen Hook in einer DLL?

Für Mouse- und Keyboard-Hook wird keine DLL benötigt ;)

hedie 23. Mär 2013 10:36

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Hallo Rufo

Es geht im grunde um einen KeyboardHook

Aber ich möchte diesen KeyboradHook innerhalb einer DLL setzen.
Damit meine ich, Das erstellen des Hooks soll innerhalb der DLL geschehen
und die bearbeitende Hookfunktion soll sich ebenfalls in dieser DLL befinden...

Also mein Programm ist sozusagen die DLL...

Ich hoffe du verstehst was ich meine :)

Der schöne Günther 23. Mär 2013 10:49

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Ich kann wahrscheinlich nichts konstruktives beitragen, nur anmerken, dass ich die Routine nicht einfach so, sondern deren Adresse an
Delphi-Quellcode:
SetWindowsHookEx
übergeben habe...

Und es waren keine Keyboard-Events, sondern Lowlevel-Keyboard-Events (
Delphi-Quellcode:
WH_KEYBOARD_LL
statt
Delphi-Quellcode:
WH_KEYBOARD
)

hedie 23. Mär 2013 10:51

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1208488)
Ich kann wahrscheinlich nichts konstruktives beitragen, nur anmerken, dass ich die Routine nicht einfach so, sondern deren Adresse an
Delphi-Quellcode:
SetWindowsHookEx
übergeben habe...

Und es waren keine Keyboard-Events, sondern Lowlevel-Keyboard-Events (
Delphi-Quellcode:
WH_KEYBOARD_LL
statt
Delphi-Quellcode:
WH_KEYBOARD
)

Jede Antwort ist hilfreicht :)

Das wollte ich auch schon versuchen... Aber dann kommt leider das:

Code:
[DCC Fehler] Project.dpr(42): E2003 Undefinierter Bezeichner: 'WH_KEYBOARD_LL'

Der schöne Günther 23. Mär 2013 10:58

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Das hatte ich auf einem älteren Delphi (6?) auch, der kannte die Konstante einfach noch nicht.

Nimm stattdessen einfach die 13, wie du auf MSDN nachlesen kannst :)

hedie 23. Mär 2013 11:01

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1208493)
Das hatte ich auf einem älteren Delphi (6?) auch, der kannte die Konstante einfach noch nicht.

Nimm stattdessen einfach die 13, wie du auf MSDN nachlesen kannst :)

Hab ich nun versucht...

Leider bekomme ich nach einem Tastendruck in der Host-Anwendung immer noch keine Meldung meiner DLL

Delphi-Quellcode:

function KeyboardHook(Code: Integer; wParam : WPARAM; lParam : LPARAM): Longint; stdcall;
begin
  MessageBox(HWND_DESKTOP,Pchar('Wir sind im Hook'),'Message',MB_ICONINFORMATION);
end;

//...

MainHook := SetWindowsHookEx(13, KeyboardHook, hinstance, 0);

zeras 23. Mär 2013 11:06

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Zitat:

Zitat von Sir Rufo (Beitrag 1208479)
Geht es um einen KeyboardHook oder um einen Hook in einer DLL?

Für Mouse- und Keyboard-Hook wird keine DLL benötigt ;)

Hast du Beispiele für Mouse und Keyboard Hook ohne DLL? Ich habe zum Test eine DLL gefunden, wo aber keine Service mehr existiert. Wenn ich das direkt in Delphi machen könnte, wäre das super.

hedie 23. Mär 2013 11:13

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Ok nun habe ich news....

Der hook schein doch so halbwegs zu klappen...

Bei mir kommt einmalig die meldung: wir sind im hook.
Direkt nach dem einklinken mit

Delphi-Quellcode:
MainHook := SetWindowsHookEx(13, KeyboardHook, hinstance, 0);
Doch danach kann ich den Hook nicht mehr auslösen...
Die frage ist nur, weshalb.

Hier mein DLL-Code

Delphi-Quellcode:
begin

  MainHook := SetWindowsHookEx(13, KeyboardHook, hinstance, 0);

  if MainHook = 0 then begin
    MessageBox(HWND_DESKTOP,Pchar('Fehlerhafter Hook!'),'Message',MB_ICONINFORMATION);
  end
  else begin
     MessageBox(HWND_DESKTOP,Pchar('Hook erfolgreich!'),'Message',MB_ICONINFORMATION);
  end;

end.
Wird die DLL nach
Delphi-Quellcode:
end.
irgendwie beendet und kann deshalb keine messages vom system mehr empfangen?

hedie 23. Mär 2013 11:35

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Wenn ich die erste Meldung, dass der Hook erfolgreich erstellt wurde, nicht bestätige,

Dann funktionieren die Keyboardhooks.

Sobald ich jedoch ok klicke. Funktioniert es nicht.

Wird die DLL also irgendwie beendet?

Wenn ja, wie kann ich die DLL in einem art IDLE Modus belasse, so dass die Hooks weiterhin funktionieren?
Oder irgendwas wie StayAlive ?

zeras 23. Mär 2013 12:06

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Du solltest keine Messages aufrufen zum Test. Bei mir mache ich das in der Statusbar, dass ich einen Zähler hochzähle. Geht bei dir nicht so, weil du eine DLL hast. Versuche aber mal, den Status irgendwo anders anzuzeigen.

Aphton 23. Mär 2013 17:31

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Hihhi ^^

Ich hatte auch Probleme beim Hooken *sigh

Es gibt zwei Ursachen:
- du hast eine 32 Bit Dll auf ein 64 Bit System - nur 32 Bit Anwendungen werden gehookt
- deine Anwendung hookt nur Prozesse, die auch von Sicherheitsgrad gleichhoch oder geringer sind! Dh. du kannst Anwendungen, die im Admin-Kontext laufen, nicht aus einem niederwertigeren Kontext hooken! EDIT: Ich glaube sogar, man kann sich nur im gleichen Kontext bewegen.. kA, teste einfach!

Edit:
Zum Test - "Wir sind im Hook" soltle auf jeden Fall erscheinen, wenn deine eigene Anwendung (der Hooker) im Vordergrund ist / Fokus hat und du eine Taste drückst!

Edit 2:
Achja, bzgl MainHook := ... der Code ab dieser Stelle sollte in einer Funktion ausgelagert werden, die veröffentlicht und nur einmal per Hooker aufgerufen wird - da sonst rekursiv bei jedem Hook (und somit bei jedem Laden) global gehookt wird. Sofern Windows das nicht berücksichtigt, dürfte es zum Systemabsturz- oder Instabilität kommen!

hedie 25. Mär 2013 13:54

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Hallo

Danke für deine Antwort.

Dies könnten wirklich gründe dafür sein.


Um mal zu teste, ob die DLL korrekt geladen wurde, möchte ich aus meiner Anwendung heraus, eine DLL Funktion aufrufen.

Folgendes Szenario:

Meine App_A injiziert eine DLL mit exportierten Funktionen in eine zweite App_B von mir.
Nun möchte ich, nachdem die DLL in App_B geladen wurde von App_A heraus eine Funktion der DLL aufrufen, welch in App_B ist.
Doch die frage, wie geht sowas?

Ist dies einfacher über Messages zu lösen?

hedie 25. Mär 2013 14:31

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Habe eine Idee wie dies funktionieren könnte...

1: Dll in externe App injizieren und den Speicheraddressen beginn merken (dllAddressExtern)
2: Nun die DLL in den eigenen Prozess laden und ebenfalls die Startaddresse speichern (dllAddressIntern)
3: Nun mit GetProcAddress die Addresse der Funktion innerhalb der in den eigenen Prozess geladenen DLL finden und speichern.
4: Die Adresse von GetProcAddress abzüglich die Startaddresse ergibt unseren Offset.
5: Diesen Offset zu dllAddressExtern addieren und schon haben wir die Addresse der Funktion in der Zielapp.

Ich habe nun versucht einer internen Funktion den Pointer von eben dieser Adresse zu geben und aufzurufen.
Aber im nachhinein ist mir aufgefallen, das dies ja nur für den eigenen Speicherbereich klappt.

Leider weiss ich also nicht wie ich nun die Externe funktion aufrufen kann...

Habe nun folgenden Code zusammen:


Delphi-Quellcode:
TestMyApp := GetProcAddress(th,pchar('TestMyApp'));
  writeln;
  write('Dll Adresse extern: ');
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
  write(integer(pdllname));
  dllAddrExtern := integer(pdllname);
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
  writeln;

  dllAddressIntern := LoadLibrary(pchar(ExtractFilePath(paramstr(0)) + 'InjectedDll.dll'));   //Interne DLL Adresse holen
  dllOffset := integer(GetProcAddress(dllAddressIntern,'TestMyApp')) - dllAddressIntern;

  write('Dll Adresse intern: ');
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
  write(inttostr(dllAddressIntern));
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
  writeln;

  write('Dll Adresse Offset: ');
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
  write(inttostr(dllOffset));
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
  writeln;

  TestMyApp := Pointer(dllAddrExtern + dllOffset);

  write('Dll Funktions Addresse: ');
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
  write(inttostr(dllAddrExtern + dllOffset));
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
  writeln;
  writeln('Versuche nun die Funktion auszuführen!');
  readln(myInput);
  readln(myInput);
  TestMyApp;

Aphton 25. Mär 2013 20:38

AW: SetWindowsHookEx innerhalb der DLL selbst
 
Deine Methode mag zu 95% aller Fälle klappen aber leider nicht immer! Der ImageBase Wert einer PE Datei (exe, dll) ist nur ein Richtwert - also nichts absolutes.
Stell dir mal vor, das wäre nicht so - was passiert dann, wenn zwei Dlls als ImageBase $200000 (den gleichen Wert) hätten? Dann würden sie sich im Speicher überschreiben.
Der PE Loader von Windows determiniert zu Beginn, ob es an die "gewünschte" Stelle geladen werden kann, sonst berechnet er eben eine andere Adresse.

Somit kannste es so vergessen.

Es geht jedoch anders. In der Classes Unit gibts die Funktion "AllocateHWnd()". Damit kannst du ganz einfach (unsichtbare) Dummy-Fenster erstellen, die du hauptsächlich für den Nachrichtenaustausch (Windows Messages) brauchen wirst.
Hast du das mal hingekriegt, kannst du nun von der Anwendung A ein Message-Broadcast abschicken (HWND_BROADCAST als Fenster-Handle) und das Dummy-Fenster in der Dll, das ja Nachrichten nun empfangen kann (dafür benötigst du evt {sofern der Hauptthread dies nicht tut} einen Thread, der dies bewerkstelligt [also ein GetMessage()->TranslateMessage()/DispatchMessage()], kann darauf reagieren und bestimmte Dinge, die du definierst/programmierst, durchführen.

Btw. Sorry für Klammerception!

Edit: Achja, aus deinem Code kann ich noch ein Blödsinn erkennen -> du versucht, Code in fremden Prozessen auszuführen. So geht das leider nicht. Der Prozessspeicher ist getrennt. Du hast zwar Zugriff auf dieselbe Adresse, jedoch befindet sich dort nicht die Funktion des anderen Prozessees. Das ganze klappt durch Paging usw.
Benütz da lieber die WinApi -> "CreateRemoteThread()" die kann in fremden Prozessen an beliebiger Stelle einen Thread starten!


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz