PeID如何计算熵?

逆向工程 混淆
2021-06-22 08:12:06

我对将二进制文件放入 PeID 时显示的熵字段值很好奇。有人知道它是如何得出这个值的吗?

3个回答

这正是我几年前处理过的一个问题,因为我们还想为以前基于 PeID 的项目实施一个尽可能接近的解决方案。

幸运的是,当时我在 PeID 论坛上发现了一个旧讨论,有人问了同样的问题,并从作者那里得到了一些提示(不是确切的代码)。我仍然有链接,但整个网站已经不复存在:(

那些日子里,我设法重新实​​现了该算法的一个版本,该版本大部分时间都产生了相同的值。原始PeID的熵实现的核心点是:

  • 它确实使用 (Order-0) Shannon 公式(参见 Guntrams 提示)作为核心算法
  • 这样的熵是为每个 PE 部分独立计算的
  • 使用每个PE部分的原始大小(即磁盘上的大小)作为数据量的起点,然后在计算香农熵之前从该值中减去最后的所有0字节。
  • 如果以下条件适用,则在进一步计算中可以忽略部分:
    • 该部分是资源部分
    • 节中没有(剩余)数据(空字节减法后)
  • 总熵是由所有单节熵值的加权组合基于它们的(有效)长度构建的。

通过这种方式,您应该能够获得非常相似的结果。但是预计非标准样本中的偏差(例如损坏/篡改的 PE 文件),即您应该预期并处理诸如不合理的部分大小或所有部分都被排除在计算之外的文件的情况......

我希望这会有所帮助,您现在可以自己成功尝试...;)

您必须询问 PeID 的创建者他使用哪种算法。

标准公式是香农公式:H(x) = - sum i=1 to np(i)*log2(p(i))。

为什么我不能在这里使用 LaTeX?

确定文件熵的一种简单方法是尝试使用标准压缩工具之一对其进行压缩。低熵导致更好的压缩。

特别是当你试图确定哪些部分是代码,哪些是数据时,压缩测试是一个更好的指标。原始香农公式没有考虑是否经常出现多个字节的组合(如函数开始/结束的推送/弹出序列),但压缩算法可以识别这些。

一个通用的熵计算看起来像这样

创建二进制内​​容的直方图最多 256 个不同的字节 (0x0..0xff)
计算(每个字节的概率乘以其计数的对数基数 2)将它们全部加起来并除以文件大小

字节计数频率?记录2 * 计数

0x00 100 (100/文件大小) log 2 (freq[0]?)*count 0x01 045(045/文件大小)日志2(频率[1]?)*计数 ………………………………………………………………………………………………………………………………………………………………………………………………………… 0xfe 020 (020/filesize) log 2 (freq[0xfe]?)*count 0xff 180 (180/文件大小) log 2 (freq[0xfF]?)*count

熵 = ^sum(0x0..0xff)^/文件大小

示例代码

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main (int argc,char *argv[]) {
  if(argc !=2 ){ printf ("usage %s file",argv[0]);return 0;}
  文件 * fp = 0;errno_t err = 0;无符号长 fsize = 0; 浮点数 =0;
  if ((((err = fopen_s(&fp,argv[1],"rb")) == 0) && (fp !=0)){
    fseek(fp,0,SEEK_END);
    fsize = ftell(fp);
    fseek(fp,0,SEEK_SET);
    unsigned char * buff = (unsigned char *)calloc(fsize,sizeof(char));
    如果(增益){
      fread(buff,fsize,sizeof(char),fp);
      fclose(fp);
      无符号长历史[256]={0};
      for(unsigned int i =0; i < fsize; i++){
        hist[buff[i]]++;        
      }
      for(unsigned int i=0;i<256;i++){//log b2 (n) = loge(n)/loge(2)
        ent+=((log((float)hist[i]/fsize)/log((float)2))*hist[i]);
      }
      printf("%f\n",-ent/fsize);
      免费(增益);
    }    
  }   
}

结果

:\>ls -l *
-rw-rw-rw- 1 管理员 0 867 2015-06-30 03:30 entropy.cpp 

:\>..\compile.bat    
:\>if "C:\Program Files\Microsoft Visual Studio 10.0\VC\" == "" ()    
:\>cl /Zi /EHsc /nologo /W4 /analyze *.cpp /link /RELEASE
熵.cpp  

:\>ls -l *
-rw-rw-rw- 1 管理员 0 867 2015-06-30 03:30 entropy.cpp
-rwxrwxrwx 1 管理员 0 135680 2015-06-30 03:32 entropy.exe
-rw-rw-rw- 1 管理员 0 5804 2015-06-30 03:32 entropy.obj
-rw-rw-rw- 1 管理员 0 1297408 2015-06-30 03:32 entropy.pdb
-rw-rw-rw- 1 管理员 0 53248 2015-06-30 03:32 vc100.pdb    

:\>entropy.exe entropy.exe 6.577609

正在修改 powershell,这两行脚本将计算与上面的 c 代码相同的熵

PS > cat .\entropy.ps1
$s=($f=gc -Encoding Byte $args)|measure;$g=$f|group -AsHashTable
 0..255|%{ $e+=(((([math]::Log( $g[$_].count / $s.count)) /
                    [数学]::Log(2.0)) * $g[$_].count)/$s.count)};-$e
PS > .\entropy.ps1 .\entropy.exe

6.57760952796101