首页

文章

如何提取BIOS固件中的代码

发布网友 发布时间:2022-04-19 09:43

我来回答

1个回答

热心网友 时间:2022-07-15 08:30

2 逆向系统管理中断(SMI)句柄
或许有人认为应该动用“硬件分析器”来参与我们的宏伟计划,其实这是一种误解。SMI处理程序是BIOS固件的一部分,和普通的BIOS代码一样,也可以类似的从中将其反汇编出来。Pinczakko的《BIOS Disassembly Ninjutsu Uncovered 》和《Guide to Award BIOS Reverse Engineering》二书,讲述了Award and AMI BIOS逆向方面的详细情况,有兴趣的读者可以到此参考。在这里,从BIOS中转储SMI处理函数,我们有两种方法可供选择。

1. 找一个漏洞,从保护模式进入SMRAM,并将SMRAM中的所有内容,尤其是TSEG,High SMRAM和0xA0000-0xBFFFF等区域转储出来。如果BIOS没有锁定D_LCK位,可以通过Duflot和BSDaemon介绍的修改SMRAMC PCI配置寄存器的方式转储。万一BIOS锁定了SMRAM,BIOS固件看上去也无懈可击,那就只有修改BIOS,令其不会设置D_LCK位这一条路了。将修改的程序重刷回BIOS的ROM,这样在启动时,SMRAM就不会被锁定了。不过这样做首先要确定BIOS不需要数字签名(digitally signed),而且目前几乎没有主板会使用带数字签名的非EFIBIOS固件。

我想在这里有必要提一下BIOS设置D_LCK位的方法。通常情况下,BIOS都倾向于使用0xCF8/0xCFC端口,通过合法的I/O访问,设置相关的PCI配置寄存器。BIOS首先将0x8000009C写入到0xCF8的地址端口,然后再将0x1A的数值写入到0xCFC的数据端口,设置SMRAMC寄存器就可以锁定SMRAM了。

2. 还有另外一种方法,相对前者来说要简单一些,不需要访问运行时的SMRAM数据。
2.1 从BIOS开发商的网站下载最新的,或者使用闪存编程器件(Flash Programmer)从BIOS的ROM中提取固件的二进制代码。我们针对的ASUS P5Q主板就是要下载P5Q-ASUS-PRO-1613.ROM文件。
2.2 大多数的BIOS固件都包含了主BIOS模块,压缩的SMI处理句柄就位于其中,利用开发商提供的提取/解压工具打开BIOS主模块。由于ASUS BIOS是基于AMI BIOS的,我们使用AMIBIOS BIOS Mole Manipulation Utility 和MMTool.exe从中抽取主模块。在MMTool中打开下载的.ROM文件,单击“Single Link Arch BIOS”抽取模块(ID=1Bh),然后检查“In uncompressed form”的选项,最后保存,就得到了包含SMI处理句柄的主BIOS模块。
2.3 主BIOS模块抽取完成,就可以用HIEW或IDA Pro等工具开始我们的SMI反汇编之旅了。

反汇编SMI句柄

我们注意到在ASUS/AMI BIOS中使用的是一个结构体数组来描述SMI的处理函数。数组中的每一个入口项都有“$SMIxx”的签名,其中“xx”字符指明了具体的SMI处理函数。图1显示的是基于P45芯片组ASUS P5Q SE主板的AMIBIOS 8所使用的SMI分配表(SMI dispatch table)数据。

反汇编SMI分配函数

BIOS中有一个特殊的SMI分配函数,我们将其命名为“dispatch_smi”,将遍历分配表中的所有入口,并调用handle_smi_ptr指向的处理函数。如果没有任何处理函数能够响应当前的SMI中断信号,它将调用最后的$DEF例程。下面的代码就是我们从ASUS P5Q主板反汇编得到的Handle_SMI BIOS函数。

钩挂SMI处理函数

基于上述的讨论,钩挂SMI处理函数的方法也有很多,可以添加一个新的SMI处理句柄,也可以给已有的句柄打个补丁,加上新的功能。两种方法在本质上并没有多大区别,所以两种情况我们都将做必要的介绍。

1.在SMI分配表中添加我们自己的SMI处理函数。
要加入新的函数,必须先在分配表中建立一个新的入口表项,我们将其取名为“$SMIaa”,如图3所示。

