2017-12-04 43 views
1

Ich setze einen globalen Haken für die Tastatur. Wenn ich anderen Anwendungen Tastatureingaben gebe, empfängt die Anwendung die Eingabe nicht und es hängt. Wenn die Konsole gestoppt wird, wird die Anwendung wiederhergestellt und die Tastatureingaben werden zusammen gebucht.Global installierter Tastaturhaken verhindert Tastatureingaben in andere Anwendungen

DLL Quelle:

#include <iostream> 
#include <Windows.h> 
#include <string> 
using namespace std; 
#define DLLEXPORT __declspec(dllexport) 

DLLEXPORT bool installhook(); 
DLLEXPORT void unhook(); 
DLLEXPORT string TestLoaded(); 
DLLEXPORT LRESULT CALLBACK KeyboardProc (int code, WPARAM wParam, LPARAM lParam); 

static HHOOK kb_hook; 
string test = "not loaded"; 
HINSTANCE hDLL; 

DLLEXPORT LRESULT CALLBACK KeyboardProc (int code, WPARAM wParam, LPARAM lParam) 
{ 
    if(code == HC_ACTION) // if there is an incoming action and a key was pressed 
    { 
     switch(wParam) 
     { 
     case VK_SPACE: 
      printf("Space was pressed\n"); //tried without this also 
      MessageBoxA(NULL, "Hi", "Space", MB_OK); 
      break; 
     } 
    } 
    return CallNextHookEx(NULL, code, wParam, lParam); 
} 

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
{ 
    test = "loaded"; 
    switch(ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
     hDLL = hModule; 
     break; 
    } 
    printf("test str = %s \n", test.c_str()); 
    return TRUE; 
} 

bool installhook() 
{ 
    kb_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hDLL, NULL); 
    if(!kb_hook) 
    { 
     return false; 
    } 
    return true; 
} 

void unhook() 
{ 
    if(kb_hook) 
    { 
     UnhookWindowsHookEx(kb_hook); 
    } 
} 

string TestLoaded() 
{ 
    return test; 
} 

Console applicatioon Quelle:

#include <iostream> 
#include <Windows.h> 
#include <string> 
#define DLLIMPORT __declspec(dllimport) 
using namespace std; 

DLLIMPORT void unhook(); 
DLLIMPORT bool installhook(); 
DLLIMPORT string TestLoaded(); 

int main() 
{ 
    cout << TestLoaded() <<endl; 
    installhook(); 
    for(int i = 1; i<=10 ; i++) 
    { 
     //Do some keyboard activities in this 10 secs 
     Sleep(1000); 
     cout << i<<endl; 
    } 

    unhook(); 
    cin.get(); 
    return 1; 
} 

Mein Verdacht war, dass, da die DLL wird in jedem Prozess in den Raum und Konsole eigene Adresse des Prozesses geladen werden wäre in anderen Anwendungen nicht vorhanden, wird ungültig und stürzt ab. Also habe ich die Konsolenausgaben entfernt und durch eine Messagebox ersetzt. Dann auch kein Unterschied.

Was könnte das Problem sein?

Update:

ich versuchte, einen lokalen Haken zu einem bestimmten Thread zu tun, bevor es global zu versuchen. Aber ich bekomme Parameter is incorrect Fehler 87 bei setwindowshookex. Im Folgenden sind die aktualisierten Code:

dll:

bool installhook(DWORD ThreadId) //exporting this function 
{ 
    kb_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, ThreadId); //tried with the dll module's handle also instead of NULL 
    if(!kb_hook) 
    { 
     printf("SetWindowsHookEx failed : %d\n", GetLastError()); 
     return false; 
    } 
    return true; 
} 

Konsolenanwendung Quelle:

DWORD myThread() 
{ 
    cout<< "Thread started\n"; 
    char str[250]; 
    cin>>str; 
    return 0; 
} 

int main() 
{ 
    cout << TestLoaded() <<endl; 
    DWORD myThreadID; 
    HANDLE myHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)myThread, NULL, 0, &myThreadID); 
    installhook(myThreadID); 
    for(int i = 0; i<100 ; i++) 
    { 
     Sleep(100); 
     if(i%10 == 0) 
     { 
      cout << i<<endl; 
     } 
    } 
    unhook(); 
} 
+0

