Linux下task_struct劫持实现进程保护

一、task_struct介绍

task_struct 是 Linux 内核中的进程控制块 (PCB),存储着所有进程的信息。它定义在 include/linux/sched.h 中,包含以下关键字段:

struct task_struct {
    pid_t pid;                       // 进程ID
    struct list_head tasks;          // 进程链表
    struct mm_struct *mm;            // 进程的内存管理信息
    struct signal_struct *signal;    // 进程的信号信息
    struct task_struct *real_parent; // 真实父进程
    struct thread_info *thread_info; // 线程信息
    ...
};

其中,task_struct->signal 是 signal_struct 类型,它存储了进程的信号处理信息:

struct signal_struct {
    unsigned long flags;  // 信号标志
    struct sigpending shared_pending;
    struct list_head posix_timers;
    ...
};

二、劫持原理

2.通过修改 task_struct 结构体中的 signal 成员(类型为 struct signal_struct),调整 signal->flags 标志位,可以实现对进程的保护,使其无法被 kill 或 kill -9 终止。flags标志作用如下表所示:

2.标志所在源码路径为include/linux/sched/signal.h如下图所示:

三、代码实现

1.方法一

直接使用裸驱动使用task_struct劫持实现进程保护驱动代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/kallsyms.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CAIJISG");
MODULE_DESCRIPTION("Process Protection Module - Prevent SIGKILL");

static pid_t protected_pid = 0;
static struct task_struct *protected_task = NULL;

static int protect_process(pid_t pid) {
    struct task_struct *task;
    
    for_each_process(task) {
        if (task->pid == pid) {
            protected_task = task;
            task->signal->flags |= SIGNAL_UNKILLABLE;
            printk(KERN_INFO "Process %d is now protected.\n", pid);
            return 0;
        }
    }

    printk(KERN_ERR "Process %d not found.\n", pid);
    return -ESRCH;
}

static int __init process_protect_init(void) {
    protected_pid = 6988;  // 替换为你要保护的进程 PID
    return protect_process(protected_pid);
}

static void __exit process_protect_exit(void) {
    if (protected_task) {
        protected_task->signal->flags &= ~SIGNAL_UNKILLABLE;
        printk(KERN_INFO "Process %d is now unprotected.\n", protected_pid);
    }
}

module_init(process_protect_init);
module_exit(process_protect_exit);

2.Makefile文件

makefile文件如下:

obj-m := proc_protect.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules


clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

3.展示结果如下

驱动运行状态下,使用kill -9 7449强制退出进程发现退出失败

驱动未运行状态下,使用kill -9 7449强制退出进程发现退出成功

4.设备号创建

如果在加载驱动时系统没有自动创建设备号,可以使用以下命令进行创建相应的设备号,命令如下所示:

sudo mknod /dev/process_protect c 10 $(grep -w process_protect /proc/misc | awk '{print $1}')

1.方法二

驱动代码实现如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>

#define DEVICE_NAME "process_protect"
#define IOCTL_SET_PID _IOW('p', 1, int)

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CAIJISG");
MODULE_DESCRIPTION("Process Protection Module - Prevent SIGKILL");

static pid_t protected_pid = 0;
static struct task_struct *protected_task = NULL;

static int protect_process(pid_t pid) {
    struct task_struct *task;

    for_each_process(task) {
        if (task->pid == pid) {
            protected_task = task;
            task->signal->flags |= SIGNAL_UNKILLABLE;
            protected_pid = pid;
            printk(KERN_INFO "Protected process PID: %d\n", pid);
            return 0;
        }
    }

    printk(KERN_ERR "Process %d not found.\n", pid);
    return -ESRCH;
}

static long protect_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    pid_t pid;
    
    if (cmd != IOCTL_SET_PID)
        return -EINVAL;

    if (copy_from_user(&pid, (pid_t __user *)arg, sizeof(pid_t)))
        return -EFAULT;

    return protect_process(pid);
}

static int protect_open(struct inode *inode, struct file *file) {
    return 0;
}

static int protect_release(struct inode *inode, struct file *file) {
    return 0;
}

static const struct file_operations protect_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = protect_ioctl,
    .open = protect_open,
    .release = protect_release,
};

static struct miscdevice protect_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &protect_fops,
};

static int __init process_protect_init(void) {
    int ret = misc_register(&protect_device);
    if (ret)
        printk(KERN_ERR "Failed to register device\n");
    else
        printk(KERN_INFO "Process protection module loaded\n");
    return ret;
}

static void __exit process_protect_exit(void) {
    if (protected_task)
        protected_task->signal->flags &= ~SIGNAL_UNKILLABLE;

    misc_deregister(&protect_device);
    printk(KERN_INFO "Process protection module unloaded\n");
}

module_init(process_protect_init);
module_exit(process_protect_exit);

2.应用层代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define DEVICE_NAME "/dev/process_protect"
#define IOCTL_SET_PID _IOW('p', 1, int)

int main(int argc, char *argv[]) {
    int fd, pid;

    if (argc != 2) {
        printf("Usage: %s <pid>\n", argv[0]);
        return -1;
    }

    pid = atoi(argv[1]);

    fd = open(DEVICE_NAME, O_RDONLY);
    if (fd < 0) {
        perror("Failed to open device");
        return -1;
    }

    if (ioctl(fd, IOCTL_SET_PID, &pid) < 0) {
        perror("ioctl failed");
        close(fd);
        return -1;
    }

    printf("Protected PID: %d\n", pid);
    close(fd);
    return 0;
}

3.Makefile文件
obj-m := proc_protect.o
KDIR :=/lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules


clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean

4.成果展示

首先加载驱动,然后通过应用层程序把需要保护的进程pid传给驱动层最后实现进程保护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值