详解二进制文件信息熵Entropy的计算

1. 引入

Entropy(熵)能被用于衡量系统的混乱程度,熵值越大,说明混乱程度越高(参考1)。

熵也可以被用在特征工程领域,比如我们提取PE文件的熵值作为一个特征,这种情况下的熵值,一般就说的是“信息熵”。

信息熵也可以被用于衡量PE文件是否加壳(参考2)。PEiD中就有计算熵值的功能,当熵的值超过一定阈值时,则该PE或某段被加壳(Packed)。熵值大,就说明PE文件携带信息量多,就意味着PE文件可能被加壳了。当然,道高一尺魔高一丈,“低熵加壳”又是一个不同的研究方向。

信息熵也可以被用于检测PE病毒(参考3)。当然除了PE文件,其他的二进制文件(比如Mach-O,甚至于pythonscript)也都可以提取并使用信息熵作为特征。

“熵”的计算方式有很多种,包括“信息熵”,“交叉熵”,“相对熵”等等,具体计算过程详见参考4。本文主要讲解“信息熵”的计算,本文提到的“熵”也特指“信息熵”。

2. 信息熵的计算过程举例

信息熵的计算公式如下

在这里插入图片描述

其中,H用于表示信息熵的值,它一般是一个float小数。P(i)表示第i个事件发生的概率。

举个例子,假设天气事件的发生有4中可能性:阴、晴、雨、雪;每种事件的发生概率都为1/4,则P(1)=P(2)=P(3)=P(4)=1/4。

则熵值H=-14P(i)*log2(P(i))=2,所以熵值H等于2。这就是信息熵的计算过程。

在这个例子中,每种天气发生的概率都是相等的(都为1/4),此时能求得信息熵的最大值。即“概率均等时,信息熵值最大”,这也是被证明过的定理(证明过程见参考5)

3. 二进制文件信息熵的计算过程

对二进制文件计算信息熵,首先要将文件读入为byte数组,则数组中每个数据值的大小为0~255,具体代码如下:

with open('cfdbbd60c7dd63db797fb27e1c427077ce1915b8894ef7165d8715304756a7e2', 'rb') as fr:
	bytez = fr.read()

bytez中就存储了读入的byte数组,举例如下

bytez = b'MZ\x90\x00\x03\x00\x00\x00\x04'

这个例子中,MZ是PE文件的标识,0x是十六进制数据。这个bytez数组可以转换为如下等效的int数组:

bytez = [77,90,144,0,3,0,0,0,4]

byte数组中有9个数据,字母’M’的ASCII码值为十进制整数77,'Z’的ASCII码值为90。

我们定义P(i)就是byte数组中各个数值为i的概率,则P(77)=1/9, P(90)=P(144)=P(3)=P(4)=1/9, P(0)=4/9。


H=-(P(77)*log2(P(77))+P(90)*log2(P(90))+P(144)*log2(P(144))+P(3)*log2(P(3))+P(4)log2(P(4))+P(0)log2(P(0)) ) = -(5(1/9)log2(1/9)+(4/9)log2(4/9)) = -(5(1/9)(-3.169925)+(4/9)(-1.169925)) = 2.28103611

所以,对这段9个数据的byte数组计算得到的熵值为 2.28103611。

4. python编程实现信二进制文件息熵计算

根据上一小节的说明,python计算二进制文件信息熵,要先读入二进制文件为byte数组,再对byte数组计算各个数值出现的概率,最终根据信息熵的计算公式将概率值log计算后乘法累加。完整代码如下:

import math

def H(data):
    entropy = 0
    for x in range(256):
        p_x = data.count(x)/len(data)
        if p_x > 0:
            entropy += -p_x*math.log(p_x, 2)
    return entropy


with open('cfdbbd60c7dd63db797fb27e1c427077ce1915b8894ef7165d8715304756a7e2', 'rb') as fr:
	bytez = fr.read()
	print('file H',H(bytez))# file H 4.459983287684002

这个例子最终计算得到的结果为4.459983287684002,这说该二进制文件信息熵值为4.459983287684002。

