记一次隐藏进程的驱动模块编写

admin 2020年12月30日16:00:50评论127 views字数 2407阅读8分1秒阅读模式

点击蓝字  关注我们

# 前言


在家闲着无聊写了一个隐藏文件隐藏进程的驱动模块就是大家俗称的rootkit技术

#Rootkit介绍

Rootkit 是一种特殊类型的 malware恶意软件,Rootkit 之所以特殊是因为您不知道它们在做什么事情。Rootkit 基本上是无法检测到的,而且几乎不能删除它们。虽然检测工具在不断增多,但是恶意软件的开发者也在不断寻找新的途径来掩盖他们的踪迹。Rootkit 的目的在于隐藏自己以及其他软件不被发现。它可以通过阻止用户识别和删除攻击者的软件来达到这个目的。Rootkit 几乎可以隐藏任何软件,包括文件服务器、键盘记录器、Botnet Remailer。许多 Rootkit 甚至可以隐藏大型的文件集合并允许攻击者在您的计算机上保存许多文件,而您无法看到这些文件。Rootkit 本身不会像病毒或蠕虫那样影响计算机的运行。攻击者可以找出目标系统上的现有漏洞。漏洞可能包括:开放的网络端口、未打补丁的系统或者具有脆弱的管理员密码的系统。在获得存在漏洞的系统的访问权限之后,攻击者便可手动安装一个Rootkit。这种类型的偷偷摸摸的攻击通常不会触发自动执行的网络安全控制功能,例如入侵检测系统。找出 Rootkit 十分困难。有一些软件包可以检测 Rootkit。这些软件包可划分为以下两类:基于签名的检查程序和基于行为的检查程序。基于签名(特征码)的检查程序,例如大多数病毒扫描程序,会检查二进制文件是否为已知的 Rootkit。基于行为的检查程序试图通过查找一些代表 Rootkit 主要行为的隐藏元素来找出 Rootkit。一个流行的基于行为的 Rootkit 检查程序是 Rootkit Revealer,在发现系统中存在 Rootkit 之后,能够采取的补救措施也较为有限。由于 Rootkit 可以将自身隐藏起来,所以您可能无法知道它们已经在系统中存在了多长的时间。而且您也不知道 Rootkit 已经对哪些信息造成了损害。对于找出的 Rootkit,最好的应对方法便是擦除并重新安装系统。虽然这种手段很严厉,但是这是得到证明的唯一可以彻底删除 Rootkit 的方法。

#正文

我们先简要分析一下内核模块的加载过程,相关代码位于内核源码树的kernel/module.c 我们从 init_module 开始看。我们先简要分析一下内核模块的加载过程。相关代码位于内核源码树的kernel/module.c 。我们从 init_module 开始看。

记一次隐藏进程的驱动模块编写

模块加载的主要工作都是 load_module 完成的,这个函数比较长,这里只贴我们关心的一小段。

记一次隐藏进程的驱动模块编写

说的具体点,我们注册的通知链处理函数是在 notifier_call_chain函数里被调用的,调用层次为: blocking_notifier_call_chain ->__blocking_notifier_call_chain -> notifier_call_chain 。有疑惑的读者可以细致地看看这部分代码,位于内核源码树的kernel/notifier.c 

代码分析告一段落,接下来我们看看如何注册模块通知处理函数。用于描述通知处理函数的结构体是 structnotifier_block 定义如下

记一次隐藏进程的驱动模块编写

注册或者注销模块通知处理函数可以使用 register_module_notifier 或者unregister_module_notifier ,函数原型如下。

记一次隐藏进程的驱动模块编写

编写一个通知处理函数,然后填充 structnotifier_block 结构体,最后使用register_module_notifier 注册就可以了。代码片段如下。

记一次隐藏进程的驱动模块编写

上面的代码是声明处理函数并填充所需结构体;下面是处理函数具体实现

记一次隐藏进程的驱动模块编写

说好的重点内容文件隐藏来了。不过说到文件隐藏,我们不妨先看看文件遍历的实现,也就是系统调用getdents / getdents64 ,简略地浏览它在内核态服务函数(sys_getdents)的源码(位于fs/readdir.c ),我们可以看到如下调用层次, sys_getdents ->iterate_dir -> struct file_operations 里的 iterate ->这儿省略若干层次 -> structdir_context 里的 actor ,也就是filldir 

filldir 负责把一项记录(比如说目录下的一个文件或者一个子目录)填到返回的缓冲区里。如果我们钩掉 filldir ,并在我们的钩子函数里对某些特定的记录予以直接丢弃,不填到缓冲区里,上层函数与应用程序就收不到那个记录,也就不知道那个文件或者文件夹的存在了,也就实现了文件隐藏。

具体说来,我们的隐藏逻辑如下:篡改根目录(也就是“/”)的 iterate为我们的假 iterate 在假函数里把 structdir_context 里的 actor替换成我们的 filldir ,假 filldir 会把需要隐藏的文件过滤掉。

记一次隐藏进程的驱动模块编写

这一层一层的剥开,我们来到了 structfile_operations 里面的 iterate这个 iterate 在不同的文件系统有不同的实现,下面(位于fs/ext4/dir.c 是针对 ext4文件系统的 structfile_operations 我们可以看到ext4 文件系统的 iterate ext4_readdir 

记一次隐藏进程的驱动模块编写

ext4_readdir 经过各种各样的操作之后会通过 filldir把目录里的项目一个一个的填到 getdents返回的缓冲区里,缓冲区里是一个个的 struct linux_dirent 。我们的隐藏方法就是在 filldir 里把需要隐藏的项目给过滤掉。

编译一个test 的文件 (其实什么文件都行只要是文件名对应上就行)

记一次隐藏进程的驱动模块编写

下面俩个是目标

记一次隐藏进程的驱动模块编写

记一次隐藏进程的驱动模块编写

记一次隐藏进程的驱动模块编写

记一次隐藏进程的驱动模块编写

本文始发于微信公众号(IDLab):记一次隐藏进程的驱动模块编写

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年12月30日16:00:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次隐藏进程的驱动模块编写http://cn-sec.com/archives/226676.html

发表评论

匿名网友 填写信息