Skip to content
KitploitKITPLOIT
工具博客
Log in
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
am335xbootrom — 对 TI AM3358 引导 ROM 进行逆向工程 | Kitploit
工具/GitHubGitHub/sjgallagher2/am335xbootrom
嵌入式系统安全逆向工程调试器硬件黑客二进制分析学习与教育固件分析
GitHubsjgallagher2/am335xbootrom

am335xbootrom

对 TI AM3358 引导 ROM 进行逆向工程

查看仓库
615182年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

逆向工程 AM335x 引导 ROM

从我第一次拿到几块从垃圾堆里救出来的 Beaglebone Black 板子算起,大概已经过去十八个月了。不幸的是,这些板子无法立即正常工作。这是我第一次接触这类板子,或者说第一次接触任何单板计算机,所以我不确定问题是出在我自己的操作上,还是板子本身有问题(也许这正是它们当初被扔进垃圾堆的原因)。我花了相当长的时间和大量精力,才让这些板子真正开始启动,但我他妈的做到了。以下就是我在这个过程中学到的东西。

注意:如何使用 Ghidra XML 文件

我在这个仓库里包含了一些实用工具,以及一个从 Ghidra 导出的 xml 文件,里面包含了我目前通过逆向获得的所有符号。我使用了这篇文章中的方法进行导出,而不包含实际固件,以避免任何版权问题,以防万一。如果你想自己调试引导 ROM,你反正已经接好了 JTAG,可以自己转储引导 ROM(从 0x20000 到 0x2BFFF)。

要加载这些符号:

  1. 创建一个新的 Ghidra 项目。将 二进制(不是 XML)导入 Ghidra:使用 ARMv7 小端模式,并确保在 Options 下将基地址设置为 0x20000,同时可以将块名称设置为 bootrom。
  2. 在 CodeBrowser 中打开这个二进制文件。不要分析。
  3. 转到 File > Add program,然后选择 XML 文件。默认设置应该没问题。现在你可以浏览复位处理程序,或者跳转到 main(),或者 MMC/SD 卡引导处理程序。

问题所在

首先,我知道这些是标准 beaglebone black 的定制版本,所以早期我判断问题可能出在板子本身缺少某些东西,比如板标识符。当我用 balenaEtcher 格式化标准 SD 卡并启动时,看到的只是什么都没有。我原本期望板上的 LED 开始闪烁,并且期望连接 UART 转 USB 线缆后能看到 U-Boot 过程。然而,UART 一片寂静。如果我移除 SD 卡,它会反复输出字母 C,这是 UART/串行引导的预期行为。它确实在 尝试 启动,而 SD 卡改变了这种行为,但我没有更多的可见信息。网上大多数故障排查都以 U-Boot 输出作为诊断问题的起点。我想我没有那种奢侈了。

我觉得此时连接一个调试探针是值得的。不幸的是,我没有匹配现有引脚封装的接头,所以我自己做了一个。

beaglebone 板子上有一个设计编号为 P2 的接头,引出了 JTAG 连接。我将一些导线连接到这个接头,再接到一个母头上,这样我就可以通过我的 J-Link 与它通信。

启动 Ozone(Segger 调试器)后,我配置了 J-Link,并首先尝试找到入口点。我原以为复位暂停(reset-halt)会把我带到需要的位置,这就是我得出了(错误)假设——入口点是 0x2148a 的原因,尽管我确实注意到这并不一致。后来,我意识到 AM335x 板子与 J-Link 的复位暂停配合得并不好,所以实际上会有几百个时钟周期的延迟,导致我不确定地落在了某个引导处理程序内部。(我最终通过为 TI 的 Code Composer Studio 编写一个 GEL 文件绕过了这个问题,CCS 支持 J-Link 调试——复位时,PC 寄存器被设置为复位处理程序,寄存器被清零,指令模式被强制为 ARM。)

