Rootkit技术(二)隐藏LKM

前一篇文章中介绍了hook系统调用的方法,但是通过lsmod等方法可以看到正在内核运行的模块。所以本文主要介绍隐藏LKM的方法,其实很简单。

从lsmod命令中隐藏模块

对于rootkit来说,隐蔽性非常重要,但lsmod命令就能直接看到我们编写的模块。这里先介绍一下lsmod原理,以便理解如何在lsmod命令中隐藏模块。
lsmod命令是通过/proc/modules来获取当前系统模块信息的。而/proc/modules中的当前系统模块信息是内核利用struct module结构体的表头遍历内核模块链表、从所有模块的struct module结构体中获取模块的相关信息来得到的。结构体struct module在内核中代表一个内核模块。通过insmod把模块插入内核时,模块便与一个struct module结构体相关联,并成为内核的一部分,所有的内核模块都被维护在一个全局链表中,链表头是一个全局变量struct module *modules。任何一个新创建的模块,都会被加入到这个链表的头部,通过modules->next即可引用到。为了让模块在lsmod命令的输出中消失,就需要在这个链表内删除这个模块。

1
list_del_init(&__this_module.list);

list_del_init函数定义于include/linux/list.h中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static inline void list_del_init (struct list_head * entry)
{
__list_del (entry->prev, entry->next);
INIT_LIST_HEAD (entry);
}

static inline void __list_del (struct list_head * prev, struct list_head * next)
{
next-> prev = prev;
prev-> next = next;
}

static inline void INIT_LIST_HEAD (struct list_head * list)
{
list-> next = list;
list-> prev = list;
}

只要在模块的初始化函数中加入

1
list_del_init(&__this_module.list);

就可以在lsmod命令中隐藏我们的模块了!

从sysfs中隐藏模块

除了lsmod命令和相对应的查看/proc/modules以外,还可以在sysfs中,也就是查看/sys/module/目录发现内核中的模块。
这个问题也很好解决,也是在初始化函数中添加一行代码:

1
kobject_del(&THIS_MODULE->mkobj.kobj);

THIS_MODULE在include/linux/module.h中的定义如下:

1
2
extern struct module __this_module;
#define THIS_MODULE (&__this_module)

可以看出THIS_MODULE的作用是指向当前模块。&THIS_MODULE->mkobj.kobj则代表的是struct module结构体的成员struct module_kobject的一部分,结构体的定义如下:

1
2
3
4
struct module_kobject {
struct kobject kobj;
struct module *mod;
}

其中kobj是一个struct kobject结构体,而kobject是组成设备模型的基本结构。这里简单介绍下sysfs这个概念,sysfs是一种基于RAM的文件系统,它提供了一种用于向用户空间展现内核空间里的对象、属性和链接的方法。sysfs与kobject层次紧密相连,它将kobject层次关系表现出来,使得用户空间可以看见这些层次关系。通常,sysfs是挂载在/sys目录下的,而/sys/module是一个sysfs的一个目录层次, 包含当前加载模块的信息. 我们通过kobject_del()函数删除我们当前模块的kobject就可以起到在/sys/module中隐藏lkm的作用。
reference
http://www.freebuf.com/articles/system/54263.html