Tun Sie nichts, dass die Callback-Blöcke oder Rekursion verursacht, wie MessageBox tut. Normalerweise können Sie die printf() - Ausgabe nicht sehen, es ist auch wichtig, die DLL mit/MT zu erstellen, damit sie eine eigene Kopie der CRT erhält und nicht versehentlich die CRT verwendet, die vom injizierten Programm verwendet wird. Sie können sicher in eine Protokolldatei schreiben. Testen Sie es zunächst, indem Sie die Injektion auf nur ein Programm begrenzen. Und bedenken Sie, dass das Eingeben von allen auf einem 64-Bit-Betriebssystem nicht möglich ist, wenn Sie nicht zwei DLLs und Injektoren erstellen und über ausreichende Rechte verfügen. –

+0

@HansPassant Ich habe alle Konsolenschreibvorgänge und Meldungsfelder aus der DLL entfernt und zu/MT geändert, andere Anwendungen können keine Tastatureingaben erhalten. Meine ist ein 64-Bit-Betriebssystem und die DLL ist 32 Bit. Ich werde versuchen, es speziell in einen einzelnen Thread eines 32-Bit-Prozesses zu injizieren. –

+0

@HansPassant Bitte überprüfen Sie das Update. Setwindowshookex schlug fehl, wenn versucht wird, einen einzelnen Thread zu haken. –

Antwort

0

Vielen Dank für alle Eingänge in Antworten und Kommentare erfassen.

Ich habe das eigentliche Problem herausgefunden. Der Fehler, den ich machte, war, Konsolenfenster ohne Nachrichtenwarteschlange zu verwenden.

Wenn ich richtig verstehe, werden Konsolenfenster von conhost.exe gehostet und sie haben keine Nachrichtenpumpen. Und der Haken funktioniert nur dann korrekt, wenn die Anwendung, die ihn installiert, eine Nachrichtenwarteschlange hat (sollte mehr darüber erfahren, warum es so ist).Siehe unten für die Möglichkeiten, können Sie es

funktioniert, wenn Sie keine Meldung an die Konsole Anwendung veröffentlichen werden:

das Ersetzen for-Schleife in der Konsolenanwendung Haupt mit diesem:

MSG msg; 
while(GetMessage(&msg, NULL, 0, 0) > 0) 
{ 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
} 

Falls Sie eine Nachricht an die Konsolenanwendung senden:

Erstellen Sie ein Fenster mit CreateWindowEx, gibt es eine Option für ein Nur-Nachrichten-Fenster auch. Sie müssten eine Klasse erstellen und einen CALLBACK-Prozess zuweisen. Lesen Sie here für weitere Details. Erstellen Sie das und übergeben Sie den Handle an die Hook-DLL und postmessage an den Handle. Verwenden Sie die Schleife zum Abrufen von Nachrichten und zum Versenden (siehe oben). Dann können alle Nachrichten, die Sie das Dummy-Fenster von Ihrer Hook-DLL veröffentlichen, mit dem CALLBACK-Fensterprozess verarbeitet werden.

Referenzen:

Why must SetWindowsHookEx be used with a windows message queue

CreateWindowEx MSDN

0

ich hatte das gleiche Problem, mit QT arbeiten, würde die GUI (wie geplant) blockiert werden, aber Wenn es wieder online ging, würde es meine Tastatur- und Mausklicks verarbeiten.

Ich bin mir nicht sicher, ob dies der effizienteste Weg ist, es zu handhaben, aber um das zu lösen, habe ich alle Tastatur- und Mausereignisse getrennt behandelt. Wenn eine Aufgabe ausgeführt wurde, ignorierte ich einfach das Schlüsselereignis.

Ansonsten denke ich, es steht nur Schlange und wartet auf seinen Zug!

2

Versuchen Sie, WH_KEYBOARD_LL zu verwenden. Sie können globale Hook auch ohne DLL-Hook-Funktion in Ihrem Prozess festlegen. Außerdem sollten Sie Weltraum-Action mit PKBDLLHOOKSTRUCT struct

LRESULT CALLBACK KeyboardProc (int code, WPARAM wParam, LPARAM lParam) 
{ 
    if (code == HC_ACTION) 
    { 
     switch (wParam) 
     { 
      case WM_KEYDOWN: 
      { 
       // Get hook struct 
       PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 
       if (p->vkCode == VK_SPACE) 
       { 
       MessageBoxA(NULL, "Hi", "Space", MB_OK); 
       } 
      } 
     break; 
     } 
    } 
    return CallNextHookEx(NULL, code, wParam, lParam); 
} 

.... 
// Somewhere in code 
kb_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, NULL); 
+0

Versucht, aber der Hook-Prozess trifft sich nicht. –

Verwandte Themen