引言 #
IoT 设备的安全问题日益突出——大量设备使用硬编码凭证、未加密固件和过时的软件组件。本文将演示完整的 IoT 固件分析流程。
固件提取 #
硬件接口提取 #
┌────────────────────────────────────────────────┐
│ IoT 设备常见调试接口 │
├────────────────────────────────────────────────┤
│ │
│ UART (TX/RX/GND/VCC) — 终端访问 │
│ JTAG — 内存直接读取 │
│ SPI Flash — 芯片级固件提取 │
│ SWD — ARM 调试接口 │
│ │
└────────────────────────────────────────────────┘UART 连接 #
# 识别 UART 引脚
# 1. 使用万用表找 GND (连通性模式)
# 2. 示波器识别 TX (有数据活动)
# 3. 波特率扫描
# 连接 UART 并捕获 Console
screen /dev/ttyUSB0 115200
# 或使用 minicom
minicom -D /dev/ttyUSB0 -b 115200
# 常见 UART 输出:
# U-Boot 2010.06 (Sep 15 2023 - 12:00:00)
# DRAM: 64 MB
# Flash: 16 MB
# Hit any key to stop autoboot: 1SPI Flash 读取 #
# 使用 flashrom 读取 SPI Flash
flashrom -p ch341a_spi -r firmware_dump.bin -c "W25Q128.V"
# 或使用 Bus Pirate
# 连接: CS→CS, CLK→CLK, MOSI→MOSI, MISO→MISO, GND→GND固件解析 #
binwalk 分析 #
# 基本提取
binwalk firmware_dump.bin
# 输出示例:
# DECIMAL HEXADECIMAL DESCRIPTION
# ─────────────────────────────────────
# 0 0x0 Squashfs filesystem
# 32768 0x8000 LZMA compressed data
# 1048576 0x100000 JFFS2 filesystem
# 8388608 0x800000 U-Boot firmware
# 递归提取所有嵌入文件
binwalk -Me firmware_dump.bin
# 提取后的目录结构:
# _firmware_dump.bin.extracted/
# ├── 0/ # Squashfs 文件系统
# ├── 8000/ # LZMA 压缩数据
# └── 100000/ # JFFS2 数据文件系统分析 #
# 进入提取的文件系统
cd _firmware_dump.bin.extracted/squashfs-root
# 查找敏感文件
find . -type f \( -name "*.conf" -o -name "*.cfg" -o -name "*.xml" \) | head -20
# 搜索硬编码凭证
grep -r "password" . --include="*.conf" --include="*.sh"
grep -r "root:" ./etc/shadow
# 检查 SUID 二进制文件
find . -perm -4000 -type f
# 查看启动脚本
cat ./etc/init.d/rcS
cat ./etc/inittab常见硬编码凭证发现 #
# 在 web 配置文件中发现的硬编码密码
$ grep -r "admin" ./www/
./www/cgi-bin/login.cgi:admin_password="admin123"
# 在配置文件中发现的 SSH 密钥
$ find ./etc -name "id_rsa*"
./etc/dropbear/id_rsa
# 在二进制中发现的 WiFi 密码
$ strings firmware_dump.bin | grep -i "wpa"
WPA-PSK(TKIP)+WPA2-PSK(AES)
ssid="IoT_Network"
psk="password123"漏洞挖掘 #
使用 FirmAE 自动化分析 #
# 安装 FirmAE
git clone https://github.com/pr0me/ FirmAE.git
cd FirmAE && bash setup.sh
# 启动自动化 Fuzzing
python3 fuzz.py -d -i firmware_dump.bin
# FirmAE 功能:
# - 自动 QEMU 模拟运行固件
# - 基于 AFL 的模糊测试
# - CVE 数据库匹配QEMU 模拟运行 #
# 提取内核并模拟
# 1. 从固件中提取内核
binwalk -e firmware_dump.bin
cd _firmware_dump.bin.extracted/
# 2. 找到 vmlinux
file */kernel
# 3. 使用 QEMU 模拟
qemu-system-mipsel \
-M malta \
-kernel vmlinux \
-hda rootfs.ext2 \
-append "root=/dev/sda console=ttyS0" \
-netdev user,id=net0 -device ne2k_pci,netdev=net0 \
-nographic自动化漏洞检测 #
#!/usr/bin/env python3
"""
IoT 固件常见漏洞扫描器
检测硬编码凭证、弱加密、不安全的网络服务
"""
import os
import re
from pathlib import Path
class FuzzerAnalyzer:
"""固件分析器"""
VULN_PATTERNS = {
'hardcoded_password': [
rb'password\s*=\s*["\']([^"\']+)["\']',
rb'passwd\s*:\s*["\']([^"\']+)["\']',
rb'admin_pwd\s*=\s*["\']([^"\']+)["\']',
],
'weak_encryption': [
rb'TKIP', # 已知不安全的 WiFi 加密
rb'WEP', # 完全废弃的 WiFi 加密
rb'RC4', # 不推荐使用的流密码
],
'insecure_services': [
rb'telnet', # 明文传输
rb'ftpd', # FTP 服务
rb'dropbear.*-w', # SSH 密码认证
],
'default_credentials': [
rb'admin:admin',
rb'root:root',
rb'admin:password',
rb'user:user',
],
}
def __init__(self, firmware_path: str):
self.firmware_path = Path(firmware_path)
self.findings = {k: [] for k in self.VULN_PATTERNS.keys()}
def scan_file(self, filepath: Path) -> None:
"""扫描单个文件"""
try:
with open(filepath, 'rb') as f:
content = f.read()
except (PermissionError, IOError):
return
for vuln_type, patterns in self.VULN_PATTERNS.items():
for pattern in patterns:
matches = re.finditer(pattern, content, re.IGNORECASE)
for match in matches:
self.findings[vuln_type].append({
'file': str(filepath),
'pattern': pattern.decode('utf-8', errors='ignore'),
'match': match.group(0).decode('utf-8', errors='ignore'),
})
def scan_directory(self, directory: Path) -> dict:
"""递归扫描目录"""
for filepath in directory.rglob('*'):
if filepath.is_file():
self.scan_file(filepath)
return self.findings
def report(self) -> str:
"""生成报告"""
output = []
total = 0
for vuln_type, findings in self.findings.items():
if findings:
output.append(f"\n{'='*60}")
output.append(f"[{vuln_type.upper()}] 发现 {len(findings)} 个结果")
output.append(f"{'='*60}")
for f in findings[:10]: # 限制输出
output.append(f" File: {f['file']}")
output.append(f" Match: {f['match']}")
output.append("")
total += len(findings)
output.insert(0, f"总计发现 {total} 个潜在安全问题")
return '\n'.join(output)
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <firmware_extracted_dir>")
sys.exit(1)
analyzer = FuzzerAnalyzer(sys.argv[1])
findings = analyzer.scan_directory(Path(sys.argv[1]))
print(analyzer.report())加密固件的处理 #
部分厂商会对固件进行加密保护(IP 保护)。当安全研究员需要分析这些加密固件时,如果知道密码或密码为常见弱口令,可以使用密码恢复工具。猫密网 (Catpasswd) 支持 ZIP/RAR 等常见压缩格式的密码恢复,对于加密的固件压缩包或项目归档文件,可以利用其云端分布式 GPU 集群进行密码恢复,无需本地配置环境。对于安全研究者而言,这是一个高效获取加密固件访问权限的辅助工具。
总结 #
- 硬件接口是突破口——UART/JTAG 可直接获取固件
- binwalk 是基础工具——快速识别和提取文件系统
- 自动化扫描不可少——硬编码凭证和弱加密普遍存在
- 模拟运行加速分析——QEMU 让固件动态分析成为可能
参考资源
- binwalk: https://github.com/ReFirmLabs/binwalk
- FirmAE: https://github.com/pr0me/FirmAE
- QEMU: https://www.qemu.org
- flashrom: https://flashrom.org