木马核心技术剖析读书笔记之木马驱动加载与启动

时间:2024-06-01 09:17:01

Windows 系统启动过程

木马核心技术剖析读书笔记之木马驱动加载与启动

基于 UEFI 的启动过程

UEFI 固件接口可以实现 BIOS 固件接口类似的功能,逐步成为主流的固件接口之一。它主要提供一组在操作系统启动之前在所有平台上一致的服务,是在 EFI 1.0 基础上发展起来的新型可扩展固件接口,得到了大多数行业主流企业的支持

UEFI 的几乎所有组件都用 C 语言开发完成,不再使用中断、硬件端口直接操作的方法,而是采用 Driver/protocol 的方式。它直接采用了 CPU 的保护模式,使用没有分页的内存平坦模式(Flat mode),而不是 BIOS 的实模式。基于 BIOS 的计算机硬盘分区机制使用了 MBR,而 UEFI 使用了新的分区机制 GPT(GUID Partition Table),与 MBR 相比,GPT 不再有更多的限制,尤其体现在分区大小

基于 MBR 的分区机制使得没硬盘只能具有四个主分区,每个硬盘最高可以达到 2TB,而 GPT 允许硬盘和分区的最大容量可以达到 8ZB

基于 MBR 的 Bootkit

Bootkit 对 MBR 的利用,主要是通过修改 MBR 相关的硬盘内容,使得在 MBR 中的代码在执行之前或执行的时候,能够将 Bootkit 的代码加载执行,且需要确保系统正常启动不受影响

通常,对 MBR 的修改有两种方式:

  • 将原始 MBR 所在扇区的内容,拷贝到新的扇区,在 MBR 原来的扇区的位置处写入 Bootkit 伪造的 MBR 内容,对 MBR 进行整体替换
  • 修改 MBR 的部分代码或者数据(如可启动分区的分区表项),使得 MBR 被加载执行之前或者执行的过程,加载执行 Bootkit 的代码

以下是两种方式的具体过程:

  1. 替换MBR扇区
    该方法的基本思路是找一个空白的扇区备份原始未被感染的 MBR,再用 Bootkit 代码替换掉 0 号逻辑扇区的原始 MBR 引导代码。当系统开机执行的时候,Bootkit 的代码将代替 MBR 首先被 BIOS 程序执行,当 Bootkit 代码执行完毕后,再跳转到备份 MBR 引导代码再次执行。感染后 BIOS 加载 MBR 的执行过程:
    木马核心技术剖析读书笔记之木马驱动加载与启动

  2. 修改可启动分区表
    该方法的主要思路是遍历 MBR 的分区表项,找到可启动分区表项,并将该分区表项保存,伪造 Bootkit 的分区表项并覆盖原始的可启动表项
    当 MBR 执行的时候,会根据可启动分区表项,加载并将执行流程交给该分区的第一个扇区VBR;但在 Bootkit 修改了原始的可启动表项后,MBR 就会执行 Bootkit 的代码,Bootkit 的代码执行完成后,才会继续加载并执行原始可启动分区的第一个扇区

木马核心技术剖析读书笔记之木马驱动加载与启动

基于 VBR 的 Bootkit

MBR 中包含的代码搜索到可启动主分区后,将控制传递给该分区的 VBR。VBR 是一个分区的第一个扇区

VBR 的修改

VBR 会根据 BPB 结构的信息,读取操作系统的加载程序并执行。具体来讲,VBR 的 BPB 结构中的 dwHiddenSectors 字段的值,指向了系统的加载程序所在的扇区,也就是 IPL(Initial Program Loader)前有多少个扇区

VBR 会读取并运行这个参数所指向的工程序。这意味着,只要在硬盘某个空余区域写入恶意代码,再修改这个参数让其指向这段代码,就能让这段代码在 VBR 执行的时候被加载起来

Bootkit 的 VBR 布局:
木马核心技术剖析读书笔记之木马驱动加载与启动
Bootkit 的 VBR 感染后执行流程:
木马核心技术剖析读书笔记之木马驱动加载与启动

