一、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传给驱动层最后实现进程保护