2009-09-28 3 views
14

Se lavoro in un'applicazione e premo il tasto dalla tastiera, come posso acquisire quella chiave (o stringa), incluso il nome dell'applicazione di origine, in C, sotto GNU/LINUX, in userland, senza X11 :)Catturare sequenze di tasti in GNU/Linux in C

Grazie.

+1

Si dovrebbe [1] stato si problema un po 'più chiaramente (si può accedere alla fonte della richiesta? Il guscio? Il sistema operativo? In entrambi i casi dove esattamente stai appeso) e [2] convincerci che faremmo qualcosa di buono per il mondo, piuttosto che aiutarti a scrivere un altro rootkit (vedi, la tua maniglia non ti sta facendo alcun favore a riguardo). – dmckee

+2

Quindi vuole scrivere il 52 ° keylogger per linux. Grande affare. La tua moralità non lo fermerà. Almeno non è finito al superutente chiedendo dove scaricarne uno. ;) –

+4

@dmckee un incarico di keylogger è un comune incarico C/Assembler al college. Potrebbe benissimo essere un ragazzino di sceneggiatura che cerca di far incazzare la gente, ma allora? Ha fatto una domanda e lui merita una risposta, indipendentemente dal suo intento. –

risposta

1

Una possibilità: trovare e dare un'occhiata all'origine per "sudosh", il "sudo shell" (o una delle sue sostituzioni poiché non è stato modificato in un istante, Google è tuo amico).

Pasticcia con pseudo-tty e tiene traccia di tutti gli input e output registrando anche le informazioni su file.

Se è abbastanza preciso per te è forse più discutibile; registrerebbe tutte le battute per tutte le applicazioni. Non sono nemmeno sicuro di come funzioni con X11, se funziona con X11.

2

È possibile leggere i dati da uno dei file in/dev/input. Quale dipende dal tuo sistema. Potrebbe essere/dev/input/event0 o/dev/input/per-path/platform-i8042-serio-0-event-kbd o qualcos'altro. Il formato è specificato nell'intestazione del kernel input.h. E '

struct input_event { 
     struct timeval time; 
     __u16 type; 
     __u16 code; 
     __s32 value; 
}; 

È possibile eseguire

od -tx2 FILENAME 

e digitare qualcosa per vedere cosa succede.

Come per scoprire quale applicazione ha ricevuto l'evento chiave, non sono sicuro. Potresti provare a verificare quale sta leggendo dal tty principale.

+0

come faccio a sapere quale file sta per la tastiera? –

20

Bene, senza X11 questo problema è molto più difficile.
Per la parte di tasti è possibile utilizzare un codice simile a questo, ma si deve passare come argomento il dispositivo che si sta leggendo (tastiera, di solito/dev/input/event0)

#include <linux/input.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <unistd.h> 

int main(int argc, char **argv) 
{ 
    int fd; 
    if(argc < 2) { 
     printf("usage: %s <device>\n", argv[0]); 
     return 1; 
    } 
    fd = open(argv[1], O_RDONLY); 
    struct input_event ev; 

    while (1) 
    { 
    read(fd, &ev, sizeof(struct input_event)); 

    if(ev.type == 1) 
     printf("key %i state %i\n", ev.code, ev.value); 

    } 
} 

credits non andare da me, questo codice è preso dal hack Ventriloctrl per ottenere le battiture. http://public.callutheran.edu/~abarker/ventriloctrl-0.4.tar.gz

Spero di essere di qualche aiuto.

+9

nota che un tale programma dovrebbe essere eseguito come root, poiché i file/dev/input/event * sono di proprietà e limitati a root. –

+0

come può gestire più combinazioni di tasti, es: ctrl + c ecc.? –

1

Per un buon esempio, dare un'occhiata al codice showkey.

In particolare, ecco il ciclo principale. Tutto ciò che fa è prendere il terminale, copiarlo, trasformare quello copiato in modalità raw, e fino a quando non viene data una sequenza di tasti 'quit' o 'interrupt', si limita a stampare quale chiave è stata data al terminale.

/* 
* showkey.c -- display cooked key sequences 
* 
* Invoke this (no arguments needed) to see keycap-to-keystrokes mappings. 
* 
* by Eric S. Raymond <[email protected]>, 1 Nov 88 
* - fix for little-endian machines (version 1.1), 21 Oct 1996. 
* - cleanup and modern packaging (version 1.2), 1 Aug 2002. 
* - changed to use termios (version 1.3), 26 Aug 2002. 
* See the RPM spec file changelog for more recent stuff. 
*/ 
#include <stdio.h> 
#include <termios.h> 
#include <signal.h> 
#include <string.h> 
#include <stdbool.h> 
static int signalled; 

// ... 

main() 
{ 
    struct termios cooked, raw; 
    unsigned char c; 
    unsigned int i, timeouts; 
    char intrchar[32], quitchar[32]; 

    for (i = SIGHUP; i <= SIGIO; i++) 
    (void) signal(c, catcher); 

    // Get the state of the tty 
    (void) tcgetattr(0, &cooked); 
    // Make a copy we can mess with 
    (void) memcpy(&raw, &cooked, sizeof(struct termios)); 
    // Turn off echoing, linebuffering, and special-character processing, 
    // but not the SIGINT or SIGQUIT keys. 
    raw.c_lflag &=~ (ICANON | ECHO); 
    // Ship the raw control blts 
    (void) tcsetattr(0, TCSANOW, &raw); 

    (void) printf("Type any key to see the sequence it sends.\n"); 
    visualize(raw.c_cc[VINTR], intrchar); 
    visualize(raw.c_cc[VQUIT], quitchar); 
    (void) printf("Terminate with your shell interrupt %s or quit %s character.\n", 
      intrchar, quitchar); 
    signalled = 0; 
    while (!signalled) 
    { 
    char cbuf[32]; 

    read(0, &c, 1); 
    visualize(c, cbuf); 
    (void)fputs(cbuf, stdout); 
    (void) fflush(stdout); 
    } 

    (void) printf("\nBye...\n"); 
    // Restore the cooked state 
    (void) tcsetattr(0, TCSANOW, &cooked); 
} 
+5

Penso che abbiano bisogno di più cast di tipo "void" ... –