4. 固件加密与解密初步
任务说明
本案例面向已获取一份经过加密的IoT固件镜像的场景。目标是通过分析固件头部结构、识别加密算法与密钥管理方式,利用已知密钥或实现中的漏洞完成解密,还原出可分析的明文固件。案例使用一个模拟的嵌入式固件加密流程,重点演示AES-128-CBC模式下因密钥硬编码和IV固定导致的可破解性。
环境与依赖
- Python 3.8+,无需第三方库(仅使用标准库
hashlib、os、struct)
- 示例固件镜像文件:
firmware.bin(由下方生成脚本产生)
固件加密实现(模拟目标设备)
以下代码模拟了目标设备固件更新包的制作过程。实际分析时,我们只能拿到加密后的 firmware.bin,但通过逆向或文档泄露可获知:加密算法为AES-128-CBC,密钥硬编码在引导加载程序中,IV固定为全零。
```python
# 固件加密模拟(用于生成目标文件,实际分析中不执行此代码)
import hashlib
import os
import struct
def pad(data: bytes) -> bytes:
"""PKCS7填充到16字节块"""
pad_len = 16 - (len(data) % 16)
return data + bytes([pad_len] * pad_len)
def aes_cbc_encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
"""极简AES-CBC实现(仅用于演示,非生产级)"""
# 实际设备使用硬件AES引擎,此处用hash模拟分组加密
# 注意:此实现仅用于生成可复现的测试镜像,不代表真实AES
from hashlib import sha256
state = iv
out = b''
for i in range(0, len(data), 16):
block = data[i:i+16]
# 模拟加密:block XOR sha256(key + state) 的前16字节
keystream = sha256(key + state).digest()[:16]
cipher_block = bytes(a ^ b for a, b in zip(block, keystream))
out += cipher_block
state = cipher_block
return out
# 生成测试固件
key = b'HardcodedKey1234' # 硬编码密钥(16字节)
iv = b'\x00' * 16 # 固定IV
plain_firmware = b'\x7fELF' + b'\x00' * 12 + b'FakeFirmwarePayload' * 100 # 模拟固件
padded = pad(plain_firmware)
encrypted = aes_cbc_encrypt(padded, key, iv)
# 写入文件(头部前16字节为未加密的元数据)
header = struct.pack('
解密分析代码
以下为实际分析脚本。它读取 firmware.bin,解析头部获取明文长度,然后使用已知密钥和IV执行AES-CBC解密,最后验证解密结果是否为ELF文件头。
```python
import hashlib
import struct
import sys
def aes_cbc_decrypt(cipher_data: bytes, key: bytes, iv: bytes) -> bytes:
"""与加密过程对应的解密实现"""
from hashlib import sha256
state = iv
plain = b''
for i in range(0, len(cipher_data), 16):
block = cipher_data[i:i+16]
keystream = sha256(key + state).digest()[:16]
plain_block = bytes(a ^ b for a, b in zip(block, keystream))
plain += plain_block
state = block # CBC模式:下一个块的state是当前密文块
return plain
def unpad(data: bytes) -> bytes:
"""移除PKCS7填充"""
if not data:
return data
pad_len = data[-1]
if pad_len < 1 or pad_len > 16:
raise ValueError("无效填充")
return data[:-pad_len]
def analyze_firmware(filepath: str):
# 1. 读取文件
with open(filepath, 'rb') as f:
raw = f.read()
# 2. 解析头部(前16字节:4字节明文长度 + 12字节保留)
if len(raw) < 16:
print("文件过短,无法解析")
return
plain_len = struct.unpack('
运行与验证
- 先运行加密模拟脚本生成
firmware.bin(实际场景中此文件来自设备固件提取)
- 运行解密分析脚本:
python3 decrypt_firmware.py
- 通过条件:输出包含
[+] 解密成功 和 [+] 验证通过,且生成 firmware_decrypted.bin 文件,其前4字节为 7f 45 4c 46(ELF魔数)
漏洞要点
- 硬编码密钥:密钥
HardcodedKey1234 直接存储在引导程序中,可通过静态分析提取
- 固定IV:IV全零,导致相同明文块产生相同密文块,泄露数据模式
- 无完整性校验:固件未签名,解密后无法验证镜像来源与完整性
实际固件分析中,若密钥未硬编码,可尝试从引导程序内存转储、JTAG调试接口或漏洞利用(如未授权shell)中提取。本案例演示了最基础的场景:一旦获得密钥,CBC模式解密即可完整还原固件。