0%
毅种循环

模块 76 - 二进制文件熵减技术

恶意软件开发课程 - 二进制文件熵减技术


模块 76 - 二进制文件熵减技术#

二进制文件熵减技术#

简介#

恶意软件通常会对其 Payload 进行加密或压缩,以隐藏真正的恶意代码。虽然这能有效应对静态字符串搜索,但会引入一个新的副作用:高熵值 (High Entropy)

💡 初学者提示:什么是熵(Entropy)?

类比理解: 想象一下你的书房桌面:

  • 低熵(有序):所有的书都整齐排列,文具归类。即便闭着眼,你也能大致猜出哪里是哪里。对于计算机来说,这意味着数据是有规律、易于预测的(如普通的英文文档或简单的代码)。
  • 高熵(混乱):桌面上洒满了打碎的拼图块、撕碎的纸屑和各种杂乱的零件。你无法从一堆纸屑中预测下一片碎纸长什么样。

在恶意软件中:加密后的 Shellcode 看起来就像一堆完全随机的乱码(纸屑)。如果一个普通的记事本程序里突然混进了一大块“乱码”,杀软就会立刻怀疑这里面藏着不想被人看的东西。

熵 (Entropy) 是指给定数据集中的随机程度。信息论中存在多种熵的度量方式,如 吉布斯熵 (Gibbs Entropy)、玻尔兹曼熵 (Boltzmann Entropy) 等。但在网络安全领域,“熵”通常特指 香农熵 (Shannon’s Entropy),其产生的值在 0 到 8 之间。数据越随机,熵值就越高。

恶意软件的二进制文件通常比普通文件具有更高的熵值。高熵通常是数据被压缩、加密或加壳的指标,恶意软件常利用这些手段来隐匿特征。由于加密或压缩会生成大量随机化程度极高的输出,这解释了为何恶意文件的熵值普遍偏高。

下图对比了合法软件与恶意样本的熵值。可以看到,大多数恶意文件的熵值在 7.2 到 8 之间,而良性文件大多分布在 5.6 到 6.8 之间。该图引用自文章 Threat Hunting with File Entropy

良型文件与恶意软件熵值对比
良型文件与恶意软件熵值对比

本模块的目标是学习如何降低恶意文件的熵值,使其维持在与良性文件相似的、可接受的范围内。

1. 测量文件的熵#

为了降低熵,首先要学会如何计算它。像 pestudioSigcheck 这样的工具都可以显示文件的熵。

为了简单起见,本课程提供了一个 Python 脚本 EntropyCalc.py 用于计算熵。此外,通过 -pe 标志,它可以计算 PE 文件各个节(Section)的熵。

EntropyCalc.py 核心逻辑#

该脚本使用香农熵公式来计算给定缓冲区的随机性:

def calc_entropy(buffer):
    if isinstance(buffer, str):
        buffer = buffer.encode()
    entropy = 0
    for x in range(256):
        # 计算每个字节出现的概率
        p = (float(buffer.count(bytes([x])))) / len(buffer)
        if p > 0:
            # 香农熵公式
            entropy += - p * math.log(p, 2)
    return entropy
python

2. 算法选择#

如前所述,恶意软件通常由于加密或编码导致熵值升高。一种解决方法是更换加密算法,因为不同的算法生成的密文随程度不同。

  • 单字节 XOR:加密过程几乎不会改变输出数据的总体熵值。缺点是加密强度极弱,容易被逆向。
  • 混淆替代加密:使用之前介绍过的 IPv4fuscationIPv6fuscationMacfuscationUUIDfuscation。这些算法输出的数据具有某种程度的“组织性”和“秩序”。由于数据集中存在类似的字节模式,其熵值会显著低于完全随机的加密字节流。

3. 插入英文文本字符串#

这种方法在各种真实病毒样本中都有发现。在代码中插入大量随机的英文长句或单词。

原理:英文字母只有 26 个(算上大小写共 52 个),这意味着每个字节能存储的可能性被限制在一个很小的范围内,远低于加密算法生成的 0-255 的随机可能性。

4. 使用固定字节进行填充 (Padding)#

这是一种更简单且极有效的减熵方法:在加密的 Payload 后面追加大量相同的、固定的字节。

原理:完全相同的字节其熵值为 0。将零熵数据与高熵 Payload 混合,会显著拉低整体的平均分。

如下图所示,Msfvenom 生成的 shellcode 熵值为 5.88325。在追加了 285 个 0xEA 字节后,整体熵值锐降至 3.77597

填充减熵演示
填充减熵演示

注:此方法的缺点是会明显增加 Payload 的体积。

5. 移除 C 运行时库 (CRT)#

CRT(C Runtime)库是 C 语言的标准接口,包含了内存管理(memcpy)、文件操作(fopen)等常用函数。

移除 CRT 库可以显著降低最终可执行文件的熵值。我们将在后续模块专门讨论移除 CRT 的具体步骤。下图展示了代码完全相同的 Hello World 程序,在有/无 CRT 库的情况下的熵值对比:

CRT 库对熵值的影响对比
CRT 库对熵值的影响对比

6. 工程化工具:EntropyReducer#

由 MalDev Academy 团队开发的 EntropyReducer 工具可以自动化这一过程。它使用专门的链表算法,在 Payload 的每两个固定大小的数据块之间插入 空字节 (Null Bytes),从而精准控制并降低熵值。

您可以参考该项目的 README 了解其详细实现细节。


🎯 总结#

在本模块中,我们学习了:

  1. 分值意识: 理解了香农熵 (0-8) 是如何成为防御端判定“加密/压缩”行为的核心依据。
  2. 真假混合: 学会了通过注入有序字符串或全同字节(零熵注入)来稀释高熵区域。
  3. 精简哲学: 认识到移除庞大的 CRT 库不仅能减小体积,还能有效净化二进制文件的特征。

📚 下一步学习

下一个模块将探讨 Module 77 - Brute Force Decryption。我们将学习一种更硬核的隐藏密钥方式:不存储密钥,而是让程序在运行时“猜”出来。