从 TI 论坛的一个帖子(AM335x: TI employees, where can I get the ROM Bootloader source code/symbols?)中,我获得了一些调试符号:SPI Initialize 位于 0x231e0,SPI ReadSectors 位于 0x23230,而 0x24bfa 是一个执行 UART 读取的例程。我想这算是不小的帮助。我注意到引导失败后会在 0x402f0440 处陷入无限循环,这是一个死循环。嗯,距离引导 ROM 的其他部分相当远,一定是在 RAM 或什么地方。大概是时候去看看技术参考手册(TRM)了!

TRM 的第 26 章包含大量关于引导的信息。我们得到了如下的引导 ROM 视图:

描述:

公共 ROM 代码的架构如图 26-1 所示。它采用自上而下的方法分为三个主要层:高层、驱动层和硬件抽象层(HAL)。一层通过统一接口与较低层通信。 高层负责公共 ROM 代码的主要任务:看门狗和时钟配置以及主引导例程。 驱动层根据接口规范为任何引导设备实现逻辑和通信协议。 最后,HAL 实现用于与硬件基础设施 IP 交互的最低层代码。终端引导设备连接到器件 IO 焊盘。

图 26-2 说明了公共 ROM 代码引导过程的高层流程。在此器件上,公共 ROM 代码在安全启动(由安全 ROM 代码执行)完成后启动。随后,ROM 代码作为公共启动过程的一部分执行平台配置和初始化。引导设备列表基于 SYSBOOT 引脚创建。引导设备可以是存储器引导设备(焊接的闪存或临时引导设备,如存储卡),也可以是连接到主机的外设接口。 引导过程的主循环遍历引导设备列表,并尝试从当前选定的引导设备搜索映像。如果找到有效的引导映像并成功执行,或者看门狗超时,则退出此循环。在 HS 器件上,映像执行之前会执行映像认证过程。认证过程失败会导致分支到安全 ROM 中的“死循环”(等待看门狗复位)。

内存映射!异常向量!流程图!这一节包含大量信息。我的工作轻松了 很多。

此时,我使用 JTAG 探针将固件下载到几个不同的文件中,并开始将内容加载到 Ghidra 中。似乎没有以方便格式提供的 SVD 文件或其他寄存器映射,这真的很不幸,因为这意味着我需要手动定义内存区域、寄存器以及所有内容。这是一个繁琐的过程,但过了一会儿,我就有了一个 Python 脚本,可以用来为 AM3358 向 Ghidra 加载符号。又少了一件需要担心的事情!

逆向

似乎我拥有的文件可以映射为:

区域起始地址长度
引导 ROM(公共)0x4002_00000xBFFF
引导 ROM(公共,别名)0x0002_00000xBFFF
内部 SRAM0x402F_04000xFC00
L3 OCM00x4030_00000x10000

有趣的是,位于 0x402f_0440 的无限循环位于内部 SRAM 中“下载映像”的顶部,而异常向量则存储在其他地方。也许这以后会是一个重要的线索……

复位时,私有引导 ROM 处理安全相关事务,并分支到 0x2 0000,其中包含复位向量。第一条指令是一个分支到 0x2 08d0 的指令,这必定是入口点。它不是 BX 指令,所以可以推测,此时我们仍然处于 Arm 模式。

复位处理程序

