|
You last visited: Today at 08:27
Advertisement
Hooking mit WinAPI über C#
Discussion on Hooking mit WinAPI über C# within the General Coding forum part of the Coders Den category.
03/29/2015, 21:07
|
#1
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Hooking mit WinAPI über C#
Ich hatte in einem meiner Spiele mal die Shoutbox hier in Verbindung mit der epvp Library über DirectX gezeichnet. Dafür habe ich mal mit C# gespielt und mittels der  eine Library (DLL) in den Prozess injizieren können.
Ich hatte testweise geplant, eine Art Eingabe zu implementieren die ermöglicht, direkt im Spiel einen Shout zu senden.
Soweit so gut aber irgendwie muss die Eingabe aus dem Spiel ja auch registriert werden, ne? Shift abzufragen ob der Eingabemodus aktiv ist, war kein Problem. GetAsyncKeyState hätte da schon ausgereicht aber ich möchte ja auch die Zeichen der gedrückten Tasten abfangen und mitzeichnen.
Erst hatte ich mit  einen Hook in die Hookchain mit dem Typ WH_KEYBOARD_LL eingereiht. Das war kein Problem, ich bekam die entsprechenden Nachrichten ( WM_KEYDOWN war relevant) über den Callback und habe tatsächlich auch den Key aus der Nachricht ziehen können, der Ingame gedrückt wurde. Einziger Haken: Enthalten ist der Virtual Key Code, der mir leider nicht viel bringt weil der VK und das eigentliche Zeichen das daraus resultiert 2 verschiedene Paar Schuhe sind.
Gut, erstmal gesucht wie man den VK denn umkonvertieren kann um das Zeichen herauszubekommen. Geht nicht wirklich, weil es keine Unterscheidung zwischen Großbuchstaben und Kleinbuchstaben gibt und Sonderzeichen wohl nicht richtig interpretiert werden (also Tastenkombinationen aus ALT usw.).
Also weiter gesucht und folgende Informationen gefunden:
Quote:
|
Originally Posted by MSDN
Key strokes are converted into characters by the TranslateMessage function, which we first saw in Module 1. This function examines key-down messages and translates them into characters. For each character that is produced, the TranslateMessage function puts a WM_CHAR or WM_SYSCHAR message on the message queue of the window. The wParam parameter of the message contains the UTF-16 character.
|
"Super", hatte ich mir gedacht. "Dann wechsel ich einfach den Typ von WH_KEYBOARD_LL auf WH_GETMESSAGE und erhalte mit der selben Callback Signatur einfach alle Nachrichten die so in die Schleife geworfen werden".
Schön wäre es gewesen aber:
Code:
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
// curModule.ModuleName: Diablo III.exe
_hHook = SetWindowsHookEx(WH_GETMESSAGE, proc, GetModuleHandle(curModule.ModuleName), 0);
}
_hHook ist nun plötzlich 0 (NULL), Aufruf zu GetLastError gibt 1428 (0x594) zurück:
Quote:
ERROR_HOOK_NEEDS_HMOD
1428 (0x594)
Cannot set nonlocal hook without a module handle.
|
Wieso? Ich habe doch hier explizit den Modulnamen angegeben und der ist auch richtig.
Wieder in MSDN nachgeschaut und folgende Informationen erhalten:
Quote:
|
Originally Posted by MSDN
WH_KEYBOARD_LL Global only
WH_GETMESSAGE Thread or global
|
Quote:
|
Originally Posted by MSDN
The global hooks are a shared resource, and installing one affects all applications in the same desktop as the calling thread. All global hook functions must be in libraries. Global hooks should be restricted to special-purpose applications or to use as a development aid during application debugging. Libraries that no longer need a hook should remove its hook procedure.
|
Hilft mir jetzt aber nicht weiter. Wieso konnte der Hook mit WH_KEYBOARD_LL platziert werden, mit WH_GETMESSAGE aber nicht?
______
Quote:
Global hooks are not supported in the .NET Framework
Except for the WH_KEYBOARD_LL low-level hook and the WH_MOUSE_LL low-level hook, you cannot implement global hooks in the Microsoft .NET Framework. To install a global hook, a hook must have a native DLL export to inject itself in another process that requires a valid, consistent function to call into. This behavior requires a DLL export. The .NET Framework does not support DLL exports. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically.
Low-level hook procedures are called on the thread that installed the hook. Low-level hooks do not require that the hook procedure be implemented in a DLL.
|
Dann fällt das weg. Gibt's noch andere Möglichkeiten für mein Vorhaben?
|
|
|
03/29/2015, 22:35
|
#2
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
|
|
|
03/30/2015, 08:05
|
#3
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Dr. Coxxy
|
Schon klar, nur besitze ich eben keine Möglichkeit die Nachrichten abzufangen weil ich nur einen WH_KEYBOARD_LL Hook setzen kann und der nur WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN und WM_SYSKEYUP Nachrichten erhält.
|
|
|
03/30/2015, 18:39
|
#4
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
edit: sollte mal genauer den firstpost angucken...
btw. - mit c# noch nie was in der richtung gemacht - aber versteh ich richtig, dass du eh schon mit ner dll im zielprozess rumgurkst? - falls ja, solltest du auch einfach z.b. GetMessage direkt hooken können.
edit2:
z.b. so:
|
|
|
03/30/2015, 20:17
|
#5
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Dr. Coxxy
btw. - mit c# noch nie was in der richtung gemacht - aber versteh ich richtig, dass du eh schon mit ner dll im zielprozess rumgurkst? - falls ja, solltest du auch einfach z.b. GetMessage direkt hooken können.
|
Ja, hatte ich als Reserve geplant aber irgendwie ruft der Zielprozess die Funktion nicht auf. Wollte dann mal weiter schauen ob PeekMessage verwendet wird, wurde aber eben auf eine andere Möglichkeit aufmerksam gemacht.
Und zwar ist es wohl doch sehr gut möglich, anhand eines VK und des Keyboard States das entsprechende Zeichen zu bekommen indem man einfach genau das selbe wie TranslateMessage tut: WM_KEYDOWN übersetzen.
Relevant dafür ist: - AttachThreadInput
- ToAscii
- MapVirtualKey
- GetKeyboardState
1. In der Hookprozedur mit AttachThreadInput an den UI Thread ranhängen damit man Zugriff auf die gedrückten Tasten bekommt. Zwingend notwendig weil die Hookprozedur nicht im selben Thread läuft
2. Keyboard State (ein Array welches den Status aller Tasten enthält) mittels GetKeyboardState holen
3. Anhand der MapVirtualKey Funktion den Scan Code des VK holen weil dieser von der ToAscii Funktion benötigt wird
4. ToAscii Funktion aufrufen und sowohl VK, Scan Code als auch den Keyboard State übergeben damit entsprechend der gedrückten Tasten das richtige ASCII Zeichen rum kommt.
Code ist derzeit richtig schlampig und ordentlich aber ist ja eh derzeit nur zum debuggen:
Code:
private IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
byte[] ks = new byte[256];
IntPtr currentHWnd = GetForegroundWindow();
uint currentProcessID;
uint currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out currentProcessID);
uint thisProgramThreadId = GetCurrentThreadId();
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true);
OnCharEntered("KS:" + GetKeyboardState(ks));
var vkey = (uint)Marshal.ReadInt32(lParam);
byte[] ch = new byte[256];
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false);
ToAscii(vkey, MapVirtualKey(vkey, MAPVK_VK_TO_VSC), ks, ch, 0);
OnCharEntered("nCode: " + nCode + " wParam: " + wParam + " lParam: " + lParam + " Map: " + System.Text.Encoding.Default.GetString(ch));
OnCharEntered("Shift:" + (ks[(int) VirtualKeyStates.VK_SHIFT] & 0x80));
Frag mich jetzt nicht wieso ich TranslateMessage nicht einfach gehooked habe. Das wäre viel zu einfach gewesen.
|
|
|
03/30/2015, 21:32
|
#6
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
funktioniert da das numpad, € und @ zeichen richtig?
ich hab schonmal was in der richtung gemacht, allerdings mit directinput und da mit paar zeichen probleme gehabt.
|
|
|
03/30/2015, 22:06
|
#7
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Dr. Coxxy
funktioniert da das numpad, € und @ zeichen richtig?
ich hab schonmal was in der richtung gemacht, allerdings mit directinput und da mit paar zeichen probleme gehabt.
|
Habe es eben mal getestet, Numpad funktioniert, @ auch. € wird leider als ? in der Konsole ausgegeben. Liegt womöglich daran, dass das Euro Zeichen nicht im ASCII Zeichensatz enthalten ist. Zumindest nicht in der Standardvariante. Laut  ist es das erste Zeichen im extended ASCII Zeichensatz (ISO 8859-1).
Man könnte ja mal weiter rumspielen und zusehen, dass man statt eines ASCII Wertes einfach mal den Unicode Wert herausbekommt. Da wird's sicher Möglichkeiten geben, ich schaue da vielleicht morgen mal.
Ansonsten bin ich mit der derzeitigen Lösung durchaus zufrieden.
|
|
|
04/05/2015, 21:38
|
#8
|
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
|
Wieso setzt du nicht einfach einen neuen WndProc und rufst dann daraus den originalen WndProc auf wenn du die Nachricht nicht behandelst. Das ist der Standardweg um Input abzufangen.
Eine neue WndProc setzt du mit SetWindowLongPtr und GWLP_WNDPROC.
Du bekommst dann alle Nachrichten, inklusive WM_CHAR etc.
|
|
|
04/05/2015, 22:41
|
#9
|
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
|
Quote:
Originally Posted by Master674b
Wieso setzt du nicht einfach einen neuen WndProc und rufst dann daraus den originalen WndProc auf wenn du die Nachricht nicht behandelst. Das ist der Standardweg um Input abzufangen.
Eine neue WndProc setzt du mit SetWindowLongPtr und GWLP_WNDPROC.
Du bekommst dann alle Nachrichten, inklusive WM_CHAR etc.
|
Ich hatte hier nicht mehr geschrieben, dass ich es tatsächlich so umgesetzt hatte weil die alte Lösung in einem anderen Thread lief und mit meinen bestehenden Hooks ein Problem hatte.
Hatte dann aber keine neue WndProc gesetzt sondern die bestehende des Hauptfensters einfach gehooked.
|
|
|
 |
