固件逆向基础:从提取到模拟的完整链路

各位同学,今天我们来聊聊固件逆向。说实话,这活儿在软件逆向里算是比较「硬核」的一块。你面对的不再是exe或者apk,而是一坨躺在Flash里的二进制数据——可能是路由器、摄像头,甚至是工控设备。我刚开始接触固件逆向时,第一反应是:这玩意儿怎么下手?

别急,我们一步步来。固件逆向的核心链路其实很清晰:提取 → 分析 → 识别 → 模拟。今天我就把这四个环节掰开揉碎了讲给你听。

一、固件提取:拿到原始数据

没有固件,一切都是空谈。提取方式取决于你手里有什么硬件。

1.1 从固件更新包提取

这是最省事的方式。很多厂商会提供固件升级文件,通常是 .bin、.trx、.img 后缀。我建议你先去官网找找,或者用爬虫抓一下。记得有一次我分析某品牌路由器,官网上的固件包直接就是未加密的——省了我拆机的时间。

1.2 从Flash芯片读取

如果拿不到固件包,就得动硬件了。常见Flash芯片有SPI Flash、NAND Flash、NOR Flash。你需要用编程器(比如CH341A、RT809H)配合夹子或座子来读取。

⚠️ 注意: 读取前一定要确认芯片型号和电压。我曾经因为没注意电压,直接把一个3.3V的Flash烧了——冒烟那种。嗯,从那以后我每次都会先查datasheet。

1.3 通过JTAG/SWD接口提取

如果设备有调试接口,你可以通过OpenOCD或JLink直接dump内存。这需要你找到板子上的JTAG引脚——通常是一排4-6个焊盘。用万用表量一下,GND、TMS、TCK、TDI、TDO,按顺序接上就行。

二、Binwalk分析:固件拆解利器

拿到固件文件后,第一件事就是扔进Binwalk。这工具能自动识别固件里的文件系统和压缩包。说白了,它就像一把瑞士军刀,帮你把固件「拆开」。

2.1 基本扫描

binwalk firmware.bin

输出会告诉你:这里有LZMA压缩数据,那里是Squashfs文件系统,还有一段U-Boot引导程序。我个人习惯先用 binwalk -Me firmware.bin 自动提取所有内容,省得手动一个个解。

2.2 深入分析

有时候Binwalk会漏掉一些东西。比如某些厂商会把文件系统放在偏移量很大的位置,或者用自定义魔数。这时候我会用 -R 参数手动搜索特征字符串:

binwalk -R "hsqs" firmware.bin   # 搜索Squashfs魔数
💡 小技巧: 如果你怀疑固件有加密,先看看熵值。用 binwalk -E firmware.bin 查看熵图。高熵区域(接近1.0)通常是加密或压缩数据。低熵区域(0.2-0.5)可能是明文代码或配置。

三、嵌入式架构识别:搞清楚它是什么芯片

拆开固件后,你得知道这代码跑在什么CPU上。ARM?MIPS?RISC-V?还是冷门的Xtensa?

3.1 从引导加载器判断

U-Boot是最常见的引导加载器。你可以在固件开头搜索 "U-Boot" 字符串。不同架构的U-Boot编译方式不同,ARM版用Thumb指令集,MIPS版用MIPS32指令集。看一眼反汇编就能分辨。

3.2 从文件系统判断

提取出文件系统后,看看里面的可执行文件。用 file 命令:

file ./sbin/init
# 输出示例:ELF 32-bit LSB executable, ARM, version 1 (SYSV)

这就明确了——ARM架构,32位,小端序。我遇到过一些国产芯片用大端序MIPS,那感觉就像在写反字,特别别扭。

3.3 常见嵌入式架构速查表

架构 常见芯片 字节序 典型设备
ARM STM32、Allwinner、Rockchip 小端(默认) 路由器、摄像头、手机
MIPS MT7620、AR9331 小端/大端 老旧路由器、打印机
RISC-V GD32V、K210 小端 IoT设备、AI加速器
Xtensa ESP32、ESP8266 小端 WiFi模块、智能家居

四、固件模拟:让固件跑起来

分析静态代码只能看到一半。真正有意思的是让固件在模拟器里跑起来——这样你可以动态调试,看它怎么联网、怎么处理输入。

4.1 使用QEMU进行用户态模拟

如果你只想跑某个二进制文件(比如web服务),用QEMU用户态模式就够了:

qemu-arm -L ./extracted_fs ./extracted_fs/usr/bin/httpd

-L 参数指定根文件系统路径。这样QEMU会从那里加载动态库。我遇到过最坑的情况是:固件里缺了某些库文件,程序直接段错误。这时候你得手动从固件里找,或者用 strace 看它到底缺什么。

4.2 全系统模拟

有些固件需要完整的硬件环境——比如依赖特定的GPIO、中断控制器。这时候得用QEMU的系统模式:

qemu-system-arm -M virt -kernel vmlinux -drive file=rootfs.squashfs,format=raw -append "root=/dev/sda"

但说实话,全系统模拟成功率不高。很多嵌入式设备有专有外设,QEMU不支持。我一般先用Firmadyne或FirmAE这类自动化工具试试,它们封装好了很多常见设备的模拟配置。

🔑 关键点: 模拟固件的核心是解决「硬件抽象层」问题。你需要为固件提供它期望的硬件接口——哪怕是个假的。比如用 libnvram 模拟NVRAM,用虚拟网卡模拟物理网口。

4.3 模拟后的调试技巧

固件跑起来后,你可以用GDB远程调试:

qemu-arm -g 1234 ./binary
# 另一个终端
gdb-multiarch
(gdb) target remote localhost:1234

这样就能下断点、看寄存器、单步执行了。我个人习惯在关键函数入口下断点,比如 recvsendsystem——这些往往是漏洞触发点。

知识体系总览

下面这张图总结了固件逆向的完整流程。你可以把它当作一个检查清单:

固件逆向基础流程 固件提取 更新包 / Flash / JTAG Binwalk分析 扫描 / 提取 / 熵分析 架构识别 ARM / MIPS / RISC-V 模拟 各阶段关键工具与输出 工具:CH341A、OpenOCD 输出:firmware.bin 工具:Binwalk、dd 输出:文件系统、内核 工具:file、readelf 输出:架构、字节序 工具:QEMU、Firmadyne 输出:运行中的固件 💡 核心思路:从物理到逻辑,从静态到动态 提取原始数据 → 拆解文件结构 → 识别运行环境 → 模拟执行调试

你看,整个流程是线性的,但实际工作中经常需要回溯。比如模拟失败时,你可能要回去重新分析文件系统,看看是不是漏了什么依赖库。这很正常——逆向工程本来就是个迭代过程。

好了,关于固件逆向的基础就讲到这里。记住:提取是前提,分析是核心,识别是关键,模拟是验证。把这四个环节练熟了,大部分嵌入式设备你都能搞定。


公众号:蓝海资料掘金营,微信deep3321