面包- BIOS逆向工程和高级调试

taibeihacker

Moderator
面包(BIOS逆向工程高级调试)是一种“可注射的”房地机X86调试器,可以通过串行电缆从另一台PC上调试任意房地模式(在实际HW上)。

Introduction​

面包出现了许多失败的试图逆转工程遗产BIOS的尝试。鉴于绝大多数(如果不是全部)使用拆卸器在静态上进行分析,因此了解BIOS变得非常困难,因为没有办法知道给定代码中的寄存器或内存的价值。
尽管这样做,但面包也可以在房地产模式中调试任意代码,例如可引导代码或DOS程序。

How it works?​

此调试器分为两个部分:调试器(完全以汇编并在被调试的硬件上运行)和桥梁,用C编写并在Linux上运行。
调试器是用16位实机编写的可注射代码,可以放置在BIOS ROM或任何其他房地产代码中。执行后,它设置了适当的中断处理程序,将处理器放在单步模式下,并在串行端口上等待命令。
另一方面,桥是调试器和GDB之间的联系。该桥通过TCP与GDB通信,并通过串行端口向调试器转发请求/响应。桥背后的想法是删除GDB数据包的复杂性,并建立一个更简单的协议以与机器通信。此外,更简单的协议使最终代码大小较小,从而使调试器更容易注入各种不同的环境中。
如下图:所示
+-----------+简单数据包+---------------+GDB数据包+------------+
| | ------------------- | | ------------------- | |
| DBG | |桥梁| | GDB |
|(真正的HW)| ----------------- | (Linux)| ------------------- | (Linux)|
+ ----------+串行+ -----------+ TCP+ -------------+

Features​

通过实现GDB存根,面包具有许多开箱即用的功能。支持以下命令:
读取内存(通过x,dump,查找和相关性)编写内存(通过集合,还原和关联)读取和写入寄存器单步(si,step)和继续(c,contine)断点(b,break)1硬件观察点(观看及其兄弟姐妹)2 3010-2 3

Limitations​

有多少人?是的。由于被调试的代码尚未意识到它正在调试,因此它可以以多种方式干扰调试器,以命名几个:
受保护模式跳跃:如果调试代码切换到受保护模式,则更改了中断处理程序的结构,并且在代码的那个时候将不再调用调试器。但是,跳回实际模式(恢复完整的先前状态)可能会使调试器再次工作。
IDT更改:如果出于任何原因更改了IDT或其基本地址,则将无法正确调用调试器处理程序。
Stack:面包使用堆栈,并假设它存在!它不应插入尚未配置堆栈的位置。
对于BIOS调试,还有其他限制,例如:从一开始就不可能调试BIOS代码(BootBlock),因为面包正常运行需要最小设置(例如RAM)。但是,可以通过将CS:EIP设置为F000:FFF0来执行“温暖重启”。在这种情况下,可以再次遵循BIOS初始化,因为面包已经正确加载。请注意,温暖重新启动过程中BIOS初始化的“代码路径”可能与冷启动可能不同,并且执行流可能并不完全相同。

Building​

建筑物仅需要GNU品牌,即C编译器(例如GCC,Clang或TCC),NASM和Linux机器。
调试器具有两种操作模式:轮询(默认)和基于中断的:

Polling mode​

轮询模式是最简单的方法,应该在各种环境中效果很好。但是,由于投票性质,CPU使用率很高:

Building​

$ git克隆3https://github.com/theldus/bread.git
$ CD面包/
$ MAKE

Interrupt-based mode​

基于中断的模式通过利用UART中断来接收新数据,而不是不断对其进行轮询,从而优化了CPU利用率。这导致CPU保持在“停止”状态,直到从调试器接收命令,从而阻止其消耗CPU资源的100%。但是,由于并非总是启用中断,因此未设置此模式为默认选项:

Building​

$ git克隆3https://github.com/theldus/bread.git
$ CD面包/
$ make uart_polling=no

Usage​

使用面包只需要串行电缆(是的,您的主板hascom标头,检查手册)并在适当的位置注入代码。
要注射,必须在DBG.ASM(调试器的SRC)中进行最小的更改。必须更改代码的“ org”,以及代码应如何返回(在代码中查找需要更改的位置的'change_here')。

For BIOS (e.g., AMI Legacy):​

