摘要:本文介绍了一种针对i386以上IBM个人计算机动态改写ROM-BIOS
的方法,对于编写密钥仿真程序或调试BIOS程序有较高的实用价值。
关键词:ROM-BIOS,线性地址,逻辑地址,页目录,页表
一、问题的提出
ROM-BIOS是IBM系列兼容机的基本输入输出系统程序,其中含有磁盘、
键盘、通讯等基础功能的常规例程。在有些情况下,如调试修改过的BIOS程序,或
需要通过BIOS截获某个中断调用,就希望能够方便地改写BIOS的内容。然而,
BIOS是写在ROM当中的,不易修改。那么,是否有其它变通的办法呢?
二、80386的分页内存管理
为了达到上述目的,可以考虑80386及更高性能的处理器所采用的保护方式。
其中的分页内存管理机制提供了线性地址到逻辑地址的对应关系。大家可能都有在
WINDOWS下同时运行多个DOS进程的经验。显然,WINDOWS通过分页内
存管理为多个DOS进程提供了0-1M的逻辑地址空间,同时启动了多个V86模式
任务。所幸的是,当我们启动计算机时,只要加载了EMM386.EXE这一内存管
理驱动程序,我们就已经处在了分页内存管理的环境之中。
为了进行更深入的讨论,有必要先介绍一下80386分页内存管理的具体过程。
80386的分页部件包含两级分页管理,如图所示。页目录及页表每项均由4个字节
构成,而每一页目录及页表都为4K字节,因此,每级页表含1024项。每页内存块
大小也是4K,一个页目录可以映射1024个页表,从而映射全部4G字节的线性地
址。
当进入EMM386.EXE后,当前页目录的第一项所指的页表就是0-1M逻
辑地址空间对应的页表。该表的第一项是逻辑地址0:0-0:FFF,第二项是逻辑
地址100:0-100:FFF...最后一项是FF00:0-FF00:FFF
分别对应的线性地址页号。
三、编程实现
要得到当前页目录,可以将控制寄存器CR3去掉低12位的内容,即为当前页目
录所在的页。不过,这一线性地址在0-1M的逻辑地址中是不可见的。如果不想使用
保护模式下编程,可以考虑BIOS提供的线性地址的数据拷贝服务。中断号15H,
功能号87H。
调用参数:
入口 AH=87H
CX=拷贝字数(WORD)
ES:SI=拷贝过程中使用的全局描述表(GDT)
DB 16 DUP(0)
DW 源块字节数
DB 3 DUP(?);源块线性地址
DB 93H
DW 0
DW 目的块字节数
DB 3 DUP(?);目的块线性地址
DB 93H
DB 18 DUP(0)
出口 C=1出错
AH=0成功,=1奇偶校验错,=2被中断,=3 A20失效
下面提供一个实例,它修改页表,将最后一项(FF00:0-FF00:FFF)
重新映射到程序的RAM地址空间,并将FF00:FFB处的内容改写为‘99’的
ASCII码(在笔者所用的计算机上,该地址处为‘96’的ASCII码)然后驻
留内存。此处为BIOS时间的年号,此时再用MSD查看,会显示BIOS生产时间
为99年。若想继续修改BIOS内容,只需修改其映射的RAM地址空间。
四、结语
利用本文提供的方法,可以生成功能很强的密钥仿真程序,在ROM-BIOS区
域截取来自加密软件的读磁盘调用,从而可以获得密钥或仿真密钥。对磁盘加密软件提
出了严重的挑战。另外,利用这一方法来动态改写及调试BIOS程序也不失为一种简
单有效的方法。
├─────┤
├─────┤ │ │
│ ├──→├─────┤
├─────┤ │ 用户页面 │
├─────┤ │ 页表 │ └─────┘
┌───┐ │ 页目录 ├──→└─────┘
│CR3├──→└─────┘
└───┘
附图:80386两级分页图
2) 页式管理的地址映射
首先要说明的是页式管理完全可以在没有段式管理的基础上实现,但是为了实现保护模式和以前的内存管理模式相兼容,才不得不在段式管理的基础上实现页式管理。
这样由段式管理而映射出的线性地址(没有页式管理前即为“物理地址”)就和以前由段式管理映射出的物理地址含义不同了。线性地址的具体含义如下:
typeded struct
{
unsigned int dir:10; // 表示页面表目录的下标,该目录指向一个页面表
unsigned int page: 10; // 表示页面表的下表,该表项指向一个物理页面
unsigned int offset:12; // 在4K字节物理页面内的偏移量
}线性地址
下面详细说明页式管理的内存映射过程:
a) 在CR3寄存器中取得页面目录的基地址。
b) 以线性地址中的dir项为下标,在目录中取得相应页面表的基地址
c) 以线性地址中的page项为下标,在所得的页面表中取得相应的页面描述项。
d) 将页面描述项中给出的页面基地址与线性地址中的offset项相加得到物理地址