4、固件二进制分析:ARM/MIPS/RISC-V架构基础、反汇编工具链对比、固件入口点定位
好,咱们进入正题。这一章聊的是固件二进制分析,说白了就是拿到一个陌生的固件文件,怎么下手。我见过不少新手,上来就用IDA一顿猛怼,结果发现反汇编出来的代码根本看不懂——为啥?因为连目标芯片是什么架构都没搞清楚。
嗯,磨刀不误砍柴工。咱们先打好基础。
4.1 三大嵌入式架构:ARM、MIPS、RISC-V
做固件逆向,第一件事就是判断架构。你想想看,ARM的指令长度和MIPS都不一样,用错反汇编引擎,出来的全是乱码。
4.1.1 ARM架构
ARM是目前智能家居固件里的绝对主流。我拆过的设备,十有八九都是ARM核。它有两个模式你得记住:
- ARM模式:指令固定4字节,性能高
- Thumb/Thumb-2模式:指令可以是2字节或4字节,密度高
这里有个坑。我曾经拿到一个固件,用IDA默认的ARM模式反汇编,结果函数入口全是乱码。折腾了半天才发现,这固件其实是Thumb-2混合编码的。切换模式后,代码瞬间就清晰了。
4.1.2 MIPS架构
MIPS在路由器、网关设备里很常见。它的特点是:
- 指令固定4字节,没有Thumb这种变长模式
- 有延迟槽(Delay Slot)——分支指令后面的那条指令一定会被执行
- 大小端模式都有,得看具体芯片
我个人习惯,拿到MIPS固件第一件事就是看入口点附近的指令。如果是lui、addiu这种组合,基本就是MIPS没跑了。
4.1.3 RISC-V架构
RISC-V是后起之秀,最近几年在IoT设备里越来越多。它的特点:
- 指令长度可变:基础指令是2字节,但大部分是4字节
- 模块化设计:RV32I是基础整数指令集,RV32M是乘除法扩展
- 寄存器数量多,有32个通用寄存器
说实话,RISC-V的固件我接触得还不多,但趋势很明显。我建议你现在就开始熟悉它的指令格式,别等满大街都是RISC-V设备了再学。
4.2 反汇编工具链对比
工具这东西,没有最好的,只有最顺手的。我三个都用过,给你说说我的真实感受。
| 特性 | Ghidra | IDA Pro | Radare2 |
|---|---|---|---|
| 价格 | 免费开源 | 商业软件(贵) | 免费开源 |
| 架构支持 | ARM/MIPS/RISC-V全支持 | 全支持,且更新快 | 全支持,但需手动加载 |
| 反汇编质量 | 好,尤其是ARM Thumb | 极好,业界标杆 | 良好,但需调参 |
| 脚本能力 | Python/Java | Python/IDC | Python/R2Pipe |
| 学习曲线 | 中等 | 陡峭 | 陡峭 |
| 我最常用的场景 | 固件批量分析 | 深度逆向、调试 | 快速查看、自动化 |
4.2.1 Ghidra —— 我的主力工具
Ghidra是NSA开源的,说实话,刚出来时我还不信它能比IDA好。用了一段时间后,真香。它的优势在于:
- 自动分析能力强:加载固件后,它能自动识别函数、变量、字符串
- 反编译功能:直接把汇编转成C代码,虽然不一定100%准确,但能省80%的时间
- 团队协作:可以多人同时分析同一个项目
我现在的流程是:先用Ghidra做初步分析,定位关键函数,然后再用IDA做深度逆向。
4.2.2 IDA Pro —— 老牌王者
IDA Pro我用了快十年了。它的反汇编质量确实是最好的,尤其是对付混淆过的代码。但缺点也很明显:
- 贵,个人用户基本买不起
- 插件生态虽然丰富,但配置起来很麻烦
我一般只在两种情况下用IDA:一是遇到加壳或混淆的固件,二是需要动态调试时。
4.2.3 Radare2 —— 命令行利器
Radare2是纯命令行的,刚开始用会很不习惯。但一旦上手,你会发现它特别适合自动化分析。比如:
# 加载固件并自动分析
r2 -A firmware.bin
# 查看入口点
[0x00000000]> afl
# 反汇编指定地址
[0x00000000]> pd 20 @ 0x1000
我写自动化脚本时,首选就是Radare2。它轻量、可定制,而且支持管道操作。
4.3 固件入口点定位
这是最关键的步骤。入口点找错了,后面全白干。
4.3.1 常见入口点类型
- Reset Vector:ARM/MIPS上电后第一个执行的地址,通常是0x00000000或0xFFFF0000
- Startup函数:C运行时初始化代码,负责设置栈、BSS段等
- main函数:用户代码的入口
4.3.2 我的定位方法
我一般按这个顺序来:
- 看文件头:如果是ELF或PE格式,直接读头里的入口点字段
- 找中断向量表:ARM的向量表在0x00000000,第一个就是复位向量
- 搜索特征字符串:比如"main"、"start"、"_start"
- 分析交叉引用:从已知的库函数反推入口
4.3.3 架构特定的入口点特征
不同架构的入口点有各自的特点:
- ARM:复位向量通常是
LDR PC, [PC, #offset]或B label - MIPS:入口点通常是
lui sp, high+addiu sp, low设置栈指针 - RISC-V:入口点通常是
j _start或auipc+jalr组合
嗯,这里要提醒一句:有些固件会故意混淆入口点,比如用花指令或者跳转表。遇到这种情况,别慌,从已知的库函数(比如memset、memcpy)反向追踪,往往能找到线索。
4.4 本章知识体系
下面这张图,是我梳理的固件二进制分析的核心流程。你可以把它当作一个检查清单:
说白了,固件二进制分析就是一条流水线:拿到固件 → 判断架构 → 选工具 → 找入口。每一步都有坑,但只要你按这个流程走,至少不会跑偏。
好了,这一章的内容就到这儿。下一章咱们会深入具体的反汇编实战,到时候我会拿一个真实的智能插座固件来演示。