BIOS Rootkit实现分析与检测技术研究系列之--IVT Hook 1
本节目录
1. 引言
2. IVT和IVT Hook介绍
3. 使用Bochs调试BIOS
4. 小结
引言
BIOS Rootkit为了达到控制系统流程的目的,一般会采用Hook IVT,即Hook中断向量表的方式来实现。IVT Hook的实现和检测,涉及许多具体的问题。因此,我把IVT Hook分几部分来进行讨论。在本节和下面几节中,我们将讨论如何借助Bochs的帮助来查看原始IVT、分析IVT Hook情况以及在此基础上写一个简单的IVT检测程序。闲话少说,这就开始我们的旅程吧。
IVT和IVT Hook介绍
1. 什么是IVT
IVT(Interrupt Vector Table)即中断向量表。对于IVT的详细解释,这里主要参考了Intel 公司的《Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide》、王爽先生的《汇编语言(第二版)》和张银奎先生的著作《软件调试》(书很厚,但物超所值)。具体描述可以参见上述著作。
由于BIOS Rootkit存在于BIOS中,其初始运行环境为实模式。所以,我们讨论的IVT以及IVT Hook,都是针对实模式下的IVT来进行的。
好,首先我们回忆一下:什么是中断?CPU在执行指令时因为检测到预先定义的某个(或多个)条件而产生的同步事件(如除法指令的除零错误),大部分书籍称之为内中断(《软件调试》一书详细阐述了中断和异常的区别)。
CPU收到中断信息后,需要对中断信息进行处理,而用来处理中断信息的程序称为中断处理程序。所谓中断向量就是中断处理程序的入口地址,而中断向量表(IVT)就是中断处理程序入口地址的列表。可以看到,IVT就是一个入口地址表,如同Windows内核中的SSDT一样。对其进行Hook的方法与Hook SSDT类似。而Hook的目的,就是控制中断处理流程,进而控制系统的运行。
IA-32架构规定,在实模式(Real Mode)下,IVT在内存中保存,起始地址为0。从内存0000:0000到0000:03FF的1024个内存单元中存放着中断向量表(IVT)。下图来自《Intel 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide》:
偷个懒,直接把《软件调试》上的相关描述进行引述,原文描述参见上面Intel的文献:
中断调用采用int n的形式,n 代表中断向量号(n=1,2,3……)。这样通过n*4这样的计算,可以迅速定位到各个中断号对应的内存地址。n*4+2存放的是中断向量的段地址,n*4存放的是中断向量的偏移地址(实模式下的汇编程序设计请参考文献)。这样IVT的1024个内存单元总共可以存放256个中断向量。
对于中断过程的执行步骤,描述如下:
1)将代码段寄存器CS和指令指针寄存器(EIP)的低16位(IP)压入堆栈。
2)将标志寄存器EFLAGS的低16位(FLAGS)压入堆栈。
3)清除标志寄存器的IF标志,以禁止其他中断。
4)清除标志寄存器的TF(Trap Flag)、RF(Resume Flag)、AC(Alignment Check)标志。
5)使用向量号n作为索引,在IVT中找到对应的表项(n*4+IVT表基地址)。
6)将表项中的段地址和偏移地址分别装入CS和IP寄存器中,并开始执行对应的代码。
7)中断例程总是以IRET指令结束。IRET指令会从堆栈中弹出前面保存的CS、IP和标志寄存器值,然后返回执行被中断的程序。
2. IVT Hook
如果在第6个步骤,把我们自行设计的程序所在的段地址和偏移地址装入CS和IP寄存器中,CPU将会运行我们的程序。这就是IVT Hook的理论基础。这里的Hook技术和传统Hook的概念没有任何区别。
使用Bochs调试BIOS
在进行IVT Hook实例分析之前,先说一下我使用Bochs进行BIOS调试的一些体会,这也是进行后续讨论的实践前提。
这个系列的《简单ISA模块编写》一篇中,曾提醒大家进行BIOS刷写实验存在一定的风险。的确,一个程序编写上的小错误,或者刷新过程中电压的不稳定等等因素,都可能造成刷写的失败。而失败的结果往往都是不能正常引导计算机启动,即无法开机。在实验过程中,我把BIOS刷坏,开始都是抱去电脑维修店进行维修。对于刷写BIOS服务,我们那的当地价是30块钱刷一片,50块刷两儿。刷的时候还要求你连主板一起也拆了去。费钱、费力、费时间。于是,我在淘宝上邮购了一套硬件刷写BIOS的编程器,问题多多,一二百的编程器还是不能和维修店里的一二千的相比。刷写无数次失败后,我决定找到一种价廉物美的实验方法。第一个感觉就是:虚拟机。
早就听说现在的虚拟机对BIOS能够进行仿真操作,先后从网上收集资料,然后自己实验比较。实验发现,对于主流的VMWare、VirtualPC,对于BIOS实验较为困难。如VMWare的BIOS定制很麻烦,而且缺少通用性。因为和本节内容关系不大,所以具体细节以后有时间补上。众里寻他千百度,终于,第一次感受到了Bochs的强大。
Bochs是很出名,这里不多介绍。大家平时多用Bochs进行操作系统的调试,进行BIOS调试的时候可能相对较少。这里,我说说对BIOS调试的体会。这里我使用的Bochs版本为v2.3.7,在其帮助文档中,我们可以发现:optromimage 选项(It's amazing!)。这个选项允许我们对最多4个附加BIOS模块(如ISA模块)进行测试(当然包括调试),分别记为:optromimage1、optromimage2、optromimage3、optromimage4。下面是帮助原文:
-------------------------------------------------------------------------------------------
Example: optromimage1: file=optionalrom.bin, address=0xd0000
This enables Bochs to load up to 4 optional ROM images.
Be sure to use a read-only area, typically between C8000 and EFFFF. These optional ROM images should not overwrite the rombios (located at F0000-FFFFF) and the videobios (located at C0000-C7FFF).
Those ROM images will be initialized by the BIOS if they contain the right signature (0x55AA).
It can also be a convenient way to upload some arbitrary code/data in the simulation, that can be retrieved by the boot loader
-------------------------------------------------------------------------------------------
这个选项应写在.bxrc配置文件中。帮助中建议我们把附加模块的加载地址设定在C8000 和EFFFF之间,大家可以对照《简单ISA模块编写》一篇中的BIOS内存分布图来理解。其实,经过摸索发现,Bochs指对设定在0xd0000~0xe0000范围之间的附加模块能够提供很好的支持,而其他范围基本都以失败告终。另外,大家还要注意一点就是:我们设计的附加模块(如ISA模块),除了本身大小应为512字节的倍数外,还要注意optromimage的支持范围,即0xd0000~0xe0000。这个范围大小为64K,因此如果你的附加模块总量,即最多4个附加模块的总大小不能超过64K。否则,Bochs会出现错误提示,并只会顺序调用在范围内的一个或几个模块。这个问题曾困扰我很久,后来反复研究optromimage的帮助终于明白。希望能给大家在做类似工作时有所帮助。
这样我们就可以把《简单ISA模块编写》一篇中提到的登录框程序,用Bochs来运行一下。配置文件相关选项就这样写:
--------------------------------------------------------------------
# filename of ROM images
romimage: file=../BIOS-bochs-latest
optromimage1: file=ISAOEM_NASM.bin, address=0xd0000
vgaromimage: file=../VGABIOS-lgpl-latest
--------------------------------------------------------------------
这里除了我们刚刚介绍过的optromimage,还有romimage和vgaromimage。romimage允许你替换整个BIOS文件,这对特定BIOS Rootkit的编写有用,如Kris提到的直接修改BIOS入口的跳转指令:jmp xxxx,xxxx换成我们的程序入口。这个问题可以单独进行讨论。vgaromimage选项允许进行显卡BIOS的调试。下一步进行显卡BIOS Rootkit研究时,可能要借助它的帮忙。:)
Bochs的调试命令和方法这里不多介绍,大家可以参阅Bochs的帮助文件。把我们的登录框程序和修改了的.bxrc配置文件放在同一目录下,运行后,我们会发现登录框程序运行。由于Bochs对于图形显示支持还不是很好,所以在Bochs中,你会发现提示输入密码的字符串没能很好显示,但这并不影响我们对功能的调试。效果图就不附上了。
小结
这一节我们对实模式下的IVT和IVT Hook进行了理论的铺垫,并对用Bochs进行BIOS调试的一些细节进行了探讨。在下一节中,我们来实际分析一下IVT Hook的应用。
待续...