[译]修改 ThinkPad 的 BIOS

原文地址:http://www.endeer.cz/bios.tools/thinkpad-biosmod.html

需要的工具:
– phcomp.exe(Phoenix Technologies 公司)—— 用于对联想提供的 BIOS 镜像进行解压以及后续的压缩。
– phnxdeco.exe(作者 Anthony Borisow,需要 cygwin1.dll)—— 从 BIOS 映像中分离出各个模块。
– IDA 反汇编器 —— 至少可以用略微可读的方式看机器代码。
– 十六进制编辑器(如果没有的话,可以选择 EditPad Pro)。
– 如果能有一个虚拟软盘驱动器,来修改 BIOS 映像,比如 Cenatek RAM Disk NT 1.5(可惜 Cenatek 已经不提供了,被新版本取代了,似乎不支持软盘驱动器)。

那么现在就可以下载某个 BIOS 更新了,比方说 ThinkPad T40-T42 ver. 3.23,然后让它解压到软盘上。取以 FL1 结尾的文件,大小应该在一兆左右,在我们的例子中是 $018F000.FL1。使用 phcomp.exe /d $018F000.FL1 解压它,应该输出 $018F000.FLh,将其重命名为 bios.rom,后文会引用此名字。使用 phnxdeco bios.rom -x 从 BIOS 映像中分离和解压各个模块,会有一些名如 phoenix0.B# 的文件,其中 # 是一个数字,从 0 到或 4 或 5 或 6。这些文件是 BiosCode 模块,很可能包含白名单。

可以在文件中搜索已知的厂商 ID,比如十六进制的 8680(Intel)。在哪个同一文件中找到这个序列的次数多,哪个文件就是我们要找的。在这儿这个特定的 BIOS 里,它是 phoenix0.B1,BiosCode1。

现在打开 IDA 反编译器,加载这个文件。会说是未知文件,确认反编译。当问到是否使用 32 位模式时,选 no,因为 BIOS 大多以 16 位模式运行。现在它会尝试反编译这个文件。如果你看到到处都只有 db XXh,就到开头的随便一行,一直按住 alt+c 一会儿。它将尽力而为。

现在你就可以看到一些指令了,比如这个(IDA 的高亮部分)。

这个例程要调用 0F000h:517Dh 处的某个函数提供的 4×2 个字节的数据,与存储在 di 寄存器指向的地址的一组 8 字节序列进行比较。这是一个循环,在 loc_B8B 处我们可以看到 di 是如何被递增的(移动指针到下一个条目,8 个字节加 1 个用于分割的字节 0),然后跳回尝试下一个。前两条指令然后检查是否遇到了表示列表结束的 0,如果是的话,然后 stc 并转到 loc_B90,从栈中加载原始寄存器内容并返回。stc 很重要,因为它基本上是用来返回一个值的,它将 CF 寄存器位设为 1,反之则是 clc,会将其设为 0。还有另一个跳转会跳到 loc_B90return),那是在调用 clc 之后。

其实,在这个函数返回后,di 寄存器仍然指向卡的 device/subsystem ID,但我尝试过跟踪代码,好像没有在其他地方再有检查。现在,我们来试着把 stc(十六进制 F9)改成 clc(十六进制 F8)。高亮显示 stc 指令,然后切换标签到十六进制视图。复制 F9 指令周围的几个字节,并在主 BIOS 映像即 bios.rom 中搜索它们。在十六进制编辑器中打开它,确保在整个文件中只有一个匹配 —— 如果不是,那就从 IDA 反汇编器中取更多的字节。当找到它的时候,只需要在正确的地方将十六进制值 F9 修改为 F8,这样就可以使函数总是返回 CF=0

现在要重新计算校验和。找到修改后的字节的准确位置,在我的例子中是十六进制 47670(十进制 292464)。计算除以 4 的余数(292464 mod 4 = 0),写下结果。在 bios.rom 文件中找到文本 EXTD。它后面应该有四个看似随机的字节,把它们看作是编号为 0、1、2、3 的字节。选择余数对应的字节,将字节值加 1。这是因为校验和的计算方法是将所有四个字节的数字相加后,结果为零。你把 F9 改成了 F8,减少了 1,所以要恢复校验和,就必须把相应的数字加 1。

这就完成了。用 phcomp.exe bios.rom 压缩它,得到了一个修改后的 ROM(phcomp 保存为 bios.ro2),回到 BIOS 更新软盘中,用它替换掉原来的 $018F000.FL1 文件。如果一切顺利的话,应该和这个存档里的文件是一样的(针对开头提到的 3.23 ThinkPad T40-T42 BIOS)。

发表评论

邮箱地址不会被公开。 必填项已用*标注