ThinkPad T440p BIOS 修改刷写实录

玩机的朋友们都知道,除非迫不得已,谁会想要去折腾 BIOS?但由于万恶的白名单机制的存在,很多人都会只是想要能够换一个好一点的无线网卡,就必须要经离着手于 BIOS 搏斗的痛苦。老夫经手过两台 ThinkPad T440p,第一台到手时,上家已经把能搞的搞了个差不多了。老夫只是安装了一下黑苹果,后来觉得没用就出掉了。结果没过几天,又想有一台可以编译 Android 源码的机器,就又搞了一台回来。这第二台的成色比较一般,后来编译的活儿没多少了想出掉,也没有人买,一直绝大部分吃灰到现在。前几天拿出来用了一下,内置无线网卡突然疯狂掉线,就把修改 BIOS 移除白名单的事情又想起来了,终于在网上搜索了一番资料后与昨日动手。整整一个下午,连操作带记录,索性前期准备充分,一路虽繁杂却顺利,没有任何返工操作,也没有任何流程失误,这对于非常在意“一次成功率”的老夫而言,非常满意。把记录附于此,以备查检。

ThinkPad T440p 去除白名单操作记录

〇、准备部分。

1. 购置编程器、免拆烧录夹;
2. 在另一台 Windows 10 系统的电脑上插入编程器,安装驱动。驱动在 http://www.winwin7.com/soft/7288.html 处下载,是一个可执行文件,双击执行,可以看到是带有下载站标志的封装 exe,唯恐其夹带私货,退出后用 7z 解压,在 .inf 文件上右键菜单选安装,安装完毕;
3. 安装编程器软件。在 https://khandishnetwork.com/dl/neoprogrammer-new-update-v2-2-0-10-15-10-2021/ 处下载,解压后即可使用;
4. 备份出厂 BIOS。这是首次实战免拆夹子,之前只看过图片。要注意夹子方向:夹子上的红色线要与芯片上的 1 号引脚凹陷指示对应;T440p 的 BIOS 芯片型号为 Winbond 25Q32FVS1Q,是以 25 打头的系列,注意与编程器板子背面的区域对应,将夹子的这端经由转接板插入编程器的插座,红色 1 号线对应固定板手的方向,然后把扳手扳下。这时到编程器软件中,执行检测操作,应该可以检测到芯片;否则调整以上操作步骤。读取芯片内容,长度为 4194304,正好 4MB。为了防止夹子不稳,读取有紊乱,连续读取了三次并均保存为文件,用 Windows 10 自带命令 certutil.exe /hashfile BIOS-Stock-T440p.bin md5 得出三个文件的 MD5 都是 e0a80f51658343775ae2e41785b36ac9,完全一致,理应无误;
5. 处理 BIOS 文件。需要用到两类工具,一是 BIOS 分析工具,二是十六进制搜索编辑工具。根据资料,前者有 PhoenixTool 和 UEFITool,后者有 Xsearch 和 HxD,等等。本次决定试试没有实战过的 UEFITool(https://github.com/LongSoft/UEFITool/releases)。要注意,UEFITool 有新老两个引擎的迭代变化,目前还在演进着的采用新引擎的 NE 版本都没有编辑功能了,应该下载老的版本如 0.21.5 的才好执行后面的操作。当然,新版本可能在界面信息呈现上有改进,所以老夫两个都放到手边备用,后文叙述在必要处会加 NE 字样明示。

确定几个目标:移除白名单,优先考虑代码修改,而不是 ID 替换;打开高级菜单(据说需要先到 BIOS 里关闭 AT Module 和 Security Chip,后续操作证明没有必要);不触发开机时的 BIOS 被篡改的告警。

一、首先是移除白名单。

根据 https://www.ibmnb.com/thread-1916046-1-1.html 一步步操作的记录。

先用 UEFITool 打开备份出来的 BIOS 文件 BIOS-Stock-T440p.bin,找到 LenovoWmaPolicyDxe,把 PE32 Image 提取出来,随便命名为 LenovoWmaPolicyDxe.dll

用 IDA Pro 打开提取出的文件。IDA 自动识别文件格式,不用改其他东西,直接点 OK。

进入 Options->General 设置,将 opcode 宽度设置为 16,这样反汇编界面就会显示 hex 数据了。

按 F5,进入 C 语言伪代码视图。函数 sub_710 就是打印错误信息的函数(Unauthorized network card is plugged in – Power off and remove the network card)。

由于本地情况与帖子里完全一致,故此处的分析步骤均从略。

最终要做的就是,关闭 IDA Pro(无需保存),用 HxD 打开 LenovoWmaPolicyDxe.dll,定位到偏移 08A8 处,将 E8 63 FE FF FF 修改为 E9 98 00 00 00,保存。

将改好的文件用 UEFITool 替换(Replace body)回去保存(要注意用老版本的如 0.21.5 的才可以)。

如果后续的功能无所谓,此时就可以用编程器把此 BIOS 刷回去了。

二、接下来还要打开高级菜单。

根据 https://www.ibmnb.com/thread-1888819-1-1.html 操作。

用 UEFITool 打开 BIOS 文件,搜索 04320B483CC2E14ABB16A73FADDA475F 这段内容。

双击搜出来的 offset 为 404h 的那条结果,定位到具体的模块代码。把 PE32 image section 用 Extract body 导出,命名为 SystemFormBrowserCoreDxe.dll

用 HxD 打开 SystemFormBrowserCoreDxe.dll,再次搜索 04320B483CC2E14ABB16A73FADDA475F,定位到具体的位置,确定完全一致后,将之替换为 778B1D826D24964E8E103467D56AB1BA(根据 leokim 大神修改 BIOS 的 patch 里面修改的内容,高级菜单这部分应该就是硬编码替换)。确定替换无误,保存。

将改好的文件用 UEFITool 替换(Replace body)回去保存。

如果后续的功能无所谓,此时就可以用编程器把此 BIOS 刷回去了。

三、最后要重建签名。

根据 https://www.ibmnb.com/thread-1899231-1-1.html 中引用的 https://www.insanelymac.com/forum/topic/337333-guide-fix-insyde-h2o-bios-signature-5-beeps-on-lenovo/ 操作。

用 HxD 打开修改后的 BIOS 文件,搜索 TCPABIOS 字样,即可定位到以 TCPABIOS 起始(含)而以 TCPACPUH 结束(不含)的一个块。

以上分作 4 段,对应于原帖,用灰、红、蓝、绿来指称。灰段为名字及块信息,红段为卷(Volume)信息(校验和以及头),红段事实上是一个列表,蓝段为列表的终止条目以及块签名(此段的理解为本人所发,与原贴的描述有所出入);绿段为最后的 128 字节,也就是 TCPABIOS 块的签名。

红段在本例中仅有一个卷的信息,事实上可以有一系列的卷,每个卷以一个字节的顺序索引值(以 0 为基)加 FD 27 形成的三字节前缀为起始。具体一条卷信息的格式是,前缀(3 字节)+ 校验和(20 字节)+ 偏移(4 字节)+ 卷大小(6 字节)+ 终止分隔符(6 字节)

我们需要修正的有:校验和、偏移、大小。

用 UEFITool NE 版打开原始以及改后的两个 BIOS 文件,定位到 EfiFirmwareFileSystemGuid 下的 File 类型的子节点,可以在右侧的信息窗内看到 Offset 都是 48h,但 Full size 一个是 2436AFh (2373295),新的是 240CBFh (2362559),这个数值后面要用到。

将修改后的 BIOS 文件中的上述 File 类型的子节点用其右键菜单中的 Extract as is 导出为文件,命名为 sig-vol-modified.ffs(出于谨慎,原始 BIOS 文件中的相同节点也导出了一份,命名为 sig-vol-stock.ffs),计算其 SHA1 的哈希值(原帖过于老旧,使用的工具是目前已经无法在微软官网下载的 fciv.exe 工具,弃之),命令行为 certutil /hashfile sig-vol-modified.ffs sha1,得到 9ab3efcbbc10d63cf1c4bf5bcd6f21f80d430e6c。用此值覆盖卷信息中原有的校验和。

出于谨慎,也计算了对应的原始卷 sig-vol-stock.ffs 的哈希为 145730e525115b4c5d0080133ae74b053a54eced,跟上面块中的原始校验和信息对不上,引发思考。

经过重新审视,发现原帖中,卷信息中所记录的,确实是 Volume 下的 File 节点的相关信息,所以偏移才会是 48h,而本次实际提取的信息中(见上),00 FD 27 条目中的偏移是 00h,且大小是 2B0000h。故,又做了验证,不是将 File 子节点导出,而是将 Volume 节点用 Extract as is 导出为文件,经计算,其 SHA1 的哈希值为 57fb4be3e31143bcea207d4dc0dc32754734b8d0,这就对上了。由此得出结论,前述新哈希需要重新导出 Volume 并重新计算。正确的值应该为 8146c348765ee30b6d3cf1db61d6b7453575a4fb

(如果不止一个卷的话,每个卷都要做此更新操作)

接下来要生成整个 TCPABIOS 块(除去最后 131 个字节,也即蓝段的最后 3 个字节 FF FF 83 和绿段)的校验和。实际内容也就是,

将此内容存为一个名为 tcpabios-block-raw-new.bin 的文件,并得出其 SHA1 值 963df979be5dae727082f9a797ab51a50f7e809d。新建一个 128 字节的全 00 文件,将新的 SHA1 值覆盖最末尾的 20 字节,保存为 tcpabios-block-raw-new.hash

——————————————————————————–

接下来的跟 OpenSSL 有关了。本机没有 OpenSSL,突然想起已经 Windows 10,就盲敲了个 winget install openssl,没用;网上说的 winget install -e --id ShiningLight.OpenSSL 也没用。后来就用 git 自带的了,在 C:\Program Files\Git\mingw64\bin 下。

——————————————————————————–

先执行 openssl genrsa -3 -out bios_key.pem 1024 成功,然后用 bios_key.pem 来签署 tcpabios-block-raw-new.hashopenssl rsautl -inkey bios_key.pem -sign -in tcpabios-block-raw-new.hash -raw > tcpabios-block-raw-new.hash.sign

接着把公钥生成出,openssl rsa -in bios_key.pem -outform der -pubout -out bios_key_pub.der。再生成公钥的 modulus 3,openssl rsa -pubin -inform der -in bios_key_pub.der -text -noout,结果如下:

把上面的内容整理为这么一行:00c3acfb333f5caa6d8d632980277113c7e812ec31a9b23df8e49c49d42812a5b9ab3d6703488353aa4e3d71f88d436f57f5f70862e13fa36d7dded477397b612c6ba2986686b793d3e4eecfed378c8804005c03c820733d25e8c2713383d79543d2c670a158066cf3708ceb448a412c1c74c540b2ef307db716e54440400afac9

在 HxD 中,把 tcpabios-block-raw-new.hash.sign 文件的内容复制到 BIOS 文件 TCPABIOS 块的尾部,也就是逐字节覆盖 FF FF 83 后的 128 字节内容。

现在来定位 BIOS 中公钥的位置,并替换掉它。此公钥位于 TCPABBLK 块之后,以 12 04 开始,01 03 FF 结束。也即形如,12 04 + 129 个字节 + 01 03 FF

3B4515h 偏移处找到,见下:

用上面最后整理成的那一整行把 12 0401 03 FF 之间的内容覆盖,保存即可。按说,此 BIOS 文件即可无恙刷入了。

最后的结果证明,一次成功。按下开机键,看到熟悉的 POST 屏幕上的 ThinkPad 字样,连一声嘀响都没有听到,彷佛什么都没有发生,只是 F1 进入后,已经可以看到 Advanced 菜单了,它展示着,还是有些什么发生了的。

后来找到一个仓库,用 Python 写的 hash 重建工具,没有使用过,链接留在此处备用:https://github.com/ValdikSS/thinkpad-shahash


除文中引用的各个链接,还有一些参考资料,附录如下。

– http://www.smxdiy.com/thread-1195-1-1.html;内有一个 CH341A 烧录软件的链接以及基本使用说明,据说比硬件卖家提供的好用;据另外的帖子(https://baijiahao.baidu.com/s?id=1752088033565259887)说,叫 NeoProgrammer 的软件也很好用,博主后来直接使用了后者;
– https://www.zzmark.top/2021/01/id_3075796319/;分享了 E440 的白名单去除过程(ID 替换法,有反编译以及查找替换的步骤);使用到了 UEFITool 和 HxD;
– https://zhuanlan.zhihu.com/p/25568937;介绍了用 PhoenixTool、XSearch、WinHex 修改 E540 BIOS 去除白名单的修改步骤(ID 替换法);
– https://bbs.pcbeta.com/viewthread-1754676-1-1.html;也是介绍 E540 的,有一个夹子夹芯片的清晰图;
– https://post.smzdm.com/p/a07n2w9w/;图文并茂的 T440p BIOS 修改刷写教程;
– https://tieba.baidu.com/p/6103207732;编程器和烧录夹使用的图文讲解;

上面这些方法都没有管开机校验失败后会连续滴滴响的问题,但博主前文中已经据 51nb/ibmnb 论坛上的探讨帖搞定。

发表回复

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