这是第一个运行的代码,所以它并不完全是一个带参数的“函数”,而更像是一个编译生成的启动脚本。第一个基本块:```arm ldr r4,[->Peripherals::CM_PER] mov r0,#0x2c ldr r6,[r4,r0]=>CM_PER.CM_PER_OCMCRAM_CLKCTRL mov r6,#0x2 str r6,[r4,r0]=>CM_PER.CM_PER_OCMCRAM_CLKCTRL mov r0,#0x2c poll: ldr r6,[r4,r0]=>CM_PER.CM_PER_OCMCRAM_CLKCTRL cmp r6,#0x2 bne poll

此块将 OCMC RAM 时钟设置为启用:
1. 设置 `CM_PER_OCMCRAM_CLKCTRL=0x2`
2. 检查寄存器是否已设置;如果没有,则持续轮询
`CM_PER_OCMCRAM_CLKCTRL` 寄存器使用位 0 和位 1 作为 `MODULEMODE` 字段,将此设置为 `=0x2` 会启用 OCMC RAM 的时钟。

下一个基本块:```arm
	    ldr        r0,[PTR_control_status] 
	    ldr        r0,[r0,#0x0]=>control_status 
	    and        r0,r0,#0x700
	    mov        r0,r0, lsr #0x8
	    cmp        r0,#0x3
	    bne        skip
		ldr        r0,[PTR_control_status] 
	    ldr        r0,[r0,#0x0]=>control_status
	    cpy        r6,r0
	    and        r0,r0,#0x1f
	    cmp        r0,#0x1f
	    bleq       GPMIC_init 
skip:   ...

此块执行以下操作:

  1. 检查 (control_status & 0x700) >> 8 == 0x3,如果不满足则跳过
  2. 检查 control_status & 0x1f == 0x1f,如果是,则在将 control_status 加载到 r6 后调用函数 GPMC_init

下一个块设置协处理器:```arm msr cpsr_c,#0xd3 ldr r4,[->Exceptions::ROM_RESET_VECTOR] mcr p15,0x0,r4,cr12,cr0,0x0 bl LAB_00020934 bl LAB_00020938 bl LAB_0002093c bl LAB_00020940 bl LAB_00020944 bl LAB_00020948 bl LAB_0002094c bl LAB_00020950 mrc p15,0x0,r0,cr1,cr0,0x0 orr r0,r0,#0x800 mcr p15,0x0,r0,cr1,cr0,0x0 b LAB_000207f0

此块中的操作:
1. 将 `11010011b` 移入 CPSR 控制字段(`I=1`,`F=1`,`T=0`,`MODE=10011`)
	1. `I` 是中断禁用位,`F` 是快速中断禁用位(因此 `I=F=1` 表示中断被禁用)
	2. `T` 是 Thumb 模式,设置为 `0`
	3. `MODE=10011` 将处理器模式设置为 Supervisor 模式([ref](https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-core-registers/ARM-processor-modes?lang=en#CIHGHDGI))
	4. 更多信息请参阅 [此处](https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-core-registers/Program-Status-Registers--PSRs-)
2. 将地址加载到 ROM 复位向量
3. 访问 [协处理器 15](https://developer.arm.com/documentation/den0013/d/ARM-Processor-Modes-and-Registers/Registers/Coprocessor-15)(系统控制协处理器)的安全扩展寄存器 `c12`,并将 ROM 复位向量加载到 `VBAR`(向量基地址寄存器)
![](https://assets.kitploit.com/production/public/readmes/48883/6c4ef51fde89883fcdb3a9497004830d928d6f6c716668acd86dce3b9a68c93b.png)
4. 看起来像是 `nop` 跳转?为什么用 `bl` 而不是 `b`?
5. 启用分支预测(将系统控制寄存器 `SCTLR` 的第 11 位置位)
![](https://assets.kitploit.com/production/public/readmes/48883/7a99ff8bd5285136c05b9d91bdf5057a6512c614cacc2726ce740254e4c240fa.png)
*VMSA 实现中的 CP15 `c1` 寄存器(系统控制寄存器)*

`SCTLR` 寄存器说明:
> SCTLR 提供系统的顶层控制,包括其存储系统。
> 该寄存器属于虚拟内存控制寄存器功能组。

参见 TRM 第 B4-1687 页。第 11 位是*分支预测启用*位,将其置位即表示启用[分支预测](https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/Common-Memory-System-Architecture-Features/Caches/Branch-predictors)。

6. 调用一个函数(通过分支到调用指令)

### 位于 `0x20894` 的函数(`__main`)
下载工具