Linux Rootkit技术研究

本文总结Linux Rookit类型,研究隐藏技术与手段...

0x01 基础知识

1. 定义

Rootkit是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身及指定的文件、进程和网络链接等信息。Rootkit通过加载特殊的驱动,修改系统内核,进而达到隐藏信息的目的。

2. 类型

1)应用级rootkit

通过替换login、ps、ls、netstat等系统工具,或修改.rhosts等系统配置文件等实现隐藏及后门

2)内核级rootkit

加载内核模块:Linux 内核可以在运行时加载内核模块(例如设备驱动程序)。这允许攻击者插入一个覆盖内核系统调用的模块,以返回不正确的值(例如,不列出某些文件),或提供对攻击者有用的新功能(例如,为某些进程提供 root 权限)

操作内存修改内核:指在系统不支持lkm机制时修改内核的一种方法,通过写入 /dev/kmem、/dev/mem等设备可以在运行时覆盖内核,从而执行任意修改

3)硬件级rootkit

主要指bios rootkit,可以在系统加载前获得控制权,通过向磁盘中写入文件,再由引导程序加载该文件重新获得控制权,也可以采用虚拟机技术,控制整个操作系统运行

3. 目的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1. 隐藏文件
通过strace ls可以发现ls命令其实是通过sys_getdents64获得文件目录的,因此可以通过修改sys_getdents64系统调用或者更底层的readdir实现隐藏文件及目录

2. 隐藏进程
隐藏进程的方法和隐藏文件类似,ps命令是通过读取/proc文件系统下的进程目录获得进程信息的,只要能够隐藏/proc文件系统下的进程目录就可以达到隐藏进程的效果,即hook sys_getdents64和readdir等。

3. 隐藏连接
netstat命令是通过读取/proc文件系统下的net/tcp和net/udp文件获得当前连接信息,因此可以通过hook sys_read调用实现隐藏连接,也可以修改tcp4_seq_show和udp4_seq_show等函数实现。

4. 隐藏模块
lsmod命令主要是通过sys_query_module系统调用获得模块信息,可以通过hook sys_query_module系统调用隐藏模块,也可以通过将模块从内核模块链表中摘除从而达到隐藏效果

5. 嗅探工具
1) 嗅探工具可以通过libpcap库直接访问链路层,截获数据包
2) 也可以通过linux的netfilter框架在IP层的hook点上截获数据包
嗅探器要获得网络上的其他数据包需要将网卡设置为混杂模式,这是通过ioctl系统调用的SIOCSIFFLAGS命令实现的,查看网卡的当前模式是通过SIOCGIFFLAGS命令,因此可以通过hook sys_ioctl隐藏网卡的混杂模式

6. 密码记录
密码记录可以通过hook sys_read系统调用实现,比如通过判断当前运行的进程名或者当前终端是否关闭回显,可以获取用户的输入密码。hook sys_read还可以实现login后门等其它功能

7. 日志擦除
传统的unix日志主要在
1) /var/log/messages
2) /var/log/lastlog
3) /var/run/utmp
4) /var
5) /log/wtmp下
可以通过编写相应的工具对日志文件进行修改,还可以将HISTFILE等环境变设为/dev/null隐藏用户的一些操作信息

8. 内核后门
1) 本地的提权后门
本地的提权可以通过对内核模块发送定制命令实现
2) 网络的监听后门
网络内核后门可以在IP层对进入主机的数据包进行监听,发现匹配的指定数据包后立刻启动回连进程

0x02 隐藏技术

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
1. 灵活的指令配置
1) 通过创建/proc下虚拟目录的读写接口函数接收ring3层的指令、指令灵活配置
2) 通过netlink技术实现ring3和ring0的通信,向rootkit下发指令

2. 内核模块隐藏(包括隐藏rootkit自身分模块)
1) 基于断链法的内核模块隐藏技术

3. 文件、目录隐藏
1) 基于对/etc目录文件读取枚举接口函数劫持的的文件隐藏
2) 隐藏文件中"特定的内容"
3) 替换关键系统指令程序,例如ls、ll
4) 基于sys_execv系统调用劫持实现可执行程序执行重定向技术

4. 进程隐藏
1) 基于/proc的目录读取函数劫持的进程隐藏
2) 基于系统调用hook的进程隐藏
3) 替换关键系统指令程序,例如ps、top
4) 基于getdents64系统调用劫持实现可执行程序执行重定向技术

5. 网络连接状态隐藏
1) netfilter注册回调实现网络连接状态隐藏
2) /proc/net/tcp修改过滤实现网络连接状态隐藏

6. 获取root权限的shell
1) 通过内核API(prepare_creds()、commit_creds())获得rootkit权限shell
2) 无连接方式SHELL激活
2.1) tcp激活
2.2) udp激活
2.3) icmp激活

7. 远程控制(shell)
1) kernel mode socket connect back(内核态反向回连)

8. 通信加密
1) commit_creds
2) 借助HTTP、或DNS协议进行通信

9. 键盘记录
1) 密码记录(ssh, su, mysql, pop3, passwd etc)

0x03 驻留技术

1. 用户态驻留点

a. INIT自启动利用

Linux init

