【问题标题】:Search ReadAllBytes for specific values在 ReadAllBytes 中搜索特定值
【发布时间】:2012-02-27 22:53:58
【问题描述】:

我正在编写一个程序,它读取“.exe”文件并将它们的十六进制值存储在一个字节数组中,以便与包含一系列值的数组进行比较。 (就像一个非常简单的病毒扫描程序)

byte[] buffer = File.ReadAllBytes(currentDirectoryContents[j]);

然后我使用 BitConverter 创建了这些值的单个字符串

string hex = BitConverter.ToString(buffer);

下一步是在此字符串中搜索一系列值(定义)并返回正数以进行匹配。这是我遇到问题的地方。我的定义是十六进制值,但在记事本中创建并保存为 defintions.xyz

string[] definitions = File.ReadAllLines(@"C:\definitions.xyz");

我一直在尝试将它们读入字符串数组,并将数组的定义元素与字符串 hex 进行比较

bool[] test = new bool[currentDirectoryContents.Length];

test[j] = hex.Contains(definitions[i]);

这是作业中的一部分,这就是为什么我没有发布我的整个程序代码的原因。上周五之前我没有使用过 C#,所以现在很可能会犯一些愚蠢的错误。

任何建议都非常感谢:)

【问题讨论】:

  • 您能否发布您的定义文件的内容或部分内容。
  • 究竟是什么问题?
  • 您的问题是什么?另一件重要的事情:将字节数组转换为字符串以进行进一步的十六进制比较确实无效。您应该将字节与字节进行比较,并且在此处使用字符串。
  • 你对你正在尝试的事情给出了一个合理的概述......但是:不清楚你在哪里卡住了。怎么了?或没有发生? (我个人同意 ken2k 我不会在这里使用十六进制字符串......但是:这是一个实现细节)
  • Myles:定义文件包含一个我编写的十六进制字符串,因为要扫描的 .exe 文件不是真正的 .exe,而是我以 exe 扩展名保存的记事本文件。

标签: c# executable definitions


【解决方案1】:

目前还不清楚您使用何种格式的定义。 Base64 是一个很好的字节 [] 编码,您可以使用 Convert.ToBase64String 和 Convert.FromBase64String() 快速来回转换。但是您的问题表明字节以十六进制编码。让我们假设一个新的 byte[] { 1, 2, 3, 4} 看起来像“01020304”。然后这个辅助函数将这样一个字符串转换回一个字节[]:

    static byte[] Hex2Bytes(string hex) {
        if (hex.Length % 2 != 0) throw new ArgumentException();
        var retval = new byte[hex.Length / 2];
        for (int ix = 0; ix < hex.Length; ix += 2) {
            retval[ix / 2] = byte.Parse(hex.Substring(ix, 2), System.Globalization.NumberStyles.HexNumber);                
        }
        return retval;
    }

您现在可以使用像 Boyer-Moore 这样的算法进行快速模式搜索。

【讨论】:

  • 文件中的定义没有指定格式。我选择让每个定义都是一个位序列(十六进制)。这是来自对病毒扫描和确定签名方法的研究。现在开始我的签名文件有一个定义: A6 7C FD 1B 45 82 90 1D 6F 3C 8A OF 96 18 A4 C3 4F FF 0F 1D 文件夹中的一个 .exe 将包含这一系列字节,因为它已经被创建在记事本中并保存为exe。定义文件没有特定的文件格式。我现在一直在使用随机扩展。
  • 嗯,有一个指定的格式是相当重要的。我发布的代码应该很接近,由于空格,您需要使用 3 而不是 2。
  • 现在已经解决了,感谢您花时间告诉我一个可能的解决方案!
【解决方案2】:

我希望您明白这是一种非常低效的方法。但除此之外,你应该这样做:

bool[] test = new bool[currentDirectoryContents.Length];
for(int i=0;i<test.Length;i++){
  byte[] buffer = File.ReadAllBytes(currentDirectoryContents[j]);
  string hex = BitConverter.ToString(buffer);
  test[i] = ContainsAny(hex, definitions);
}

bool ContainsAny(string s, string[] values){
  foreach(string value in values){
    if(s.Contains(value){
      return true;
    }
  }
  return false;
}

如果你可以使用 LINQ,你可以这样做:

var test = currentDirectoryContents.Select(
             file=>definitions.Any(
               definition => 
                 BitConverter.ToString(
                   File.ReadAllBytes(file)
                 ).Contains(definition)
             )
           ).ToArray();

另外,请确保您的定义文件的格式与BitConverter.ToString() 的输出相匹配:大写,用破折号分隔每个编码字节:

12-AB-F0-34
54-AC-FF-01-02 

【讨论】:

  • 我确实理解代码的低效率,但我不是一个经验丰富的编码人员,并且很高兴在查看改进之前编写工作代码。我意识到我的整个代码都在工作,但是我正在阅读的 exe 文件中包含的代码已经是十六进制的。所以我的代码只是将每个字节转换为不同的十六进制值。现在解决了。感谢大家的贡献和建议!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-27
  • 2011-06-10
相关资源
最近更新 更多