固件与 IoT 设备逆向

固件与 IoT 设备逆向实战:覆盖固件提取的 Flash、OTA 与串口三条路径,binwalk 解包与文件系统还原、架构识别与交叉反编译、UART 与 JTAG 调试接口定位、MQTT 与 CoAP 通信协议分析、硬编码凭据与后门排查,以及 QEMU 与 Firmadyne 仿真运行和防御加固要点。

引言

IoT 与固件逆向是 CTF 里最「物理」的方向:它不给你一个规整的二进制,而是给你一段从设备里读出来的裸镜像、一个串口日志,或者一个厂商官网的升级包。题目要你从这些碎片里还原出设备的行为、找出隐藏的凭据或后门,最终拿到 flag。它和移动逆向共享「多层剥离」的思路,但多了硬件层与文件系统层的复杂度。

工程上的难点集中在三处。第一是入口不确定:固件可能藏在 SPI Flash 芯片里、可能从 OTA 升级包拿到、也可能只能通过串口 dump;不同入口得到的镜像完整度差别很大,需要先判断「我手上这份是完整镜像还是分区片段」。第二是架构五花八门:ARM、MIPS、MIPSel、ARM Thumb、甚至 RISC-V,交叉反编译必须选对架构与端序,选错了反汇编出来全是垃圾指令。第三是运行环境难以复现:嵌入式程序依赖特定的硬件外设、内核模块与启动脚本,直接丢到 x86 上跑不起来,必须靠 QEMU 做用户态或系统态仿真。

本文按「攻击面 → 固件提取 → 解包 → 架构识别 → 硬件调试 → 协议分析 → 凭据排查 → 仿真 → 防御」的顺序组织,所有实验在自建靶场固件、公开的 CTF 附件与自己拥有或获授权的设备上完成。设备侧的整体防护体系可参考 移动与 IoT 安全 ;文件系统层的结构与取证方法可对照 Linux 文件系统与磁盘 与 Misc 方向隐写与取证 。

目录

  1. IoT 设备的攻击面与题目形态
  2. 固件提取:Flash、OTA 与串口三条路径
  3. binwalk 解包与文件系统还原
  4. 架构识别与交叉反编译
  5. 硬件调试接口:UART 与 JTAG
  6. 通信协议分析:MQTT 与 CoAP
  7. 硬编码凭据与后门排查
  8. 仿真运行:QEMU 与 Firmadyne
  9. 防御要点与检测

1. IoT 设备的攻击面与题目形态

一个典型的 IoT 设备由四层构成,每层都有独立的攻击面:

层级组件典型攻击面
硬件层SoC、Flash、调试口UART/JTAG 暴露、Flash 可读
固件层Bootloader、内核、根文件系统硬编码凭据、未签名更新
系统层服务进程、Web 面板、UPnP命令注入、认证绕过
通信层MQTT、CoAP、私有协议明文传输、弱认证、重放

CTF 里的固件题目通常按「你拿到的入口」分类:

  • 给整段 Flash 镜像:最常见,需要自己判断分区表与文件系统类型。
  • 给厂商 OTA 升级包:通常是加密或签名过的容器,考的是解密与解压链。
  • 给设备与串口:需要用 USB-TTL 连接,读启动日志甚至进 bootloader 命令行。
  • 给一段抓包:考的是协议逆向与密钥提取,与流量分析方向重叠。

判断题型后立刻能确定路线:有整镜像就直接 binwalk,有升级包先分析容器格式,有串口就先抓启动日志。启动日志是信息密度最高的入口——它通常会打印 SoC 型号、内核版本、分区挂载点、以及各个服务的启动状态,一次采集就能省掉大量猜测。

2. 固件提取:Flash、OTA 与串口三条路径

三条提取路径的成本与完整度各不相同,实际做题时按可获得性选择。

路径一:从 Flash 芯片直读。设备主板上通常有一颗 SPI NOR Flash(如 Winbond W25Q128,16 MB)。硬件手法是用 SPI 编程器(CH341A)夹住芯片读取,或在设备上找到 SPI 的 CLK/MOSI/MISO/CS 测试点飞线。软件手法是在能拿到 shell 的前提下,直接在设备上读 /dev/mtd*:

# 本地教学:在已授权的自建设备上 dump 固件
cat /proc/mtd                      # 列出分区表:名字、大小、擦除块大小
dd if=/dev/mtd0 of=/tmp/boot.bin   # 读 bootloader 分区
dd if=/dev/mtdblock2 of=/tmp/rootfs.bin   # 读根文件系统分区
nanddump -f /tmp/ubifs.bin /dev/mtd3      # NAND 设备需用 nanddump

/proc/mtd 是解题的关键线索:它直接告诉你每个分区的名字(u-boot、kernel、rootfs、nvram)与偏移大小,比从整镜像里猜要快得多。注意 /dev/mtd* 是字符设备(带 OOB 数据),/dev/mtdblock* 是块设备(去掉 OOB),NAND 设备必须用 nanddump 才能保留正确的 ECC 布局。

路径二:从 OTA 升级包。厂商的升级包可能是明文 tar、加密的 zip、或者自定义容器(如某些厂商用 AES-CBC 加密后包一层 header)。分析顺序是:先 file 与 xxd 看头部,再 binwalk 扫内嵌签名,最后若发现是加密容器,就从设备固件里找解密密钥(通常硬编码在某个 libupgrade.so 或 upgrade 二进制里)。

硬件读取的细节值得单独说:SPI NOR Flash 的 SOIC-8 封装引脚顺序是固定的(1 号脚有圆点标记),用 CH341A 编程器夹住后读出的镜像是整个芯片的线性映射,包含所有分区。读出后应当先 sha256sum 记录哈希(保证后续分析的是同一份数据),再用 xxd 核对首字节——若开头是 0xFF 的成片填充,说明该区域未写入或被擦除。还有一种常见情况是双镜像(A/B 分区):芯片里存了两份固件以便回滚,解题时两份都要看,因为老版本可能没有修掉后门。

路径三:从串口 dump。当 Flash 被读出保护(RDP)锁住时,只能通过 UART 进 bootloader(U-Boot)命令行,用 md(memory display)与 tftpput/ymodem 把内存里的固件传到主机。这条路径最慢但最通用。

三条路径可以组合使用:先用 OTA 包拿到明文根文件系统(解包最快),再用 UART 验证运行时行为(看真实启动参数),最后若发现关键逻辑在加密分区里,才动用 Flash 直读或 JTAG。按「成本从低到高」的顺序尝试,是最省时间的策略。

# 本地教学:U-Boot 命令行下的常见操作(自建设备)
=> bdinfo                      # 打印板级信息:内存布局、波特率
=> printenv                    # 打印环境变量,常含启动命令与分区定义
=> md.b 0x80000000 0x100       # 以字节为单位 dump 内存
=> tftpput 0x80000000 0x100000 192.168.1.10:dump.bin   # 通过 TFTP 传出

printenv 的输出常含 bootargs(内核启动参数,能看出根文件系统类型与分区)、bootcmd(默认启动命令),以及出厂默认的 IP 与升级口令。

3. binwalk 解包与文件系统还原

拿到固件镜像后的第一步是识别结构。binwalk 通过扫描已知签名定位内嵌的文件系统与压缩流:

# 本地教学:固件解包标准流程
binwalk firmware.bin                       # 列出所有识别到的签名与偏移
binwalk -e firmware.bin                    # 按签名提取(仅对本地自建文件)
binwalk -E firmware.bin                    # 熵分析:识别加密段(熵接近 8 的区间)
strings -a -n 8 firmware.bin | grep -iE "password|admin|token" | head

熵分析是判断「有没有加密」的关键:正常固件里代码段熵约 6–7,压缩数据熵约 7.9,而全 0 的空白区熵接近 0。若镜像中间出现一段持续高熵的区域,基本可以断定是加密或强压缩的内容,此时 binwalk 的签名扫描会失效,需要先解密再解包。

嵌入式根文件系统的类型决定了后续怎么挂载:

类型特征还原方式
SquashFS魔数 hsqs(小端)/ sqsh(大端)unsquashfs -d out rootfs.sqsh
JFFS2魔数 0x1985(字节序敏感)jefferson -d out jffs2.img
UBIFS需 UBI 层信息(UBI#)先 ubireader_extract_images 再 ubireader_extract_files
CramFS魔数 0x28cd3d45cramfsck -x out cramfs.img
ext2/3/4标准 ext 超级块mount -o loop 或 debugfs
YAFFS2无固定魔数,需按 OOB 布局解析unyaffs 或 yaffs2utils
# 本地教学:SquashFS 还原(最常见的类型)
unsquashfs -d rootfs_extracted rootfs.sqsh
ls rootfs_extracted/etc/init.d/          # 启动脚本,看起了哪些服务
cat rootfs_extracted/etc/passwd          # 默认账号与口令哈希
cat rootfs_extracted/etc/shadow          # 若存在,含真正哈希

还原后的根文件系统是信息宝库,按优先级排查:

  • /etc/passwd、/etc/shadow:默认账号与口令哈希(嵌入式设备常用弱口令)。
  • /etc/init.d/、/etc/rc.local:启动脚本,能看出有哪些服务、监听哪些端口。
  • /etc/ 下的厂商配置:Wi-Fi 默认口令、云端 API key、MQTT broker 地址与凭据。
  • /usr/sbin/、/usr/bin/:自定义二进制,是逆向的主要目标。
  • /etc/nginx/ 或 /etc/lighttpd/:Web 面板配置,常暴露 CGI 路径。

4. 架构识别与交叉反编译

嵌入式设备极少用 x86,架构选错会让反汇编彻底失败。识别方法有三层,从快到准:

# 本地教学:架构识别三层法
# 第一层:ELF 头(对单个可执行文件最准)
file rootfs_extracted/usr/sbin/upgrade
# 输出形如:ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked

# 第二层:镜像整体(对无文件系统的裸镜像)
binwalk -Y firmware.bin         # 用 capstone 反汇编扫描,猜测架构
# 第三层:读启动日志里的 SoC 型号,反查其内核架构

嵌入式常见的几种架构与识别要点:

架构file 输出关键词端序典型厂商
ARMARM, EABI5小端为主高通、博通、全志
ARM ThumbARM, EABI5, Thumb小端代码密度优化场景
MIPSMIPS, MIPS32大小端都有联发科、瑞昱、Atheros
MIPSelMIPS, MIPS32, LSB小端大量家用路由器
RISC-VRISC-V, RV32/RV64小端为主新兴 IoT 芯片
PowerPCPowerPC大端部分工业设备、老网络设备

反编译工具的选择:IDA Pro 对 MIPS 与 ARM 的支持最成熟,Ghidra 免费且反编译质量在近年追得很近。加载时必须显式选对处理器型号与端序,特别是 MIPS 的 mipsl(小端)与 mipsb(大端)不能混。若 file 报出的是「MIPS, MIPS32 rel2」,在 IDA 里选 mipsr(MIPS32 小端)通常正确。

一个实用的验证技巧:反汇编后如果看到大量非法指令或明显的对齐错乱,就是架构或端序选错了;正确的反汇编里函数序言(ARM 的 push {r4, lr}、MIPS 的 addiu sp, sp, -0x20)应当规律出现。

# 本地教学:命令行交叉反编译(无 GUI 环境)
# 用 Ghidra headless 批量反编译
analyzeHeadless /tmp/proj fw -import ./upgrade -postScript DecompileAll.java
# 或用 objdump 做快速粗读(注意指定架构)
objdump -D -b binary -m mips:isa32 -EB firmware.bin | head -50

5. 硬件调试接口:UART 与 JTAG

硬件层接口是「绕过一切软件防护」的后门:拿到 UART 就能读启动日志、进 bootloader、甚至拿到 root shell;拿到 JTAG 能直接读写内存与寄存器。

UART 定位:主板上通常有 3 或 4 个未焊接的焊盘,标着 TX、RX、GND、VCC。用万用表找 GND(与屏蔽罩或电容负极导通),再用示波器或逻辑分析仪看哪个脚在启动时有数据(TX 脚会有约 3.3V 的方波)。波特率常见为 115200 或 57600,用 screen 或 picocom 连接:

# 本地教学:连接 UART(自建设备)
picocom -b 115200 -d 8 -p n /dev/ttyUSB0
# 或在 minicom 中:115200 8N1,无流控
# 启动设备后能看到 U-Boot 与内核日志

一个高频技巧是在 U-Boot 启动倒计时期间打断自动启动(通常是按任意键),进命令行后可以改 bootargs(如加 init=/bin/sh 直接进 shell)、或用 md/tftpput 导出内存。有些设备还允许从 U-Boot 直接 tftpboot 一个自定义内核,完全绕过厂商固件。

JTAG 定位:JTAG 有 4–5 个必需信号(TCK、TMS、TDI、TDO、可选 TRST),比 UART 复杂但权限更高——能 halt CPU、读写任意内存、设硬件断点。定位方法是用 JTAGulator 或 JTAGenum 自动扫描引脚组合。拿到 JTAG 后可用 OpenOCD 连接:

# 本地教学:OpenOCD 连接(需已知 SoC 的 tap 定义)
openocd -f interface/ftdi/ft2232.cfg -f target/mips_m4k.cfg
# 在 telnet 控制台里:
# halt                 停止 CPU
# mdw 0x80000000 16    读 16 个字
# dump_image out.bin 0x80000000 0x100000

JTAG 的价值在于绕过 Flash 读保护:即便固件被加密存储,CPU 运行时的内存里也一定有明文(或至少是解密后的代码),通过 JTAG halt 后 dump 内存即可。

检测与防御:硬件接口的防御手段是「熔断 eFuse 禁用 JTAG」「启用安全启动」「Flash 加密 + 密钥存于 SoC 内部不可读区域」。这些措施能把成本从「飞线 + 万用表」提高到「需要芯片级攻击」,是消费级与工业级设备的主要分界线。

6. 通信协议分析:MQTT 与 CoAP

IoT 设备与控制端、云端的通信协议是最容易出问题的环节,因为它常常在「能跑就行」的优先级下被草率实现。

MQTT 是发布/订阅模型,基于 TCP(1883 明文 / 8883 TLS)。它的报文结构极简:固定头(1 字节类型 + 变长剩余长度)、可变头、载荷。CONNECT 报文里含 Client ID、用户名、密码——这三者在明文 1883 上完全可见。

# 本地教学:抓取并解析 MQTT(自建 broker 与设备)
tcpdump -i eth0 -w mqtt.pcap port 1883
tshark -r mqtt.pcap -Y mqtt -T fields -e mqtt.msgtype -e mqtt.topic -e mqtt.msg
# 直接用 mosquitto 客户端订阅通配主题,看设备在发什么
mosquitto_sub -h broker.local -t '#' -v

MQTT 的常见问题:允许匿名连接(allow_anonymous true);ACL 未配置导致任意客户端可订阅 # 通配主题,从而拿到所有设备的数据;用客户端 ID 或 MAC 当作身份标识(可伪造);TLS 未启用或未校验服务端证书。

报文类型的高四位决定了包的种类,做题时按这张表快速定位:

类型值名称用途
1CONNECT建立连接,携带 Client ID / 用户名 / 密码
2CONNACK连接确认,返回码 0 表示成功
3PUBLISH发布消息,含主题名与载荷
8SUBSCRIBE订阅主题(可含通配符 + 与 #)
12PINGREQ心跳保活

PUBLISH 的载荷格式由设备厂商自定义:可能是裸 JSON、可能是二进制结构体、也可能是加密后的一段数据。若载荷是加密的,密钥通常硬编码在固件的对应二进制里,此时需要回到反编译流程找解密函数——这也是「协议题」与「固件题」经常合并出现的原因。

CoAP 是面向 UDP 的轻量协议(默认 5683),为受限设备设计。报文结构为固定 4 字节头 + token + options + payload,用 GET/POST 等方法操作资源,语义上类似 HTTP。它的 Block1/Block2 选项用于分块传输,观察(Observe)选项用于订阅资源变化。

# 本地教学:CoAP 探测(自建设备)
coap-client -m get coap://device.local/.well-known/core     # 发现可用资源
coap-client -m get coap://device.local/status

私有二进制协议是固件题的高频考点:题目给一段 UART 或 TCP 抓包,要求还原协议字段。分析方法与 Misc 方向隐写与取证 里的流量题一致——先看字节频率与固定位置的常量(可能是魔数与长度字段),再看载荷是否随操作变化,最后用固件里对应的解析函数交叉验证。协议逆向与网络协议栈的基础知识可参考 网络协议基础 。

一个实用的交叉验证方法:在反编译出的固件里搜协议相关的字符串或常量(如魔数 0x55AA、校验多项式),找到解析函数后,把函数逻辑与抓包逐字节对照,就能确定每个字段的含义。

检测与防御:MQTT 应强制 TLS 与双向认证、禁用匿名、按设备粒度配置 ACL;CoAP 应使用 DTLS(coaps://)并启用 PSK 或证书;私有协议应做完整性校验(HMAC)与防重放(nonce + 时间戳)。固件更新必须签名验证,否则一次 OTA 劫持就能批量控制设备。

7. 硬编码凭据与后门排查

硬编码凭据是 IoT 设备最常见也最致命的问题,排查应当系统化而非靠 grep 碰运气。

第一层:文件系统里的静态凭据。

# 本地教学:凭据排查脚本化
grep -rniE "(password|passwd|pwd|secret|token|api[_-]?key)\s*[:=]" rootfs_extracted/etc/ | head -40
cat rootfs_extracted/etc/passwd rootfs_extracted/etc/shadow 2>/dev/null
# 查 SSH 密钥、TLS 证书私钥
find rootfs_extracted -name "*.pem" -o -name "id_rsa" -o -name "*.key"

第二层:二进制里的字符串。凭据可能被编译进可执行文件而非配置文件:

# 本地教学:二进制字符串排查
strings -a -n 6 rootfs_extracted/usr/sbin/* | grep -iE "admin|root|12345|default" | head
# 对特定二进制做更细的排查
strings -a -n 4 rootfs_extracted/usr/bin/cgi-bin/login.cgi | less

第三层:后门与调试接口。常见形态包括:调试用的隐藏 CGI(如 /cgi-bin/debug)、带固定口令的 telnetd 启动项、以特定 UDP 包触发的命令执行、以及「万能口令」(某个固定字符串绕过所有认证)。

# 本地教学:查启动脚本里的可疑服务
grep -rn "telnetd\|dropbear\|debug" rootfs_extracted/etc/init.d/
# 查是否有硬编码的默认 Wi-Fi 口令算法(常见于用 MAC 派生口令的设备)
grep -rn "ssid\|wpa\|wlan" rootfs_extracted/etc/ | head -20

第四层:弱口令哈希破解。嵌入式设备的 /etc/shadow 常含 DES 或 MD5 crypt 的哈希,用 hashcat 或 john 针对嵌入式设备的常见口令字典(如设备型号、root、admin、12345)爆破:

# 本地教学:识别并破解嵌入式口令哈希
cat rootfs_extracted/etc/shadow | grep -v '^[^:]*:[*!]'
# $1$ 开头是 MD5 crypt,$5$ 是 SHA-256,$6$ 是 SHA-512
hashcat -m 500 hashes.txt wordlist.txt      # -m 500 = md5crypt

检测与防御:每一台设备的默认凭据必须唯一(出厂时随机生成或首次登录强制修改);禁止编译进调试后门;发布固件前用自动化工具扫描硬编码凭据;关闭不必要的调试服务(telnet、调试 CGI);启用安全启动确保固件不可篡改。

8. 仿真运行:QEMU 与 Firmadyne

当固件依赖特定硬件而无法在真机上跑时,仿真能在 x86 主机上复现设备行为。它有两个层次:

用户态仿真(qemu-user) 只模拟 CPU 指令集,让单个二进制在主机内核上运行。它快、简单,适合分析单个程序(如某个 CGI):

# 本地教学:用户态仿真 MIPS 二进制
sudo apt install qemu-user-static binfmt-support
qemu-mipsel -L rootfs_extracted ./rootfs_extracted/usr/sbin/upgrade
# -L 指定动态链接库的根目录(sysroot),否则找不到 .so
# 若程序检查架构,可配合 qemu-mipsel-static 与 chroot
sudo chroot rootfs_extracted qemu-mipsel-static /usr/sbin/upgrade

用户态仿真的常见失败原因是「缺少动态库」或「调用了主机不存在的 ioctl」。前者用 -L 或 chroot 解决,后者只能转系统态仿真或手工 patch。

系统态仿真(qemu-system) 模拟整个 SoC 与外设,能启动完整的内核与根文件系统。Firmadyne 与 FirmAE 是自动化这一过程的框架:它们从固件里提取内核与文件系统、推断网络配置、构造启动脚本,最终把设备「跑起来」并提供网络访问。

# 本地教学:FirmAE 自动化仿真(对自建靶场固件)
sudo ./run.sh -c -a ./firmware.bin     # -c 清理环境,-a 自动分析并仿真
# 仿真成功后可用 nmap 扫描其网段,直接对 Web 面板做测试

系统态仿真的三个主要障碍:自定义内核(厂商魔改的内核可能缺少 QEMU 支持的驱动,需要换用通用内核或打补丁);NVRAM 依赖(设备从 Flash 的 NVRAM 分区读配置,仿真时需要构造一份默认 NVRAM);硬件外设(Wi-Fi 芯片、GPIO、看门狗在仿真里不存在,程序可能卡在初始化)。FirmAE 相比 Firmadyne 在「解决启动卡死」上有显著改进,成功率更高。

仿真的价值不只是「跑起来」:一旦设备在仿真里运行,就能用常规的 Web 漏洞扫描、命令注入测试、以及动态调试手段去分析它,把嵌入式问题转化为熟悉的 Linux 服务问题。

网络配置是仿真中最容易被忽略的一环。QEMU 默认用用户态网络(SLIRP),设备只能主动外连、外部无法直连它,这对测试 Web 面板是致命的。正确做法是配置 TAP 网桥,把仿真设备接入主机的一个虚拟网段:

# 本地教学:为仿真设备配置 TAP 网络(需要 root)
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up promisc on
sudo ip addr add 192.168.0.1/24 dev tap0
# 在 QEMU 启动参数里加:
# -netdev tap,id=n1,ifname=tap0 -device e1000,netdev=n1
# 之后即可用 nmap 扫描 192.168.0.0/24 找到仿真设备
nmap -sV -p- 192.168.0.100

有了可直连的仿真环境,后续的漏洞验证就能像测一台普通 Linux 服务器一样进行,这一步往往比仿真本身更有价值。

检测与防御:仿真能成功本身就是一种警告——它意味着设备的固件没有做足够的硬件绑定校验。防御手段包括「启动时校验关键外设的指纹」「内核做完整性度量」「关键逻辑放安全 enclave」。当然,这些手段的成本与设备价格成正比,消费级设备通常不做。

9. 防御要点与检测

把前面的攻击面反过来,就是一份 IoT 固件安全要求清单:

攻击面风险防御措施
Flash 可读固件与凭据泄露Flash 加密,密钥存 SoC 内部
UART/JTAG 暴露直接获得 shell 或内存读写熔断 eFuse、隐藏调试口
未签名固件恶意固件刷入安全启动 + 固件签名验证
硬编码凭据批量设备被控每台唯一凭据、出厂强制改密
明文 MQTT/CoAP流量窃听与重放TLS/DTLS + 双向认证
无 ACL通配订阅拿到全量数据按设备粒度配置 ACL
调试服务常开telnet/调试 CGI 被利用发布版移除所有调试接口
OTA 无校验升级劫持签名 + 防回滚(版本号单调递增)

三条工程原则值得强调。第一是**「出厂即安全」:不能指望用户去改默认口令,必须在生产环节为每台设备生成唯一凭据。第二是「信任链从硬件开始」:安全启动(Secure Boot)让 CPU 只执行签名过的 bootloader,是整条信任链的根,没有它,上层所有防护都可能被一次刷机绕过。第三是「最小暴露」**:设备上不该有的服务一律不装,调试接口在量产版一律关闭。

检测侧的能力建设同样重要:网络层监控设备是否在向异常地址发送数据(被控信号)、固件更新是否来自预期源、是否存在异常的 MQTT 订阅行为。这些属于设备侧的持续可观测性,与 移动与 IoT 安全 中讨论的设备生命周期管理直接相关。

权衡取舍

场景优先手段理由局限
有完整 Flash 镜像binwalk -e + unsquashfs一步到位还原文件系统加密段需先解密
只有 OTA 升级包先分析容器格式与密钥唯一入口密钥可能硬编码在别处
Flash 有读保护UART 进 bootloader绕过 Flash 保护需要焊接与串口工具
软件防护极强JTAG 直接读内存绕过一切软件限制需要引脚定位与 SoC 定义
单个二进制分析qemu-user 用户态仿真快,无需完整系统缺库与 ioctl 会失败
要测 Web 面板FirmAE 系统态仿真提供完整网络环境自定义内核可能启动失败
协议不明抓包 + 固件交叉验证字段语义可确定依赖固件里能找到解析函数
无硬件可用纯静态分析零硬件成本加密与动态解密逻辑看不到

选型的判断顺序是:先确定「手上有什么」,再确定「缺什么」。有整镜像就静态解包;缺文件系统就走 OTA 或串口;缺明文代码就上仿真或 JTAG。切忌在没确认架构与端序的情况下直接反编译——那只会浪费时间在垃圾指令上。

常见坑清单

  1. 架构或端序选错:MIPS 大小端混用,反汇编全是非法指令;先用 file 确认,再在 IDA/Ghidra 里显式选型号。
  2. 把 /dev/mtd 当块设备读:字符设备含 OOB 数据,直接 dd 得到的镜像无法挂载;NAND 必须用 nanddump。
  3. binwalk 在加密段上无效:高熵区域扫不出签名,先做熵分析确认加密范围,再找解密密钥。
  4. SquashFS 版本不兼容:新版 unsquashfs 可能不支持老固件的 LZMA 压缩,需要装对应版本或用 -comp 指定。
  5. qemu-user 报「No such file or directory」:实际是找不到动态链接器,用 -L 指定 sysroot 或用 qemu-*-static。
  6. 系统态仿真卡在启动:多为 NVRAM 缺失或外设初始化失败;用 FirmAE 的 -c 清理并用通用内核替换。
  7. UART 波特率猜错:日志全是乱码,常见值是 115200 与 57600,两个都试一遍。
  8. 忽略 /etc/passwd 与 /etc/shadow 的差异:前者可能只有占位符,真正哈希在 shadow;两者都要看。
  9. 只 grep 配置文件而漏了二进制:大量凭据被编译进可执行文件,必须对 /usr/bin、/usr/sbin 做 strings 排查。
  10. 在未授权设备上操作:本文方法仅适用于自建设备、公开 CTF 靶场与自己拥有或书面授权的硬件,其余情形属违法。

小结

固件逆向的核心是「入口决定路线,分层逐级剥离」。拿到整镜像就 binwalk 解包,拿到升级包先解容器,只有串口就进 bootloader;解包后按「文件系统 → 二进制 → 硬件接口 → 协议」四层推进,每层都有成熟的工具与方法。真正拉开差距的不是工具,而是对嵌入式系统整体结构的理解——知道 /proc/mtd 会告诉你分区、知道 U-Boot 的 printenv 里有出厂配置、知道 MIPS 的端序陷阱。

仿真这一环近年进步最大:FirmAE 这类框架把「让固件跑起来」从数天的调试压缩到几十分钟,使得嵌入式设备也能享受常规的漏洞扫描与动态测试。但仿真成功本身也暴露了一个事实——许多设备的固件缺少硬件绑定校验,这既是攻击者的便利,也是防守方需要补的课。

最后回到防御:IoT 安全的问题很少出在「算法不够强」,而是出在「出厂凭据不唯一」「调试接口没关」「固件更新不验签」这些工程细节上。这些问题的修复成本极低,收益极高,是设备厂商最应该优先投入的方向。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「网络安全攻防」更多文章

  1. 流量分析与协议逆向
  2. 椭圆曲线与格攻击
  3. Windows 提权与 AD 内网渗透