/* * N0Sp00f.c Semplice modulo per evitare che qualche lama * decida di usare il nostro sistema come hop di * lancio per pacchetti IP spoofati. Intercetta * la chiamata di sistema socketcall() per il * parametro IP_HDRINCL passato a setsockopt(). * Purtroppo Linux ha le seguenti istruzioni in * ~/net/ipv4/af_inet.c: * * case SOCK_RAW: * if (protocol == IPPROTO_RAW) * sk->ip_hdrincl = 1; * * che permettono di bypassare tranquillamente * l'uso di setsockopt() ... * In questo caso dovremo anche controllare in * ogni sys_sendto() per evitare lo spoof degli * IP sorgente dalla nostra box. Comunque, ogni * tentativo verra' loggato. Una comoda password * da inserire in un file in /proc/net/ potra' * servire al 'legittimo' root per operare sugli * header dei pacchetti. * * Implementazione per Linux 2.2.x * * __NO__(C)2000 FuSyS [S0ftPj|BFi] * * * Compilate con: gcc -c -O2 -fomit-frame-pointer N0Sp00f.c * Installate con: insmod N0Sp00f.o * * Credits: LKMPG per /proc, pIGpEN per avermi spronato, * i LAMAH di tutto il mondo per i DoS [se privi * di ogni significato 'antagonista' ...], * Gigi_Sull per tutti gli Aieeeee' =) * */ #define MODULE #define __KERNEL__ #define CONFIG_PROC_FS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PASS_LENGTH 50 #define PASSWORD "[S0ftPj|BFi]" #define LKMNAME "N0Sp00f" #define LOG int (*old_socketcall) (int, unsigned long *); int (*old_query_module)(const char *, int, char *, size_t, size_t *) ; extern void *sys_call_table[]; static char password[PASS_LENGTH]; char *DEVICE="eth0"; char Rip[15]; int errno; MODULE_PARM(DEVICE, "s"); char *ntoa(unsigned long ip) { static char buff[18]; char *p; p = (char *) &ip; sprintf(buff, "%d.%d.%d.%d", (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); return(buff); } void getIPs() { struct device *dev; struct in_device *in_dev; struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; dev =(struct device *)(dev_get(DEVICE)); in_dev = dev->ip_ptr; if ((in_dev=dev->ip_ptr) != NULL) { for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) if (strcmp(DEVICE, ifa->ifa_label) == 0) break; } strncpy(Rip, ntoa(ifa->ifa_local), 15); } static ssize_t module_output(struct file *file, char *buf, size_t len, loff_t *offset) { static int finished = 0; int i; char message[PASS_LENGTH+30]; if (finished) { finished = 0; return 0; } sprintf(message, "N0SP00F Password\n"); for(i=0; ieuid == 0) return 0; return -EACCES; } int module_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; return 0; } int module_close(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return 0; } static struct file_operations N0SP00F_fops = { NULL, module_output, module_input, NULL, NULL, NULL, NULL, module_open, NULL, module_close, }; static struct inode_operations N0SP00F_iops = { &N0SP00F_fops, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, module_permission }; static struct proc_dir_entry N0SP00F = { 0, 7, "N0SP00F", S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 50, &N0SP00F_iops, NULL }; int new_socketcall(int call, unsigned long *args) { int socket; unsigned long *sargs = args; unsigned long a0, a1, a2; void *buf; struct iphdr *ip; if(call == SYS_SETSOCKOPT) { if(sargs[2] == IP_HDRINCL) { if(!strstr(password, PASSWORD)) { printk(KERN_INFO " IP_HDRINCL: %s with UID:%d and TTY:%s\n", current->comm, current->uid, current->tty->driver.driver_name); return -EPERM; } } return socket = (*old_socketcall) (call, args); } else if(call == SYS_SENDTO) { get_user(a0, sargs); get_user(a1, sargs + 1); get_user(a2, sargs + 2); buf = (void*)kmalloc(a2, GFP_KERNEL); copy_from_user(buf, (void *) a1, a2); ip = (struct iphdr *)(void *)buf ; if(ip->ihl == 5 && ip->version == 4) { if(!strstr(password, PASSWORD)) { if(!strstr(Rip, (ntoa(ip->saddr)))) { #ifdef LOG printk(KERN_INFO " sys_sendto\(): %s with UID:%d, TTY:%s and IP: %s\n", current->comm, current->uid, current->tty->driver.driver_name, ntoa(ip->saddr)); #else printk(KERN_INFO " sys_sendto\(): %s with UID:%d, TTY:%s\n", current->comm, current->uid,current->tty->driver.driver_name); #endif return -EPERM; } } } } return socket = (*old_socketcall) (call, args); } int new_query_module(const char *name, int which, char *buf, size_t bufsize, size_t *ret) { int res; int cnt; char *ptr, *match; res = (*old_query_module)(name, which, buf, bufsize, ret); if(res == -1) return(-errno); if(which != QM_MODULES) return(res); ptr = buf; for(cnt = 0; cnt < *ret; cnt++) { if(!strcmp(LKMNAME, ptr)) { match = ptr; while(*ptr) ptr++; ptr++; memcpy(match, ptr, bufsize - (ptr - (char *)buf)); (*ret)--; return(res); } while(*ptr) ptr++; ptr++; } return(res); } void ttycredit(char *str) { struct tty_struct *mytty; if((mytty = current->tty) != NULL) { (*(mytty->driver).write)(mytty, 0, str, strlen(str)); } } int init_module(void) { EXPORT_NO_SYMBOLS; getIPs(); old_socketcall = sys_call_table[SYS_socketcall]; sys_call_table[SYS_socketcall] = (void *) new_socketcall; old_query_module = sys_call_table[SYS_query_module]; sys_call_table[SYS_query_module]=(void *)new_query_module; ttycredit("\n\033[1;34m---[ \033[1;32mN0Sp00f\033[1;34m"); ttycredit(" Linux 2.2.x LKM by FuSyS [S0ftPj|BFi] ]---\033[0m\r\n\r\n"); printk(KERN_INFO "Loading N0Sp00f to protect bypassing %s\n", Rip); return proc_register(proc_net, &N0SP00F); } void cleanup_module(void) { proc_unregister(proc_net, N0SP00F.low_ino); sys_call_table[SYS_socketcall] = old_socketcall; sys_call_table[SYS_query_module] = old_query_module; ttycredit("\n\033[1;34m Modulo N0Sp00f Disattivato\033[0m\r\n\r\n"); printk(KERN_INFO "Modulo N0Sp00f Disattivato\n"); }