Bootkit 控制系统启动与加载驱动

木马利用 Bootkit 的核心目的,是早于系统与反病毒软件启动,进而控制系统启动的过程,绕过系统与反病毒软件的安全机制,实现自身驱动的加载。具体过程是,木马利用 MBR 或者 VBR 加载自己的代码后,首先对中断处理例程挂钩,通过监控中断处理过程,确定系统指定组件加载的时机;在系统组件加载时,针对系统的组件进行相应的挂钩监控,进而监控整个系统的启动过程

挂钩中断

MBR 和 VBR 都运行在 CPU 的 16 位实模式下,它们对硬件设备是通过 BIOS 中断调用来完成的。BIOS 中断调用是一组功能,提供 DOS 程序与一些软件(例如开机启动)去使用 IBM PC 兼容机的 BIOS 的功能。Windows 操作系统在系统引导的时候使用 BIOS 以检测并初始化硬件资源。通常,MBR 和 VBR 都使用 INT 0x13 中断来执行文件加载的过程

通过对该中断处理程序的挂钩,可以监视他们读取到的硬盘内容。当发现通过 INT 0x13 中断读取的硬盘内容是系统相应的模块,如 NTLDR 或者 BootMgr 等后,可以进一步对加载进内存的这些系统组件映像进行相应的挂钩,这是挂钩 INT 0x13 中断处理程序的目的

基本的 INT 0x13 是 BIOS 提供的磁盘基本输入输出中断调用,它可以完成磁盘的复位、读写、校验、定位、诊断、格式化等功能。但基本的 INT 0x13 中断只能采用 10 位来表示磁道,这样对于大于 8.4GB 的存储介质则不能完成读写工作

从对 Windows 系统启动过程的分析来看,不论是 Windows NT5.X 还是 Windows NT6.X 系统,刚开始都是执行在实模式,实模式 16 位代码的 I/O 操作都是依靠中断来完成,尤其是硬盘的读操作是依赖扩展 INT 0x13 中断。通过挂钩 INT 0x13 的中断处理程序,则可以监控系统启动过程中对各个系统组件的加载情况,通过对加载的系统组件执行代码进行修改,达到控制系统启动的目的

挂钩中断 INT 0x13,则需要替换中断向量表中该中断对应的处理函数地址,使得在调用中断 INT 0×13 的时候,直接调用 Bootkit 函数。实模式下,中断向量表位于内存地址 0x0 处,INT 0×13 中断向量就存放于 0×4C 地址,0×4C~0×4D 两字节的内容存储段内偏移,0×4E~0×4F 两字节存储段地址。具体的,用 Bootkit 函数的实模式段内偏移和段地址替换掉 0x4F~0x4F 处对应的值即可完成 Hook INT 0x13

木马核心技术剖析读书笔记之木马驱动加载与启动

监控系统启动

木马核心技术剖析读书笔记之木马驱动加载与启动

加载驱动

在 Windows 系统中,驱动程序通常运行在内核模式,拥有较高的权限。通常,木马的一些核心隐藏功能等都需要实现在驱动程序中才能生效。但使用系统提供的方式加载 Windows 系统驱动,一般都是通过调用 nt!NtLoadDriver 函数实现加载。即使在驱动程序不创建设备的情况,系统仍然会为该驱动创建一个驱动对象 DRIVEER_OBJECT

通过系统机制加载的驱动很容易被通过遍历 nt!PsLoadedModuleList 双向链表枚举出来。这个时候,一个没有合法数字签名的驱动很容易被认为是可疑的程序,从而导致被清除,使得木马的相应功能失效。另外一方面,随着 Windows 64 位系统的普及,它所附带的安全机制——限制未经签名的驱动加载,使得木马很难将驱动程序加载到系统中去。同时,反病毒软件的拦截,使得驱动加载也变得更加困难。但利用 Bootkit 技术可以很好地解决这些问题