Systemweit Tastaturanschläge auslesen



  • Da ich vor einigen Monaten zu Linux (Ubuntu) gewechselt bin, fehlt mir noch ein Programm, das automatisch meine Rechtschreibfehler beim Tippen korrigiert. Unter Windows geht das z.B. mit As-U-Type unter Linux fehlt mir leider so ein Programm.
    Ich habe jetzt in einem Blog E=mg² einen Keylogger gefunden, den ich gerne als Vorlage für mein Programm benutzen würde. Nur leider lässt sich das Script nicht kompilieren, kann mir jemand helfen und sagen was ich noch installieren muss, damit ich den Source kompiliert bekomme?

    Danke!
    Tsunami

    keylogger.cpp:9:35: Fehler: X11/extensions/record.h: No such file or directory
    keylogger.cpp:37: Fehler: ISO-C++ verbietet Deklaration von »XRecordRange« ohne Typ
    keylogger.cpp:37: Fehler: expected »;« before »*« token
    keylogger.cpp:38: Fehler: »XRecordClientSpec« bezeichnet keinen Typ
    keylogger.cpp:39: Fehler: »XRecordContext« bezeichnet keinen Typ
    keylogger.cpp:76: Fehler: »XRecordInterceptData« wurde nicht deklariert
    keylogger.cpp: In member function »void KeyLogger::setupRecordExtension()«:
    keylogger.cpp:46: Fehler: »XRecordQueryVersion« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:57: Fehler: »recRange« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:57: Fehler: »XRecordAllocRange« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:64: Fehler: »recClientSpec« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:64: Fehler: »XRecordAllClients« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:67: Fehler: »recContext« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:68: Fehler: »XRecordCreateContext« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp: In static member function »static void KeyLogger::eventCallback(char*, int*)«:
    keylogger.cpp:77: Fehler: Abfrage des Elementes »category« in »* hook«, das vom Nicht-Klassentyp »int« ist
    keylogger.cpp:77: Fehler: »XRecordFromServer« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:78: Fehler: »XRecordFreeData« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:82: Fehler: Abfrage des Elementes »data« in »* hook«, das vom Nicht-Klassentyp »int« ist
    keylogger.cpp:91: Fehler: »XRecordFreeData« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp: In member function »void KeyLogger::processData()«:
    keylogger.cpp:100: Fehler: »XRecordProcessReplies« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp: In member function »void KeyLogger::start()«:
    keylogger.cpp:123: Fehler: »recContext« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:123: Fehler: »XRecordEnableContextAsync« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp: In member function »void KeyLogger::stop()«:
    keylogger.cpp:130: Fehler: »recContext« wurde in diesem Gültigkeitsbereich nicht definiert
    keylogger.cpp:130: Fehler: »XRecordDisableContext« wurde in diesem Gültigkeitsbereich nicht definiert
    


  • installier mal das paket x11proto-record-dev



  • Vielen Dank, habe ich gemacht. Wenn ich jetzt den Source mit "g++ keylogger.cpp -L/usr/X11R6/lib -lXtst -lX11" kompilieren möchte kommt die Meldung

    /usr/bin/ld: cannot find -lXtst
    collect2: ld gab 1 als Ende-Status zurück
    

    Wenn ich den Schalter wegnehme kommen wieder längere Fehlermeldungen am Stück. Müsste ich noch was installieren?



  • libXtst oder libXtst-dev oder sowas in der Art sollte installiert sein, keine Ahnung, wie das Ding unter Ubuntu heißt.

    edit: Unter Debian heißt es libxtst-dev.



  • Wow, vielen Dank! Ich habe libxtst-dev installiert und jetzt kann ich es kompileren! 😃



  • Ich habe jetzt leider doch noch mal eine Frage:
    In dem oben genannten Code wird eine statische Funktion benutzt (eventCallback), wo die gedrückte Taste in eine Datei geschrieben wird. Ich habe jetzt Verschiedenes probiert und komme einfach nicht weiter eine Schnittstelle von dort zu meinem restlichen Programm zu entwickeln.
    In der Klasse KeyLogger habe ich eine neue öffentliche Variable angelegt namens static QString Test;
    In der Routine eventCallback möchte ich diese Variable mit der gedrückten Taste auffüllen und zwar mit Test = XKeysymToString(XKeycodeToKeysym(userData->ctrlDisplay, c, 0));
    Aber leider geht das nicht, ich bekomme folgenden Kompilierfehler zurück:

    build/qtfasttype.o: In function `KeyLogger::eventCallback(char*, XRecordInterceptData*)':
    qtfasttype.cpp:(.text._ZN9KeyLogger13eventCallbackEPcP20XRecordInterceptData[KeyLogger::eventCallback(char*, XRecordInterceptData*)]+0x92): undefined reference to `KeyLogger::Test'
    collect2: ld gab 1 als Ende-Status zurück
    make: *** [bin/QtFastType] Fehler 1
    

    Könnte mir ja vielleicht noch mal jemand helfen, wie ich diese Variable richtig speichere? Danke!



  • Tsunami schrieb:

    build/qtfasttype.o: In function `KeyLogger::eventCallback(char*, XRecordInterceptData*)':
    qtfasttype.cpp:(.text._ZN9KeyLogger13eventCallbackEPcP20XRecordInterceptData[KeyLogger::eventCallback(char*, XRecordInterceptData*)]+0x92): undefined reference to `KeyLogger::Test'
    collect2: ld gab 1 als Ende-Status zurück
    make: *** [bin/QtFastType] Fehler 1
    

    Könnte mir ja vielleicht noch mal jemand helfen, wie ich diese Variable richtig speichere? Danke!

    Ich denke mal, du hast die statische Variable nicht definiert, d.h. dir fehlt noch ein

    QString KeyLogger::Test;
    


  • Danke für deine Rückmeldung, aber ich komme da leider auch nicht mit weiter. 😞
    Deswegen hier der Sourcecode mit meinen beiden Veränderungen. Ich habe lediglich

    static QString Test; 
    Test = XKeysymToString(XKeycodeToKeysym(userData->ctrlDisplay, c, 0));
    

    hinzugefügt, lässt sich aber leider nicht kompilieren. Wenn ich die Änderungen wegmache, dann geht alles.

    class KeyLogger {
    	string m_displayName;
    	CallbackClosure userData;
    	std::pair<int,int> recVer;
    	XRecordRange *recRange;
    	XRecordClientSpec recClientSpec;
    	XRecordContext recContext;
    
    	void setupRecordExtension() {
    	    XSynchronize(userData.ctrlDisplay, true);
    
    	    // Record extension exists?
    	    if (!XRecordQueryVersion (userData.ctrlDisplay, &recVer.first, &recVer.second)) {
    			cout << "%sThere is no RECORD extension loaded to X server.\n"
    		    "You must add following line:\n"
    		    "   Load  \"record\"\n"
    		    "to /etc/X11/xorg.conf, in section `Module'.%s" << endl;
    		 	throw exception();
    	     }
    	    cout << "Record extension v" << recVer.first << "."	<< recVer.second << endl;
    
    	    recRange = XRecordAllocRange ();
    	    if (!recRange) throw exception(); // "Could not alloc record range object!\n";
    	    recRange->device_events.first = KeyPress;
    	    recRange->device_events.last = KeyPress;
    	    recClientSpec = XRecordAllClients;
    
    	    // Get context with our configuration
    	    recContext = XRecordCreateContext (userData.ctrlDisplay, 0, &recClientSpec, 1, &recRange, 1);
    	    if (!recContext) {
    			cout << "Could not create a record context!" << endl;
    			throw exception();
    	    }
    	}
    
    	// Called from Xserver when new event occurs.
    	static void eventCallback(XPointer priv, XRecordInterceptData *hook) {
    	    if (hook->category != XRecordFromServer) {
    			XRecordFreeData(hook);
    			return;
    	    }
    
    	    CallbackClosure *userData = (CallbackClosure *)priv;
    	    XRecordDatum *data = (XRecordDatum *) hook->data;
    
    	    // Es gab einen Tastaturanschlag
    	    if (data->event.u.u.type == KeyPress) {
    			int c = data->event.u.u.detail; // Das ist der Tastaturcode der gedrückten Taste 
    			FILE *output = fopen("/home/michael/keylogger.log", "a+");
    
    			Test = XKeysymToString(XKeycodeToKeysym(userData->ctrlDisplay, c, 0));
    
    			fprintf(output,"%s", XKeysymToString(XKeycodeToKeysym(userData->ctrlDisplay, c, 0)));
    			fclose(output);
    
    	    }
    	    XRecordFreeData(hook);
    	}
    
    public:
    	KeyLogger() {}
    	~KeyLogger() {stop();}
    	void processData() {XRecordProcessReplies (userData.dataDisplay);}
    	static QString Test;
    
    	bool connect(string displayName) {
    	    m_displayName = displayName;
    	    if (NULL == (userData.ctrlDisplay = XOpenDisplay(m_displayName.c_str())) ) return false;
    	    if (NULL == (userData.dataDisplay = XOpenDisplay(m_displayName.c_str())) ) { 
    			XCloseDisplay(userData.ctrlDisplay);
    			userData.ctrlDisplay = NULL;
    			return false;
    	    }
    	    // You may want to set custom X error handler here
    
    	    userData.initialObject = (void *)this;
    	    setupRecordExtension();
    	    return true;
    	}
    
    	void start() {if (!XRecordEnableContextAsync (userData.dataDisplay, recContext, eventCallback, (XPointer) &userData)) throw exception();}
    	void stop() {if(!XRecordDisableContext (userData.ctrlDisplay, recContext)) throw exception();}
    };
    


  • Tsunami schrieb:

    Danke für deine Rückmeldung, aber ich komme da leider auch nicht mit weiter. 😞
    Deswegen hier der Sourcecode mit meinen beiden Veränderungen. Ich habe lediglich

    static QString Test; 
    Test = XKeysymToString(XKeycodeToKeysym(userData->ctrlDisplay, c, 0));
    

    hinzugefügt, lässt sich aber leider nicht kompilieren. Wenn ich die Änderungen wegmache, dann geht alles.

    Ich finde in deinem Code auch nirgendwo die Zeile, die ich oben gepostet hatte ;). Füge die Zeile doch mal hinzu, und zwar außerhalb der Klasse, dann sollte auch die "undefined Reference" weg sein.



  • Vielen Dank für den Hinweis, habe es jetzt direkt unter der Klasse gesetzt. Allerdings lässt sich das leider auch nicht kompilieren. Ich bekomme jetzt folgende Fehlermeldung:

    Projekt aktualisieren (qmake qtfasttype.pro)...
    Projekt bereinigen (make clean)...
    rm -f build/moc_qtfasttype.cpp
    rm -f build/ui_Dialog.h
    rm -f build/qtfasttype.o build/main.o build/moc_qtfasttype.o
    rm -f *~ core *.core
    Erstellen (make)...
    /usr/bin/uic-qt4 ui/Dialog.ui -o build/ui_Dialog.h
    g++ -c -pipe -fpermissive -O2 -Wall -W -D_REENTRANT -DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Ibuild -Ibuild -o build/qtfasttype.o src/qtfasttype.cpp
    g++ -c -pipe -fpermissive -O2 -Wall -W -D_REENTRANT -DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Ibuild -Ibuild -o build/main.o src/main.cpp
    /usr/bin/moc-qt4 -DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Ibuild -Ibuild src/qtfasttype.h -o build/moc_qtfasttype.cpp
    g++ -c -pipe -fpermissive -O2 -Wall -W -D_REENTRANT -DQT_SHARED -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Ibuild -Ibuild -o build/moc_qtfasttype.o build/moc_qtfasttype.cpp
    g++ -Wl,--no-undefined -o bin/qtfasttype build/qtfasttype.o build/main.o build/moc_qtfasttype.o    -L/usr/lib -L/usr/X11R6/lib -lXtst -lX11 -lQtGui -lQtCore -lpthread
    build/main.o:(.bss+0x0): multiple definition of `KeyLogger::Test'
    build/qtfasttype.o:(.bss+0x0): first defined here
    build/moc_qtfasttype.o:(.bss+0x0): multiple definition of `KeyLogger::Test'
    build/qtfasttype.o:(.bss+0x0): first defined here
    collect2: ld gab 1 als Ende-Status zurück
    make: *** [bin/qtfasttype] Fehler 1
    


  • am besten sollte es sein, wenn du die definition von test in die cpp schreibst, also außerhalb der klasse und ab in die cpp syntax is der gleiche.
    dann wird die auch bloß 1x gelinkt



  • Klasse, das hat jetzt hingehauen 😃
    Meinen ganz herzlichen Dank nochmals an alle, die mir hier geholfen haben! 👍


Log in to reply