Similar Threads
|
[Help] Winapi/C++
07/08/2011 - C/C++ - 2 Replies
Hallo leute also ich habe mir in letzter zeit oder schon etwas länger c++ Beigebracht. Ich weis nicht ob meine kenntnisse schon ausreichen aber naja ich hab mich mal an Winapi versucht und jetzt mein problem ... kann mir jemand vll erklären was n Handle ist und wenn nicht das gibt es dan vieleicht irgendwelche aufgaben womit ich mir meine c++ kenntnisse verbessern/festigen kann also ich hoffe ihr könnt mir helfen da ich echt ziehmlich interressiert in der Programmierung(Coding) bin. Ich würd...
|
WinApi Problem
02/17/2011 - General Coding - 12 Replies
Hi,
hab keine Ahnung wieso das hier nicht geht. Es lässt sich kompilieren aber es macht nichts, also es erscheint kein Fenster.
#define STRICT
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
const char szAppName = "Textausgabe im Anwendungsbereich";
|
WinAPI / AutoIT
02/09/2011 - Last Chaos - 2 Replies
Ich hab ne weile nicht mehr für lc programmiert .. und wollt mal wieder bisl an meinem bots rumspielen .. habe das letzte mal vor!! x trap programmiert ^^
Ich bevorzuge eigentlich AutoIT wegen der tollen pixelsearch und mousemove funktionen ;).
Meine Frage .. ist es gar nicht mehr möglich über AutoiT memorys auszulesen selbt mit WINAPI ( windows 7 64 bit ) ?
Xtrap meckert bei mir nicht aber er findet auch keinen Prozess ( ich geh davon aus das xtrap blockt ).
Habe ich da nen Fehler/etwas...
|
WinAPI use in C#
06/09/2008 - .NET Languages - 15 Replies
Hi,
in Anlehnung an die Topics hier habe ich mich dazu aufgerafft, nen Annotrainer zu schreiben (siehe Attachment).
In der Listview werden halt aktive Annoprozesse angezeigt, die man dann anwählen kann um dann mit dem Cheat button Geld zu cheaten. Jedes item in der Listview hat im item.Tag das jeweilige Prozessobject, somit auch die ID.
Allerdings komme ich mit den eigentlichen Funktionen OpenProcess, ReadProcessMemory und WirteProcessMemory in C# noch nicht klar. Zwar bekomme ich das...
|
WinAPI use in C#
05/19/2008 - .NET Languages - 0 Replies
Hi,
in Anlehnung an die Topics hier habe ich mich dazu aufgerafft, nen Annotrainer zu schreiben (siehe Attachment).
In der Listview werden halt aktive Annoprozesse angezeigt, die man dann anwählen kann um dann mit dem Cheat button Geld zu cheaten. Jedes item in der Listview hat im item.Tag das jeweilige Prozessobject, somit auch die ID.
Allerdings komme ich mit den eigentlichen Funktionen OpenProcess, ReadProcessMemory und WirteProcessMemory in C# noch nicht klar. Zwar bekomme ich das...
|
All times are GMT +1. The time now is 08:28.
|
|