以AMI遗产为例,将调试器模块放置在BIOS徽标(0x108200或FFFF:8210)的位置,并且ROM中的以下说明已替换为Module3:
.
00017EF2 06推动ES
00017EF3 1E推DS
00017EF4 07 POP ES
00017EF5 8BD8 MOV BX,AX-┐替换为: CALL 0XFFFF3:0X8210(dbg.bin)
00017EF7 B8024F MOV AX,0x4F02-┘
00017EFA CD10 INT0x10
00017EFC 07 POP ES
00017EFD C3 RET
.以下补丁就足够了:
diff -git a/dbg.asm b/dbg.asm
索引CAEDB70.88024D3 100644
--- a/dbg.asm
+++ b/dbg.asm
@@ -21,7 +21,7 @@
;软件。
[位16]
- [org0x0000]; change_here
+[org0x8210]; change_here
%包括'常数。
@@ -140,8 +140,8 @@ _start:
; change_here
;下面覆盖BIOS指令(如果有)
-Nop
-Nop
+MOV AX,0x4F02
+int0x10
nop
请务必注意,如果您在ROM中更改了一些说明以调用调试器代码,则必须在从调试器返回之前恢复它们。
替换这两个说明的原因是,在BIOS在屏幕上显示徽标之前,它们是在屏幕上执行的,现在是调试器
徽标模块(这是调试器)已经被加载到内存视频中中断BIOS的内存视频中已经有效的代码表明,堆栈已经存在找到一个良好的位置可以调用调试器(BIOS已经足够初始化了,但没有太晚,但可能具有挑战性),但可能是可能的。
此后,DBG.BIN准备插入ROM中的正确位置。

For DOS​

用面包调试DOS程序有点棘手,但可能:

1. Edit dbg.asm so that DOS understands it as a valid DOS program:​

将组织设置为0x100,将有用的代码远离文件开头(times)设置程序输出(int0x20)以下修补程序地址this:
diff -git a/dbg.asm b/dbg.asm
索引CAEDB70.B042D35 100644
--- a/dbg.asm
+++ b/dbg.asm
@@ -21,7 +21,10 @@
;软件。
[位16]
- [org0x0000]; change_here
+[org0x100]
+
+乘以40*1024 db0x90;保持一定距离,
+; 40kb应该足够
%包括'常数。
@@ -140,7 +143,7 @@ _start:
; change_here
;下面覆盖BIOS指令(如果有)
-Nop
+int0x20; DOS中断到退出过程
NOP

2. Create a minimal bootable DOS environment and run​

创建一个仅包含内核和端子: kernel.sys和command.com的可启动freedos(或DOS)的软盘图像。另外,还将将要调试的程序和dbg.com(dbg.bin)添加到这个软盘图像中。
创建Image:之后应采取以下步骤
用已经打开的桥梁启动它(请参阅下一节以获取说明)。执行dbg.com。执行停止后,使用GDB相对于要调试的下一个过程添加任何所需的断点和观察点。然后,允许dbg.com的过程继续直至完成。运行要调试的过程。先前配置的断点和观察点应如预期的那样触发。重要的是要注意,DOS未能在其退出后删除该过程图像。结果,可以像其他任何DOS程序一样配置调试器,并且可以设置适当的断点。调试器的开头充满了NOP,因此可以预料,新过程不会覆盖调试器的内存,即使它似乎已完成”,也可以继续运行。这允许面包调试其他程序,包括DOS本身。

Bridge​

桥是调试器和GDB之间的胶水,无论是在真实硬件还是虚拟机上,都可以以不同的方式使用。
它的参数为:
USAGE:/bridge [选项]
Options:
-s通过插座启用串行,而不是设备
-d路径替换默认设备路径(/dev/ttyusb0)
(如果启用-s,则不起作用)
-p端口序列端口(作为插座),默认: 2345
-G端口GDB端口,默认: 1234
- 这有帮助
如果没有通过选项,则默认行为IS:
./bridge -d/dev/ttyusb0 -g 1234
最小建议使用:
./bridge -s(插座模式,在2345上串行,在1234上的GDB)
./bridge(设备模式,在/dev/ttyusb0和1234上的GDB串行)

Real hardware​

要在真实硬件上使用它,只需调用它而无需参数即可。可选,您可以使用-D参数:更改设备路径

Execution flow:​

将串行电缆连接到PC Run Bridge(././bridge或./bridge -d/path/to/device)打开PC进行调试,请等待Message:单端,您现在可以连接GDB!然后启动GDB: GDB。

Virtual machine​

用于虚拟机中,执行顺序略有更改:

Execution flow:​

Run Bridge(./bridge或./bridge -d/path/to/device)打开VM3(例如3:制造boch或制造QEMU)等待消息:单键,您现在可以连接GDB!然后启动GDB: GDB。在这两种情况下,一定要在桥根文件夹中运行GDB,因为该文件夹中有辅助文件,供GDB在16位中正常工作。

Contributing​

面包总是向社区开放,并愿意接受捐款,无论是问题,文档,测试,新功能,错误文件,错别字等。欢迎使用。

License and Authors​

面包经过麻省理工学院许可证。由戴维森马云惹不起马云弗朗西斯(Davidson Francis)和(希望)其他贡献者撰写。

Footnotes​

断点作为硬件断点实现,因此可用的断点数量有限。在当前实施中,一次只有1个主动断点! ↩
硬件观察点(如断点)也只受到一次支持。 ↩
请注意,调试寄存器默认不在VM上工作。对于Bochs,需要使用-enable-x86-debugger=yes flag对其进行编译。对于QEMU,它需要使用启用kvm enabled: -enable-kvm运行(使qemu已经这样做)。 ↩
 
返回
上方