Rootkit
Rootkit是一种隐蔽的恶意软件,通过隐藏自己的存在和修改系统文件来实现对计算机系统的完全控制。
Rootkit的主要特点是其高度隐蔽性和持久性。一旦成功植入到系统中,它会在系统启动时自启动,并在后台监控系统的运行状态。攻击者可以通过Rootkit来窃取用户信息、执行远程控制、发起网络攻击等恶意操作。
简单来说:rootkit就是一种能够悄悄的获取系统信息,然而不被任何人发现痕迹的幽灵
Rootkit的分类
Rootkit根据其入侵途径和作用方式的不同,可以分为以下几种主要类型:
- 用户空间Rootkit:在操作系统内的进程列表中隐藏恶意进程,使其不会被用户察觉。
- 内核空间Rootkit:通过安装恶意驱动程序或直接篡改操作系统内核,控制整个系统的运行。
- 引导Rootkit:篡改系统的引导扇区,从而使操作系统启动时加载恶意代码。
- 固件Rootkit:通过植入硬件设备中的恶意软件,控制整个系统的运行。
- 网络Rootkit:通过篡改网络协议栈或者网络接口,控制网络连接和流量。
- 特殊环境Rootkit:针对特定的环境或操作系统,例如移动设备、嵌入式系统等制定的Rootkit。c用户空间Rootkit
1.进程注入的Rootkit
实现原理
- 找到目标进程:通过遍历系统中的进程列表,找到一个目标进程,注入代码。
- 注入代码:将恶意代码注入到目标进程的内存空间中,然后通过修改目标进程的执行路径,在目标进程中执行恶意代码。
- 注入技术:使用DLL注入技术来将恶意代码注入到目标进程中。
2.基于ld.so.preload.so的Rootkit
2.1 实现原理
利用/etc/ld.so.preload文件,将恶意共享库文件添加到预加载列表中,然后将其注入到目标进程的地址空间中,从而控制和隐藏目标进程的行为和输出。
ld.so.preload文件是在系统启动时由动态链接器(ld.so)加载的一个共享库文件列表,其中指定的共享库会在所有程序加载时自动预加载到地址空间中,从而可以使用其中的函数。而系统调用本质上也是由系统的动态链接器(ld.so)加载和解析的共享库函数,因此如果在ld.so.preload文件中指定了一个共享库,它就可以在所有程序调用该系统调用时被优先加载到进程地址空间中,从而劫持系统调用实现hook。
2.2 hook实现方式
- 真实的libc库中的函数指针查找 使用dlsym()函数在查找符号时从调用dlsym()的代码之后的库中查找
- 对于hook点进行具体的操作,无需进行操作的直接调用真实的libc库的函数进行操作
2.3 特点
该方式完全是应用层的rootkit,大致上均可实现klm级的rootkit的hook技术,太过于依赖/etc/ld.so.preload文件
内核空间的Rootkit
- 驱动程序Rootkit:通过编写设备驱动程序来隐藏自己或者修改系统的行为。驱动程序Rootkit可以利用驱动程序代码的本身不易发现和容易隐藏的特点,对系统状态进行监控和篡改。
- 模块Rootkit:通过修改系统内核模块,实现欺骗系统、隐藏进程、修改文件属性等高危操作。
- 中断处理Rootkit:利用中断处理程序修改进程的系统调用表,从而实现对系统调用的篡改和控制,以此控制和隐藏进程的行为和输出。
模块Rootkit
1.Livepatch
Livepatch是一种Linux内核补丁技术,Livepatch技术可以实现对内核函数的修改和重载。
当某个系统调用被修改时,Livepatch技术可以拦截该系统调用,并运行一个自定义的函数来替代它。这个自定义的函数可以实现攻击者的目的
2.ftrace
ftrace可以拦截系统调用,并使其指向自定义的函数,从而实现对系统调用的篡改和控制.
- 导入头文件ftrace_header.h
struct ftrace_hook {
const char *name;
void *function;
void *original;
unsigned long address;
struct ftrace_ops ops;
};
#define HOOK(_name, _hook, _orig)
{
.name = SYSCALL_NAME(_name),
.function = (_hook),
.original = (_orig),
}
-
定义一个ftrace_hook hooks结构体数组
static struct ftrace_hook hooks[] = { HOOK("sys_mkdir", hook_mkdir, &orig_mkdir), };
3.kprobe/kretprobe
kretprobe与ftrace类似,但它跟踪的对象是函数的返回值,而不是函数本身。这使得kretprobe在某些情况下比ftrace更为适用
kprobe与ftrace一样
4.基于修改 [sys_call_table]的系统调用挂钩
1.获取sys_call_table表的指针地址
2.替换系统调用的地址
特点
开机自启难以实现,内核版本要求太高
引导Rootkit
BIOS Rootkit
BIOS会按照启动顺序去查找第一个磁盘头的MBR信息,并加载和执行MBR中的Bootloader程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘(PS:启动顺序可以在BIOS的界面中进行设置),一旦BootLoader程序被检测并加载内存中,BIOS就将控制权交接给了BootLoader程序
该Rootkit采取的就是在BIOS取第一块磁盘信息时,先运行恶意程序在将第一块的扇区恢复,重头读取
run-init Rootkit
- 正常linux启动流程
在Linux系统启动时,内核首先加载initramfs文件系统(调用initrd.img-x.x.x.x-generic,initramfs文件系统镜像文件),后调用initramfs文件系统中的run-init程序来启动init进程。run-init程序会根据initramfs文件系统中的内容,调用一系列的初始化程序和脚本,以完成系统的初始化和配置,最终启动系统中的所有服务和用户进程。 - 恶意run-init程序生成
Klibc提供了一系列的库和工具,可以用于构建、编译和链接initramfs文件系统中的程序。通过Klibc提供的工具和库,采取添加补丁的方式可以方便地生成和定制run-init程序,以满足不同的需求。
使用kilbc生成正常的run-init利用打补丁的形式将hw程序写入run-init,修改正常的启动顺序,使其加载hm程序 - 更新initramfs文件系统,写入恶意run-init
使用更新initramfs文件系统的命令update-initramfs
,此时系统会检查当前可用的内核版本,并重新生成每个版本的initramfs文件系统(生成目录在/var/tmp/mkinitramfs_xxx),以更新其中的配置和程序,并打包成指定的initramfs文件系统镜像文件更新完毕后mkinitramfs_xxx目录自动删除
HORSEPILL会监控/var/tmp/目录下的文件,查找到var/tmp/mkinitramfs_xxx/bin/run-init
文件时,直接将其替换成恶意run-init,此时生成的initramfs文件系统镜像文件就已经植入了HM程序.
Grub Rootkit(仅仅测试普通的模块加载,打印hello)
编写基于grub语法的mod文件
修改其配置文件grub.cfg即可将自写的mod模块带起
ebpfkit
eBPF程序需要注册自己的处理函数,并将其挂载到内核系统调用表中。当用户进程发起系统调用请求时,内核会将请求转发给挂载在系统调用表中的处理函数。
eBPF程序可以在处理函数中截获系统调用,分析请求参数并执行自己的逻辑。完成处理之后,eBPF程序将结果返回给内核并返回给用户进程。
map是一种基于键值对存储的内存结构,可以在eBPF程序和用户程序之间共享数据。
XDP可以在网卡驱动层面截取数据包,并在内核态中对数据包进行处理