固件和IoT逆向
固件和IoT逆向
本文适合
已经理解 文件头、文件尾与真实类型、字符串、交叉引用与控制流 和基础 Linux 目录结构的学习者。学完你能:从固件镜像中提取 rootfs,识别架构和高价值文件,定位 Web 后台、脚本、硬编码密钥或二进制校验逻辑
一句话判断
题目给 firmware.bin、rootfs.img、squashfs、uImage、路由器/摄像头升级包,或者出现 MIPS/ARM 嵌入式程序,就按固件和 IoT 逆向处理。
固件题的第一步不是打开 IDA,而是先拆包、建目录地图、找入口服务。
题目中常见信号
文件名:
firmware.bin
update.bin
rootfs.img
openwrt.bin
uImage
camera_update.pkg
router_backup.tar文件识别信号:
Squashfs filesystem
U-Boot uImage
LZMA compressed data
gzip compressed data
ELF 32-bit MSB executable, MIPS
ELF 32-bit LSB executable, ARM高价值目录:
/etc/passwd
/etc/shadow
/etc/init.d/
/etc/config/
/www/
/var/www/
/htdocs/
/bin/
/sbin/
/usr/bin/
/usr/sbin/高价值关键词:
flag
admin
password
passwd
token
secret
telnet
debug
system(
popen(
eval
nvram核心概念
固件通常是多个部分拼在一起:
bootloader + kernel + rootfs + config + appCTF 最常考的是 rootfs 里的内容:
- Web 管理后台。
- 默认账号密码。
- CGI / Lua / PHP 脚本。
- BusyBox 工具。
- MIPS/ARM 后端服务。
- 配置文件和启动脚本。
固件逆向不是单一方向,它经常和 命令注入、路径穿越、任意文件读取与下载、流量包基础、字符串、交叉引用与控制流 交叉。
最小分析流程
1. 文件识别和拆包
file firmware.bin
binwalk firmware.bin
strings -a firmware.bin | head提取:
binwalk -e firmware.bin如果自动提取失败:
binwalk -Me firmware.bin或根据 binwalk 输出的偏移手动切:
dd if=firmware.bin of=part.squashfs bs=1 skip=OFFSET
unsquashfs part.squashfs2. 建目录地图
进入提取目录:
find . -maxdepth 3 -type f | sort | less优先看:
find . -path "*/etc/*" -o -path "*/www/*" -o -path "*/bin/*" -o -path "*/sbin/*"3. 识别架构
find . -type f -perm -111 -exec file {} \; | head -50看到:
ELF 32-bit MSB executable, MIPS说明后续反汇编要选 MIPS 大端。
4. 搜敏感词和危险调用
rg -n "flag|admin|password|passwd|token|secret|debug|telnet" .
rg -n "system\\(|popen\\(|eval|exec|nvram|getenv" .对二进制:
strings -a ./usr/sbin/httpd | rg -i "flag|admin|password|system|popen|cgi|login"5. 找启动入口
看启动脚本:
ls etc/init.d
rg -n "httpd|boa|lighttpd|uhttpd|telnet|dropbear" etc init.d . 2>$null目标是知道哪个程序提供 Web 或服务接口。
最小验证示例
验证固件里是否有硬编码账号
rg -n "admin|root|password|passwd" squashfs-root/etc squashfs-root/www如果发现:
www/login.cgi: if user == "admin" and pass == "c2VjcmV0"尝试解码:
python - <<'PY'
import base64
print(base64.b64decode("c2VjcmV0"))
PY如果输出 secret,就可以尝试登录或继续追登录逻辑。
验证命令注入点
如果脚本里有:
ping -c 1 $host最小验证 payload:
127.0.0.1;id
127.0.0.1&&cat /flag如果是二进制调用 system(),用 strings 找参数格式,再进 Ghidra 看 system 的交叉引用。
常见利用 / 解题路线
路线总览:
路线一:静态找 flag 或密钥
适合入门固件题:
rg -n "flag|ctf|secret|token" squashfs-root如果 flag 被编码,继续用 编码、哈希与加密 判断 Base64、Hex、XOR。
路线二:Web 后台漏洞
- 找
/www、/htdocs、CGI。 - 找登录逻辑和路由。
- 搜
system、popen、文件读取。 - 构造 Web 参数利用。
路线三:逆向后端服务
- 找
httpd、service、daemon。 file看架构。strings找成功失败提示。- 用 Ghidra 选择正确架构导入。
- 追登录、校验、解密函数。
路线四:模拟运行
如果静态信息不够:
qemu-mips-static ./usr/sbin/service
qemu-arm-static ./bin/app很多程序依赖 rootfs 路径、环境变量或 NVRAM。运行失败时不要马上放弃,先看缺什么文件。
常见失败原因
- 只看 binwalk 第一层:固件里可能多层压缩,使用
binwalk -Me。 - 忽略端序:MIPS 有大端和小端,架构选错伪代码会很怪。
- 只搜 flag:真实线索可能是密码、token、debug 开关或密钥。
- 运行二进制失败就放弃:嵌入式程序常依赖 rootfs、环境变量和配置文件。
- 把 Web 后台当普通网页测:固件里能直接读源码和配置,要先静态审计。
- 没有记录提取偏移和路径:复盘时无法证明 flag 从哪里来。
迷你案例
题目给:
router_firmware.bin第一步:
binwalk router_firmware.bin看到:
0x00120000 Squashfs filesystem, little endian, version 4.0提取:
binwalk -e router_firmware.bin
cd _router_firmware.bin.extracted/squashfs-root第二步搜敏感词:
rg -n "flag|admin|password|system\\(|popen\\(" .发现:
www/cgi-bin/ping.cgi: system("ping -c 1 " + query["host"])
etc/config/web: admin_pass=YWRtaW4xMjM=第三步解码密码:
python - <<'PY'
import base64
print(base64.b64decode("YWRtaW4xMjM=").decode())
PY得到:
admin123第四步确认 ping.cgi 参数可控。构造:
host=127.0.0.1;cat /flag如果题目提供模拟环境,就登录后台触发;如果没有环境,WP 中要说明静态证据:
- 参数
host没有过滤。 - 拼接进
system()。 - 固件配置泄露后台密码。
- 组合后可通过后台命令注入读取 flag。