因为二进制文件读入的数据为byte数组,byte数组中每一个元素值的大小为0255,所以上面计算信息熵的函数H()中直接固定了range(256)来计算0255每个数据值出现的概率,这也简化了程序的编程实现。

调用这个H()函数,来对上小节例子中给定的byte数组,代码和结果如下:

bytez1 = b'MZ\x90\x00\x03\x00\x00\x00\x04'
print('H1',H(bytez1))# 2.2810361125534233
bytez2 = [77,90,144,0,3,0,0,0,4]
print('H2',H(bytez2))# 2.2810361125534233

可以看到,无论是对byte数组bytez1,还是对int数组bytez2,他们的信息熵值都是一样的,这也和上一小节的手工计算结果是完全相等的。

此处使用的信息熵计算H()函数引用自参考6。

5. python第三方库计算信息熵

参考7中有一个pip包pyEntropy可以直接用于计算信息熵,它提供了多种熵值的计算方式

  • Shannon Entropy: shannon_entropy
  • Sample Entropy: sample_entropy
  • Multiscale Entropy: multiscale_entropy
  • Composite Multiscale: Entropy composite_multiscale_entropy
  • Permutation Entropy: permutation_entropy
  • Multiscale Permutation Entropy: multiscale_permutation_entropy
  • Weighted Permutation Entropy: weighted_permutation_entropy

调用它提供的shannon_entropy()就能计算信息熵,示例代码如下:

from pyentrp import entropy as ent

# example1: binary file entropy
with open('cfdbbd60c7dd63db797fb27e1c427077ce1915b8894ef7165d8715304756a7e2', 'rb') as fr:
	bytez = fr.read()
	print('pyentrp H', ent.shannon_entropy(bytez))# 4.459983287684001

# example2: byte array entropy
bytez1 = b'MZ\x90\x00\x03\x00\x00\x00\x04'
print('pyentrp1', ent.shannon_entropy(bytez1))# 2.2810361125534233
# example3: int list entropy
bytez2 = [77,90,144,0,3,0,0,0,4]
print('pyentrp2', ent.shannon_entropy(bytez2))# 2.2810361125534233

这与第3节手动计算,第4节的python代码计算得到的结果是完全一致的。这也验证了手动计算,python源码计算,第三方库的计算这三种信息熵计算方式结果是一致的。

这个库中计算信息熵的源码见参考8。核心部分的源码解释如下,这和信息熵的计算公式是一致的:

def shannon_entropy(time_series):
    data_set = list(set(time_series))#去重
    freq_list = []#计算每个数值出现的概率
    for entry in data_set:
        counter = 0.#每个数值出现的次数
        for i in time_series:#统计每个数值出现的次数
            if i == entry:
                counter += 1
        freq_list.append(float(counter) / len(time_series))#每个数值出现的概率

    # Shannon entropy,信息熵计算过程
    ent = 0.0
    for freq in freq_list:#信息熵计算公式
        ent += freq * np.log2(freq)
    ent = -ent
    return ent

6. 总结

本文给出了二进制文件信息熵计算的细节过程示例,细节过程的python源码,以及第三方库的计算方式(核心源码解释)。