在systemd成为主流之前,sysvinit是大多数发行版的选择。作为Linux的init程序,也就是PID 1,负责启动之后的所有进程,所有的服务都是由它管理,可用其实现rootkit驻留

对于sysvinit,常见的驻留点需要以root身份写入:

1
2
3
/etc/init.d
/etc/rc[runlevel].d
/etc/rc.local

对于systemd,可以用更多手段实现驻留,不需要root权限也可以:

1
2
3
4
5
6
etc/systemd/system
/etc/systemd/user
/lib/systemd/system
/lib/systemd/user
~/.local/share/systemd/user
~/.config/systemd/user

systemctl --user enable ervice使服务随用户登录启动, systemctl enable service 让服务随系统启动。

bashrc

bashrc或者zshrc等文件会随着shell的运行而被执行,利用时只需在里面加入恶意的shell script

1
2
3
4
/etc/profile
~/.bashrc
~/.bash_profile
~/.bash_logout

xinitrc

当目标主机有安装Xorg,也可以以下位置写入shell script实现rootkit驻留,不需要root权限

1
2
3
4
~/.xinitrc
~/.xserverrc
/etc/X11/xinit/xinitrc
/etc/X11/xinit/xserverrc

用户initrc

任何应用程序都可能在启动时执行代码,而且它们可能会执行用户home目录的rc文件,可用于rootkit驻留

vimrc

可以在vimrc里 写入vimscript来执行代码实现rookit的驻留,可以不需要root权限

b. CROND计划任务利用

写入软件包使用的crontab里面,如/etc/cron.d目录,模拟正常程序隐藏rootkit

定时任务文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1) 系统配置项:系统执行的计划任务

/etc/crontab
/etc/cron.d/

2) 用户允许/禁止配置文件

/etc/cron.deny :用来禁止一些用户使用cron服务的配置文件
/etc/cron.allow :允许一些用户来使用cron服务的配置文件,优先级高

3) 用户配置项:执行crontab命令操作的目录

/var/spool/cron

4) 其他计划任务文件

/etc/cron.daily
/etc/cron.deny
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly

c. 命令/文件替换

常用替换命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
1) bin目录

/bin/ls

/bin/ps

/bin/bash

/bin/netstat

/bin/login

/bin/find

/bin/lsmod

/bin/pidof

/bin/lsof

/bin/ss

2) usr目录

/usr/bin/ls

/usr/bin/ps

/usr/sbin/ps

/usr/bin/bash

/usr/bin/netstat

/usr/sbin/netstat

/usr/sbin/rsyslogd

/usr/sbin/ifconfig

/usr/bin/login

/usr/bin/find

/usr/sbin/lsmod

/usr/sbin/pidof

/usr/bin/lsof

/usr/sbin/lsof

/usr/sbin/tcpd

/usr/bin/passwd

/usr/bin/top

/usr/bin/du

/usr/bin/chfn

/usr/bin/chsh

/usr/bin/killall

/usr/bin/ss

/usr/sbin/ss

/usr/bin/ssh

/usr/bin/scp

3)sbin目录

/sbin/ifconfig

/sbin/lsmod

/sbin/pidof

/sbin/syslog-ng

/sbin/rsyslogd

程序文件替换

替换或者patch一些会被服务或用户本身执行的程序文件,同时执行恶意代码,是比较常见的驻留方式

如果目标主机是git或svn服务器,如果能获取项目源码,可以通过修改目标的源码植入恶意代码,或者利用编译环境,在项目构建时插入恶意代码,比如在configure脚本里或者Makefile里插入代码,既可以在本机运行,又有可能在编译之后在更多主机上运行,进一步扩大感染范围

d. 动态链接库劫持

替换动态链接库

libc会被几乎所有的ELF调用,而特定的lib则会被特定的ELF调用,可以利用重新编译的恶意so替换掉它所链接的某个so文件,达到执行恶意代码的效果;大部分程序都是动态链接库文件,需避免加入的代码调用的程序最终往回调用修改的库文件本身,作为动态链接库,其函数可能被频繁调用,在利用的时候要避免造成不必要的负载

ld.so.preload

最常见是在 /etc/ld.so.preload 中写入需要让libc执行的so文件,或者设置 LD_PRELOAD 环境变量,这样,任何依赖系统libc的user space程序,都会在运行之前执行我们的so文件,从而实现rootkit驻留

2. 内核态驻留点

a. LKM – 可加载内核模块

Linux 内核可以在运行时加载内核模块(例如设备驱动程序)。这允许攻击者插入一个覆盖内核系统调用的模块,以返回不正确的值(例如,不列出某些文件),或提供对攻击者有用的新功能(例如,为某些进程提供 root 权限)

LKM实现比较简单,在加载和退出的时候执行了两个shell脚本,并使用printk输出了内核调试信息。只需定义两个函数分别用于initialize和exit即可完成LKM的主体框架了,module.h会有相应函数 module_init 和module_exit用来实现

b. 通过 /dev/kmem 加载的 Rootkit

指在系统不支持lkm机制时修改内核的一种方法,通过写入 /dev/kmem、/dev/mem等设备可以在运行时覆盖内核,从而执行任意修改

0xFF Reference