Linux内核重建注意点,Linux Loader 机制与内核模块修复

文章目录

[隐藏]

0x0 前言

0x1 Linux 启动与内核加载

1.1 bootloader

1.2 内核文件

1.3 解剖 initramfs

1.4 bootloader 配置

0x2 内核模块依赖重建

2.1 内核模块

2.2 问题重现

2.3 修复内核模块

0x4 总结

0x0 前言

在吃着月饼喝着茶的闲暇时间里,突然接到某单位的应急通知。赶往现场进行初步勘察后,发现攻击者手段非常暴力,直接删除系统相关关键模块(包括 PAM 模块、基础内核驱动模块等),导致后续用户无法登录操作系统。

在尝试恢复 PAM 模块后,正常登录系统,但由于缺少基础的核心模块,网络、USB 挂载等仍无法正常使用。在下载部分二进制驱动包进行安装后,重启开始出现问题(截图为后期复现):

949253b8b547265988ac248800a2ee63.png

确认 /lib/modules/ 下确实存在此文件,但重启依然出现此问题。

而由于对 Linux Loader 机制的不熟悉,现场并未能解决此问题(菜。同时在不确定攻击者是否也删除了正常业务程序组件的情况下,恢复的成本较大,于是备份关键数据,提取相关样本与日志后,对系统进行重装,恢复正常业务。

0x1 Linux 启动与内核加载

1.1 bootloader

首先,还是从我们的老朋友 BIOS 进行加电自检(POST,Power-On Self-Test)后,开始读取 MBR 记录。MBR 为 512 字节大小的扇区,其中前 446 字节硬编码着 bootloader 程序。BIOS 从 MBR 记录读取 bootloader 程序,将其加载到内存,并运行该程序。

对于不同的操作系统,有不同的 bootloader 程序,一般在安装操作系统时,安装程序会向 MBR 写入 bootloader 程序。如 Windows 操作系统,使用自带的 bootloader 程序。对于 Linux 发行版,一般使用新版的 GRUB2 来生成并写入 bootloader。

bootloader 的工作便是载入内核文件,使操作系统正常运行。

1.2 内核文件

在 Linux 中,由 bootloader 载入的内核文件位于 /boot 节点下:

[root@centos boot]# ls --format=single-column /boot config-2.6.32-696.el6.x86_64 # 内核编译时启用的配置信息与模块设定 efi # EFI 引导程序 grub # GRUB 引导程序支持 initramfs-2.6.32-696.el6.x86_64.img # 虚拟文件系统,主角 ;-) symvers-2.6.32-696.el6.x86_64.gz # 驱动模块符号表 System.map-2.6.32-696.el6.x86_64 # 内核符号表 vmlinuz-2.6.32-696.el6.x86_64 # 内核文件

如上,vmlinuz 便是 bootloader 载入的 Linux 内核文件,内核文件主要负责检测基础的硬件设施,并载入相关驱动,这些驱动一般位于 /lib/modules// 目录下。

那么 initramfs 是干嘛的?当内核启动时,需要往 /lib/modudles 下读取驱动文件,以支持 SATA、USB 等接口的设备,但是明显 /lib/modules 是存储于 SATA 磁盘中,没有 SATA 驱动的情况下也无法读取挂载,这里就出现了先有鸡还是先有蛋的问题。

而 initramfs 便是来解决这个问题,initramfs 事实上是一个具有根目录结构的文件,其中包含基础的应用程序,以及核心的内核模块,例如 SCSI、SATA、USB 等,用于支持最基础的外部设备。

1.3 解剖 initramfs

新建目录,将 initramfs 拷贝到目标目录下:

[root@centos ~]# mkdir /tmp/initramfs [root@centos ~]# cp /boot/initramfs-2.6.32-696.el6.x86_64.img /tmp/initramfs/initramfs.img

initramfs 使用 gzip 进行压缩,将其解压:

[root@centos ~]# cd /tmp/initramfs/ [root@centos initramfs]# file initramfs.img initramfs.img: gzip compressed data, from Unix, last modified: Wed Oct 4 17:17:17 2017, max compression [root@centos initramfs]# mv initramfs.img initramfs.gz [root@centos initramfs]# gzip -d initramfs.gz

在解压完成后,实际上文件使用 cpio 进行归档,最后我们使用 cpio 将其解压出来:

[root@centos initramfs]# file initramfs initramfs: ASCII cpio archive (SVR4 with no CRC) # -i 解压文件 # -d 必要时创建目录 # -H newc 指定类型为 SVR4 的归档文件 # --no-absolute-filenames 不要将文件解压覆盖到绝对路径 [root@centos initramfs]# cpio -i -d -H newc --no-absolute-filenames < initramfs 108638 blocks

从最后的目录结构可以看到 initramfs 的真实内容:

[root@centos initramfs]# ll total 54432 drwxr-xr-x. 2 root root 4096 Oct 5 22:50 bin drwxr-xr-x. 2 root root 4096 Oct 5 22:50 cmdline drwxr-xr-x. 3 root root 4096 Oct 5 22:50 dev -rw-r--r--. 1 root root 23 Oct 5 22:50 dracut-004-409.el6_8.2 drwxr-xr-x. 2 root root 4096 Oct 5 22:50 emergency drwxr-xr-x. 7 root root 4096 Oct 5 22:50 etc -rwxr-xr-x. 1 root root 8989 Oct 5 22:50 init drwxr-xr-x. 2 root root 4096 Oct 5 22:50 initqueue drwxr-xr-x. 2 root root 4096 Oct 5 22:50 initqueue-finished drwxr-xr-x. 2 root root 4096 Oct 5 22:50 initqueue-settled drwxr-xr-x. 2 root root 4096 Oct 5 22:50 initqueue-timeout drwxr-xr-x. 7 root root 4096 Oct 5 22:50 lib drwxr-xr-x. 3 root root 4096 Oct 5 22:50 lib64 drwxr-xr-x. 2 root root 4096 Oct 5 22:50 mount drwxr-xr-x. 2 root root 4096 Oct 5 22:50 netroot drwxr-xr-x. 2 root root 4096 Oct 5 22:50 pre-mount drwxr-xr-x. 2 root root 4096 Oct 5 22:50 pre-pivot drwxr-xr-x. 2 root root 4096 Oct 5 22:50 pre-trigger drwxr-xr-x. 2 root root 4096 Oct 5 22:50 pre-udev drwxr-xr-x. 2 root root 4096 Oct 5 22:50 proc drwxr-xr-x. 2 root root 4096 Oct 5 22:50 sbin drwxr-xr-x. 2 root root 4096 Oct 5 22:50 sys drwxr-xr-x. 2 root root 4096 Oct 5 22:50 sysroot drwxrwxrwt. 2 root root 4096 Oct 5 22:50 tmp drwxr-xr-x. 7 root root 4096 Oct 5 22:50 usr drwxr-xr-x. 4 root root 4096 Oct 5 22:50 var

列一下 lib/modules//kernel/drivers 下的驱动文件:

[root@centos initramfs]# ls lib/modules/2.6.32-696.el6.x86_64/kernel/drivers/ acpi ata atm auxdisplay bcma block bluetooth cdrom <...snippets...>

initramfs 中包含最核心的驱动程序,bootloader 在启动时,将 initramfs 临时挂载到根目录,在内核文件正常加载驱动后,对其进行卸载,并挂载真正的根目录节点。

最后,内核程序启动 init / systemd 对系统服务进行加载。

1.4 bootloader 配置

在 Linux 发行版下,bootloader 通常由 GRUB 程序进行管理,而 bootloader 又负责加载内核文件,较新的发行版一般使用新的 GRUB2 进行引导。

由于笔者使用的是 CentOS 6.X,所以此时默认还是旧版的 GRUB 引导管理程序,但不同版本配置上大同小异,所以以旧版为例。

默认情况下,/boot/grub 下(新版为/boot/grub2)存放 GRUB 的配置文件:

[root@centos ~]# ls /boot/grub grub.conf # GRUB 的引导菜单配置文件 stage1 stage2 <...snippets...>

可以注意到目录下有 stage1 和 stage2 文件,这个其实便是 bootloader 程序。由于 MBR 区域只有可怜的 512 字节,而 bootloader 程序相对都会比较大,所以 GRUB 将启动分为两个阶段,真正存在于 MBR 处的代码便是 stage1 程序,再由此加载真正的 bootloader 程序 stage2。

再看看主配置文件 /boot/grub/grub.conf 的内容:

# grub.conf generated by anaconda default=0 timeout=5 title CentOS 6 (2.6.32-696.el6.x86_64) root (hd0,0) kernel /vmlinuz-2.6.32-696.el6.x86_64 ro root=/dev/mapper/vg_centos-lv_root nomodeset rd_NO_LUKS https://www.centos.bz/wp-content/uploads/2017/10/2-11.png" alt="" srcset="https://www.centos.bz/wp-content/uploads/2017/10/2-11.png 1664w, https://www.centos.bz/wp-content/uploads/2017/10/2-11-768x508.png 768w" sizes="(max-width: 1664px) 100vw, 1664px" />

再次重启后,正常进入系统,基本模块修复:

121c7d855fb5be5c93821627110e6927.png

0x4 总结

内核通过 initramfs 载入核心驱动为基础的外部设备提供支持

内核模块位于 /lib/modules/ 下,modules.dep 记录模块索引,使用 depmod -a 可以自动建立依赖信息

使用 dracut 可以对 initramfs 进行重建,将 /lib/modules/ 下的核心模块打包到虚拟文件系统当中

在 SELinux 的上下文下,需要建立 /.autorelabel 通知 SELinux 重新建立策略

总体而言都是在干运维的活,但是 Loader 的加载机制还是十分有趣。

原文出处:threathunter -> https://threathunter.org/topic/59d60bebec721b1f1966ec64https://threathunter.org/topic/59d60bebec721b1f1966ec64

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值