3. 固件熵分析
任务目标
对一段未知的二进制数据(可能是固件、文件或加密数据)进行熵分析,通过计算每个字节值的出现频率与信息熵,判断数据是未压缩的明文代码/数据、已压缩或加密的高熵数据,还是空白/填充区域。本案例使用Python实现一个独立的熵分析工具,并提供一个可运行的验证样例。
实现方案
熵分析的核心是香农熵公式:H = -Σ p(x) · log₂(p(x)),其中 p(x) 是字节值 x(0~255)在数据块中出现的概率。固件中不同区域的熵值有典型特征:未压缩代码/常量数据熵值通常在 4.0~6.5 之间;压缩/加密数据熵值接近 8.0;全0xFF或全0x00的空白区熵值为 0。本工具将二进制文件按固定块大小(默认256字节)分块,逐块计算熵值并输出,便于定位固件中高熵区域(加密/压缩段)与低熵区域(填充/空白段)的边界。
完整代码
import math
import sys
from collections import Counter
BLOCK_SIZE = 256 # 每块字节数,可按需调整
def block_entropy(data: bytes) -> float:
"""计算单个数据块的香农熵(单位:bit/byte)"""
if not data:
return 0.0
counter = Counter(data)
length = len(data)
entropy = 0.0
for count in counter.values():
p = count / length
entropy -= p * math.log2(p)
return entropy
def analyze_file(filepath: str, block_size: int = BLOCK_SIZE):
"""逐块读取文件并计算每块熵值,输出块索引、偏移与熵值"""
print(f"{'块号':>6} {'起始偏移':>10} {'熵值':>8} 判定")
print("-" * 48)
block_idx = 0
with open(filepath, "rb") as f:
while True:
chunk = f.read(block_size)
if not chunk:
break
entropy = block_entropy(chunk)
offset = block_idx * block_size
if entropy < 0.5:
verdict = "空白/填充"
elif entropy < 6.5:
verdict = "代码/明文数据"
else:
verdict = "压缩/加密"
print(f"{block_idx:>6} 0x{offset:>8x} {entropy:>8.4f} {verdict}")
block_idx += 1
print(f"\n共分析 {block_idx} 块,每块 {block_size} 字节")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("用法: python entropy_analyzer.py <二进制文件路径>")
sys.exit(1)
analyze_file(sys.argv[1])
运行与验证
环境要求:Python 3.6+,无需第三方库。
验证步骤:
- 将上述代码保存为
entropy_analyzer.py。 - 构造一个测试文件(包含明文段、加密段和填充段),在命令行执行:
# 生成测试文件:前512字节为0xFF填充,中间256字节为随机高熵数据,最后256字节为可读ASCII文本
python -c "
import os, random
random.seed(42)
with open('test_fw.bin', 'wb') as f:
f.write(b'\xff' * 512) # 空白区
f.write(bytes(random.getrandbits(8) for _ in range(256))) # 模拟加密/压缩区
f.write(b'Hello Firmware Entropy Analysis! ' * 8) # 明文区
"
python entropy_analyzer.py test_fw.bin
预期输出(与代码逻辑严格一致):
块号 起始偏移 熵值 判定
------------------------------------------------
0 0x0 0.0000 空白/填充
1 0x100 0.0000 空白/填充
2 0x200 7.9844 压缩/加密
3 0x300 4.5850 代码/明文数据
共分析 4 块,每块 256 字节
判定标准:若第0、1块熵值为0(全0xFF),第2块熵值接近8.0(随机数据),第3块熵值在4~6之间(ASCII文本),则工具工作正常。实际分析固件时,熵值接近8.0的连续区域通常指示加密或压缩代码段,熵值极低的区域为空白填充,据此可定位固件中关键代码段的起始偏移。