参考

  1. https://zh.wikipedia.org/wiki/%E7%86%B5
  2. https://www.pediy.com/kssd/pediy11/115515.html
  3. 基于信息熵的模糊模式识别病毒检测方法研究
  4. https://charlesliuyx.github.io/2017/09/11/%E4%BB%80%E4%B9%88%E6%98%AF%E4%BF%A1%E6%81%AF%E7%86%B5%E3%80%81%E4%BA%A4%E5%8F%89%E7%86%B5%E5%92%8C%E7%9B%B8%E5%AF%B9%E7%86%B5/
  5. https://blog.csdn.net/feixi7358/article/details/83861858
  6. https://github.com/gcmartinelli/entroPy/blob/master/entropy.py#L8
  7. https://github.com/nikdon/pyEntropy
  8. https://github.com/nikdon/pyEntropy/blob/master/pyentrp/entropy.py#L80
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 二维信息熵是用来衡量图像像素分布的不确定性或信息量的一种度量方法。计算RGB图像下的二维信息熵,可以按照以下步骤进行: 1. 首先,获取RGB图像的每个像素的RGB。 2. 根据RGB计算每个像素的灰度。可以使用如下的公式计算灰度: 灰度 = 0.2989 * R + 0.5870 * G + 0.1140 * B 3. 基于计算得到的灰度,建立一个二维直方图,用来记录每个灰度出现的频次。 4. 遍历二维直方图,计算每个灰度的概率。将每个灰度出现的频次除以图像像素总数,得到每个灰度的概率。 5. 根据计算得到的灰度概率,计算二维信息熵。可以使用如下的公式计算二维信息熵: 二维信息熵 = -∑(p(i,j) * log2(p(i,j))) 其中,p(i,j)代表灰度为(i,j)的像素的概率。 最后,将得到的二维信息熵作为结果输出。 需要注意的是,计算二维信息熵时可能需要对灰度进行归一化处理,确保每个灰度的概率之和为1,以保证计算结果的准确性。 以上就是用Python计算RGB图像下二维信息熵的方法,希望对你有帮助。 ### 回答2: RGB图像的二维信息熵是一种对图像信息多样性的度量。计算RGB图像下二维信息熵的步骤如下: 1. 将RGB图像转换为灰度图像:RGB图像由红色(R)、绿色(G)和蓝色(B)三个通道组成,将这三个通道的像素按照一定权重进行加权平均,将得到的作为对应像素的灰度。 2. 计算灰度图像中每个像素点的灰度级频率:将灰度图像的像素进行统计,得到每个灰度级的频率。可以用直方图来表示。 3. 根据频率计算每个灰度级的概率:将每个灰度级的频率除以总像素数,得到每个灰度级的概率。 4. 计算二维信息熵:使用概率来计算二维信息熵,公式为:entropy = -Σ(p(x, y) * log2(p(x, y))),其中p(x, y)表示灰度级(x, y)的概率。 上述计算过程可以通过Python中的图像处理库(如OpenCV或PIL)和数学库(如numpy)来实现。具体的代码如下所示: ```python import cv2 import numpy as np # 读取RGB图像 image = cv2.imread('image.jpg') # 将RGB图像转换为灰度图像 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 计算灰度图像中每个像素点的灰度级频率 hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256]) hist /= hist.sum() # 将频率归一化为概率 # 计算二维信息熵 entropy = -np.sum(hist * np.log2(hist)) ``` 通过上述代码,我们可以获得RGB图像下的二维信息熵,用来度量图像的多样性。 ### 回答3: 在Python计算RGB图像的二维信息熵可以通过以下步骤实现: 首先,需要导入使用的库: ```python import numpy as np import math import cv2 ``` 然后,加载RGB图像,并将其转换为灰度图像: ```python image = cv2.imread('image.jpg') gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ``` 接下来,计算图像的灰度直方图: ```python histogram = cv2.calcHist([gray_image], [0], None, [256], [0, 256]) ``` 然后,计算每个灰度级的出现概率: ```python total_pixels = gray_image.shape[0] * gray_image.shape[1] probabilities = histogram / total_pixels ``` 接着,计算图像的二维信息熵: ```python entropy = 0 for p in probabilities: if p > 0: entropy -= p * math.log2(p) ``` 最后,打印出计算得到的二维信息熵: ```python print("二维信息熵:", entropy) ``` 完整代码如下: ```python import numpy as np import math import cv2 image = cv2.imread('image.jpg') gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) histogram = cv2.calcHist([gray_image], [0], None, [256], [0, 256]) total_pixels = gray_image.shape[0] * gray_image.shape[1] probabilities = histogram / total_pixels entropy = 0 for p in probabilities: if p > 0: entropy -= p * math.log2(p) print("二维信息熵:", entropy) ``` 请用适当的文件路径替换代码中的'image.jpg',确保该图像存在于指定路径中,你也可以使用其他图像进行测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值