2. 固件逆向工程基础:固件提取技术、二进制分析工具链、固件结构解析

做MCU安全,说白了就是跟二进制打交道。你拿不到源码,只能对着hex文件或者bin文件硬啃。这时候,逆向工程就是你的基本功。

我个人习惯把固件逆向分成三步:拿到固件 → 看懂结构 → 分析代码。每一步都有坑,咱们一个一个说。

2.1 固件提取技术:怎么把固件搞到手?

没有固件,分析个啥?提取固件的方式,取决于你手里有什么。

提取方式 适用场景 工具/方法 难度
读芯片Flash 有开发板或目标板,芯片未锁 J-Link / ST-Link + 厂商工具 低
读外部存储器 固件存在SPI Flash / EEPROM 逻辑分析仪 / 编程器 + 飞线 中
OTA抓包 设备支持无线升级 Wireshark + 代理 / 嗅探 中高
拆芯片读Die 芯片有读保护,硬破解 酸腐蚀 + 显微镜 + 探针台 极高
我的经验:别一上来就想着拆芯片。先试试用调试器读Flash,很多开发板压根没开读保护。我曾经遇到一个项目,客户说固件加密了,结果我用J-Link直接读出来了——他们只开了写保护,没开读保护。

读Flash时,注意地址范围。MCU的Flash通常从0x08000000或0x00000000开始。用J-Link Commander读个例子:

# 连接目标
connect
# 选择设备,比如STM32F103
# 读取整个Flash,保存为bin文件
savebin firmware.bin 0x08000000 0x10000

读出来的bin文件,就是你的分析对象。嗯,这里要注意:如果芯片开了读保护(RDP Level 1或2),调试器会拒绝读取。这时候才考虑其他手段。

2.2 二进制分析工具链:你的武器库

拿到固件后,用什么工具看?我列个清单,都是我自己常用的。

2.2.1 十六进制查看与编辑

  • HxD / 010 Editor:快速查看文件头、字符串、Magic Number。
  • binwalk:自动扫描固件中的文件系统、压缩包、Bootloader。

2.2.2 反汇编与反编译

  • Ghidra:NSA出品,免费,支持ARM/Thumb/Cortex-M。我主力工具。
  • IDA Pro:商业工具,插件生态好。但贵。
  • objdump:GNU工具链自带,快速看汇编。

2.2.3 固件结构分析

  • binwalk:提取文件系统、识别LZMA/gzip压缩。
  • strings:找明文字符串,比如WiFi密码、API Key。
  • hexdump:看原始字节布局。
避坑指南:我曾经用binwalk分析一个IoT固件,它报了一堆“LZMA compressed data”,结果全是误报。后来手动看文件头才发现,那是厂商自定义的加密魔数。所以,工具的结果要交叉验证,别全信。

2.3 固件结构解析:从二进制到逻辑

MCU固件不是一堆随机字节。它有结构。最常见的布局是这样的:

+-----------------------+
| 中断向量表 (IVT)      |  <- 起始地址,存放栈指针和复位向量
+-----------------------+
| Bootloader (可选)     |  <- 引导程序,负责跳转或升级
+-----------------------+
| 应用程序代码          |  <- 你的main函数在这里
+-----------------------+
| 只读数据 (.rodata)    |  <- 字符串、常量
+-----------------------+
| 文件系统 (可选)       |  <- 如LittleFS、SPIFFS
+-----------------------+

怎么快速定位?看中断向量表。Cortex-M的向量表开头是栈顶地址,第二个是复位向量。这两个值通常是合法的RAM和Flash地址。比如:

0x08000000: 0x20001000  (栈顶,指向RAM)
0x08000004: 0x08000123  (复位向量,指向Flash)

如果这两个值看起来合理,那基本就是标准的固件。如果全是0xFF或0x00,那可能是加密了,或者你读错了地址。

注意:有些厂商会把向量表偏移,比如放在0x08002000。这时候你需要查芯片手册,或者用Ghidra的“Auto Analyze”手动指定基址。

2.4 固件逆向核心流程:一张图说清楚

我把整个流程画成了一张SVG图。你跟着这个顺序走,基本不会迷路。

固件逆向工程核心流程 固件逆向工程核心流程 ① 固件提取 ② 结构识别 ③ 反汇编/反编译 ④ 关键函数定位 ⑤ 漏洞分析 关键点: • 向量表定位基址 • 字符串搜索敏感信息 • 交叉引用找调用链 常见陷阱: • 加密固件直接分析 • 忽略Bootloader区域 • 误认文件系统边界

2.5 实战:用Ghidra打开一个固件

说一千道一万,不如动手做一次。我拿一个常见的STM32固件举例。

  1. 打开Ghidra,新建项目,导入你的.bin文件。
  2. 选择语言:ARM Cortex-M小端(v7或v8,看你芯片)。
  3. 设置基址:比如0x08000000。如果不知道,看向量表第一个值。
  4. 自动分析:Ghidra会反汇编、识别函数、建交叉引用。
  5. 找main函数:搜索字符串“main”或看复位向量指向的地址。
小技巧:Ghidra里按G跳转到复位向量地址,然后按F创建函数。如果反汇编出来全是“undefined”,说明基址设错了。我刚开始用Ghidra时,经常犯这个错。

分析过程中,重点关注几个地方:

  • 字符串引用:比如“password”、“admin”、“key”。
  • 外设寄存器访问:比如0x40000000附近的地址,那是GPIO/UART/SPI。
  • 系统调用:比如SVC指令,可能触发RTOS上下文切换。

嗯,到这里,你已经能独立分析一个固件了。剩下的就是耐心和细心。逆向工程没有捷径,但有了正确的工具和流程,你至少不会在第一步就卡住。