该入口包含了指向默认SMI处理句柄的指针,待会儿我们将修改这个默认的处理函数。或者我们也可以在SMRAM中找一块空闲区域,放上一段shellcode,将指向默认句柄的指针替换为指向shellcode。最后还要注意,当有新的处理函数加入到分配表中之后,保存在SMRAM数据段中的SMI代码计数值也要相应的加1,保持SMI处理函数数目的一致性。
上述这个“调试”处理函数只做了一件事情,就是将SMI分配表从0x0B428:[si]拷贝到0x07000:[di]的位置,看来我们可以放心大胆的用自己的SMI代码钩挂它了。随后,我们将实现一个键盘记录程序,将其注入到这个处理函数内部。不过在我们开始新的章节之前,还是有必要先来回顾一下可以用于在用户击键时,调用记录程序的相关技术。
1. 使用I/O APIC将键盘的硬件中断(IRQ #01)导向SMI。Shawn Embleton和Sherri Sparks采用的就是I/O高级可编程中断控制器,将键盘的IRQ #01号中断导向SMI,并在SMI处理程序中捕获击键事件。
2. 采用键盘控制器数据端口访问时的I/O陷阱机制。
我们在本文中使用了不同于前者的I/O陷阱技术,该项技术最初是BIOS模拟PS/2键盘的用途,在下一章节中我们将详细的解释其工作原理。

3 SMM键盘记录程序

3.1 硬件I/O陷阱机制

实现一个内核级的键盘记录程序,方法之一是钩挂中断描述符表(IDT)中的调试陷阱#DB处理函数,并设置调试寄存器DR0-DR3,用数据端口0x60捕获系统的击键事件。类似的,我们也可以采用通过键盘I/O端口60/64陷入SMI的方法。我们参考了AMI BIOS的设计*《USB Support for AMIBIOS8》,里面有这样的一段叙述。

“2.5.4 60/64端口模拟(emulation)
该选项可以开启或者关闭60h/64h端口的陷阱功能。60h/64h端口陷阱允许BIOS为USB键盘和鼠标提供基于PS/2的完全支持,在Microsoft Windows NT操作系统和支持多语言键盘上尤为有用。该选项还为USB键盘提供了诸如键盘锁定,密码设置和扫描码选择等各项PS/2键盘的功能。”

该机制由硬件系统来完成,所以我们还要查看一下具体的硬件配置情况。好在Intel和AMD的CPU中都有I/O陷阱的相关机制。AMD开发手册《BIOS and Kernel's Developer's Guide for AMD Athlon 64 and AMD Opteron Processors》中的“SMM I/O Trap and I/O Restart”一节,和Intel手册《Intel IA-32 Architecture Software Developer's Manual》中的“I/O State Implementation and I/O INSTRUCTION RESTART”一节对该机制都有详细的介绍。
I/O陷阱机制允许陷入SMI后,在SMI处理程序内部使用IN和OUT指令来访问系统的任意I/O端口。之所以设计该机制的目的是为了在断电时,通过I/O端口来开启(power on)某些设备。除此之外,I/O陷阱当然也可以用于在SMI句柄中模拟60h/64h的键盘端口。在某种程度上说,它和上述的调试陷阱机制有些类似,用陷阱捕获对I/O端口的访问,但是并非调用OS内核的调试陷阱处理句柄,而是产生一个SMI中断,让CPU进入SMM模式,执行I/O陷阱的SMI处理函数。
当处理器陷入I/O指令,进入SMM模式时,它会将I/O指令陷入时的所有信息保存在SMM存储状态映射区(Saved State Map)的I/O状态域(I/O State Field)中,位于SMBASE+0x8000+0x7FA4的位置。图4是该区域的数据分布情况,待会儿我们的记录程序将会用到。

-设置了IO_SMI (bit 0),表示当前是一个I/O陷阱SMI。
- I/O 长度标志(bits [1:3])表示 I/O访问是byte(001b)、word(010b)或dword(100b)三者之一。
- I/O Type标志(bits [4:7])表示I/O指令的类型,IN imm(1001b),IN DX(0001b)等。
- I/O 端口(bits [16:31]),包含了当前访问的I/O端口号。

如果当前是通过IN DX指令,字节宽度来访问0x60端口, IO_SMI置位,SMM keylogger首先需要检测和更新SMM存储状态映射区中的EAX域,然后还要检测0x7FA4处的I/O状态域的值是否为0x00600013。

mov esi, SMBASE
mov ecx, dword ptr fs:[esi + 0xFFA4]
cmp ecx, 0x00600013
jnz _not_io_smi

上述是检测的简化形式,SMM keylogger还需要检测I/O状态域中I/OType和I/O Length等其他标志。因为我们是记录键盘的目的,所以只关心I/O陷阱,并不用理会I/O重启(I/O Restart)的相关设置。I/O重启和I/O陷阱构成了完整的SMI I/O处理方式,当SMM中的SMI执行完毕时,I/O重启允许IN或OUT指令从SMI中断处恢复并继续执行。
I/O陷阱机制允许我们在任意I/O端口的软硬件交互读写操作时陷入SMI的处理例程,现在关心的只是0x60数据端口,实现键盘击键时的I/O陷入的具体步骤如下:
1. 击键事件发生时,键盘控制器产生一个硬件中断,用I/O APIC将IRQ 1中断信号导向SMI的处理句柄。
2. 收到键盘中断之后,APIC调用IDT中的键盘中断处理程序,对PS/2键盘是0x93号中断向量。
3. 键盘中断处理程序通过端口0x60从键盘控制器的缓冲区中读取按键扫描码。正常情况下将清空扫描码,并将其显示在屏幕上。
4. 此时芯片组引起端口0x60的读取陷阱,产生信号通知I/O陷阱SMI。
5. 在SMM模式下,keylogger的SMI处理句柄响应SMI中断,处理I/O陷阱SMI。
6. 退出SMM时,keylogger的SMI处理句柄将结果(当前扫描码)返回给0x60端口的读取指令,交由内核的中断句柄作进一步处理。
上述的第6步操作,将扫描码返回到OS的键盘中断处理程序,在I/O陷阱和I/O APIC下的实现是有区别的。如果使用了APIC来触发SMI,SMI keylogger必须再次向键盘控制器的缓冲区中填充扫描码,以待操作系统再次读取,做进一步处理。
I/O陷阱下则是采用另外的方法。OS键盘中断处理程序使用的“IN al, 0x60”指令会引起SMM keylogger的I/O陷入,由于该IN指令产生了无穷的SMI陷入循环,将永远无法从SMM中恢复到原来的状态继续执行。此时,SMI句柄只要将IN指令的读取结果保存到AL/AX/EAX寄存器,表现得就像IN指令从来没有陷入过一样。
IA32体系,EAX寄存器位于SMRAM存储状态区偏移为0x7FD0的位置,即 SMBASE +0x8000+0x7FD0,在IA64下为SMBASE + 0x8000+0x7F5C。因此当上述的IO_SMI置位时,SMM keylogger需要将从0x60端口读取的扫描码更新至EAX域,下面就是更新EAX域的代码片段:

; 1.验证读取0x60端口时设置的IO_SMI位
; 2.更新SMM存储状态区的EAX域(SMBASE + 0x8000 + 0x7FD0)
mov esi, SMBASE
mov ecx, dword ptr fs:[esi + 0xFFA4]
cmp ecx, 0x00600013
jnz _not_io_smi
mov byte ptr fs:[esi + 0xFFD0], al

3.5 多处理器下的keylogger说明

我们的keylogger已经更新了系统SMRAM存储状态映射区中的EAX(RAX)寄存器,要是碰到了多处理器系统那又该怎么办呢?当多个逻辑处理器同时进入SMM模式时,它们在SMRAM中都要有自己的SMM存储状态映射区,这将由BIOS为每个处理器分配不同的SMRAM 基地址(SMBASE)来妥善解决,因此该项技术也被称为“SMBASE重定向”。
例如在双处理器系统中,两个逻辑处理器分别具有不同的SMBASE,SMBASE0和SMBASE0+0x300;第一个处理器的SMI处理句柄将从EIP = SMBASE0+0x8000处开始执行,而第二个则从EIP = SMBASE0+0x8000+0x300的地方开始;同理,它们各自的存储状态映射区也就分别位于(SMBASE0+0x8000+0x7F00)和(SMBASE0+0x8000+0x7F00+0x300)。
不只是0x300,BIOS也会为额外的处理器设置其他的SMBASE增量偏移。增量偏移虽然可变,但是其计算过程也不算复杂。在SMM存储状态映射区内部0x7EFC偏移处包含了一个SMM修正ID(Revision ID),对每个处理器来说都是同样的数值。例如SMM的修正ID可能为0x30100,在SMRAM中找到各处理器的修正ID,计算它们之间的差值也就得到了各SMBASE间的相对位移。
下面我们展示的是SMM keylogger在双处理器系统上的EAX更新代码。它将顺次检查I/O状态域是否和某个处理器的I/O陷阱匹配,确定的话则更新其SMM存储状态映射区中的EAX值。

; 在双处理器系统上更新EAX
mov esi, SMBASE
lea ecx, dword ptr [esi + SMM_MAP_IO_STATE_INFO]
cmp ecx, IOSMI_IN_60_BYTE
jne _skip_proc0:
mov byte ptr [esi + SMM_MAP_EAX], al

_skip_proc0:
lea ecx, dword ptr [esi + SMM_MAP_IO_STATE_INFO + 0x300]
cmp ecx, IOSMI_IN_60_BYTE
jne _skip_proc1:
mov byte ptr [esi + SMM_MAP_EAX + 0x300], al

_skip_proc1:


4 建议的检测方法

4.1 I/O陷阱机制检测
4.2 计时(timing)检测
ups快递客服电话24小时 贷款记录在征信保留几年? 安徽徽商城有限公司公司简介 安徽省徽商集团新能源股份有限公司基本情况 安徽省徽商集团有限公司经营理念 2019哈尔滨煤气费怎么有税? 快手删除的作品如何恢复 体育理念体育理念 有关体育的格言和理念 什么是体育理念 万里挑一算彩礼还是见面礼 绿萝扦插多少天后发芽 绿萝扦插多久发芽 扦插绿萝多久发芽 炖牛排骨的做法和配料 网络诈骗定罪标准揭秘 “流水不争先”是什么意思? mc中钻石装备怎么做 为什么我的MC里的钻石块是这样的?我想要那种。是不是版本的问题?如果是... 带“偷儿”的诗句 “君不见巴丘古城如培塿”的出处是哪里 带“奈何”的诗句大全(229句) 里翁行()拼音版、注音及读音 带“不虑”的诗句 “鲁肃当年万人守”的出处是哪里 无尘防尘棚 进出口报关流程,越详细越好。谢谢大家指教。 双线桥不是看化合价升多少就标多少的吗?为什么CL2+2KI=2KCL+I2中I失... 出师表高锰酸钾有画面了吗 2021年幼儿园新学期致家长一封信 电脑屏幕一条黑线怎么办? 销售代理商销售代理商的特点 商业代理商业代理的特征 如何看微信有没有开通微众银行 为什么微众没有开户 微众银行怎么开户 微众银行APP开户流程是什么? 唐古拉山海拔唐古拉山海拔是多少 怎么看待取消跳广场舞的人的退休金 如何选购新鲜的蓝田水柿? 恭城水柿柿树作用 创维洗衣机使用教程 创维全自动洗衣机怎么使用 自动开门器 狗羊属相婚姻相配吗 3岁的小孩不会说话怎么办 3岁孩子不会说话,应该挂什么科? 3岁小孩不会说话正常吗 鹿茸炖乌鸡怎么做? 新型冠状肺炎吃什么药可以预防 冰箱上电后一直响 食品生产许可证编号开头为“ G”。 电脑固件中UX325JA UEFI出现感叹号要不要维修? 如何向ios固件中注入cydia 魅族固件升级过程中,固件损坏怎么办? 为什么iOS固件中的某些文件不能被打开? 求大神,apm 飞控刷入固件中,出现这个怎么解决 固件中的软件设置怎样更改? 怎么改固件中的 mac地址 怎么该5530刷机固件中的默认主题图标? 影驰固态硬盘升级固件无效? 提示升级成功 重启以后固件还是旧版本?怎么办. 无法安装Microsoft Defender应用程序防护? 404 Not Found win8.1怎么解决无法安装hyoer-v该固件中的虚拟化支持被禁用 银行系统异常怎么回事? 忘记路由器密码怎么办 路由器忘记了密码登录不上怎么办 路由器忘记密码怎么重新设置 家用路由器忘记密码怎么办 哪些专业的人员适合学习嵌入式linux? 纯软件开发人员怎样做嵌入式linux应用开发 工信部嵌入式工程师证书什么时候考试 魅族固件升级过程中,固件损坏怎么办 怎么在固件中固化软件———— 如何从一个固件中提取ipk安装包 如何将一个现成的ipk加入到openwrt编译出的固件中 路由器怎么升级固件 手机固件是什么东西 银行系统异常是什么原因 银行贷款年利率是多少 银行贷款最多可以贷多少年 银行贷款年化利率是多少 请问银行贷款年化利率是什么意思怎么计算? 银行贷款年化利率怎么计算? 银行个人贷款最长贷多少年 四大银行贷款年利率是多少 银行贷款的年化和利息怎么计算? 银行贷款年利率是指什么? 银行贷款年化率怎么算 请问,银行贷款是怎么计算年化率和年利率的? 银行贷款最长期限是多少年 银行的贷款利息是按照年算还是月算还是天算
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com