使用C#获取托管PE32文件的校验和

时间:2017-05-04 11:59:45

标签: c# .net checksum portable-executable

在我的托管PE文件上使用dumpbin,我可以看到它包含可选标头值中的校验和。

我希望能够获得该校验和,以便我可以存储它并确保没有人正在替换我们的构建机器生成的PE文件。我不担心这个校验和是否加密安全,因为我们只使用它来确定某人是否错误地将PE文件放在错误的位置而且我们没有防止故意攻击。我不知道如何从PE文件中获取校验和。 C#是否有用于获取PE文件校验和的托管API?

如果这个diagram是正确的,我可以使用FileStream并检查PE文件的正确字节,但如果可能的话,我更愿意使用.NET框架来获取这些信息。

以下是命令dumpbin /HEADERS MyDLL.dll中的字段图像。我在我想要检索的田地周围放了一个黄色方块。

enter image description here

EDIT1: 当我说我可以使用一个不安全的C#项目来读取标题时,我感到很复杂。正如@xanatos所指出的,我只能使用文件流来读取标题的字节。

EDIT2: 我删除了关于这是否是PE32(+)文件的问题,因为我能够确定它只是一个PE32文件。

1 个答案:

答案 0 :(得分:0)

所以这是我构建的控制台应用程序,用于从我正在使用的PE文件中获取校验和。

using System;
using System.IO;
using System.Text;

namespace ConsoleApp1
{
   class Program
   {
      public const int PeHeaderOffset = 0x003C;
      public const int CheckSumOffset = 0x0058;

      static void Main(string[] args)
      {
         while (true)
         {
            Console.Write("Path to PE file: ");
            string path = Console.ReadLine();

            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
               byte[] peHeaderPointer = new byte[4];
               byte[] checkSum = new byte[4];

               peHeaderPointer = ReadPeHeaderPointer(fileStream);

               int checkSumOffSet = BitConverter.ToInt32(peHeaderPointer, 0);
               checkSum = ReadChecksum(fileStream, checkSumOffSet);

               string hex = ByteArrayToHexString(checkSum);

               Console.WriteLine($"Checksum: {hex}");
               Console.ReadLine();
            }
         }
      }

      //This will not reverse the bytes because the BitConvert.ToInt32 is already reading it in the correct order.
      public static byte[] ReadPeHeaderPointer(FileStream fileStream)
      {
         byte[] bytes = new byte[4];

         fileStream.Seek(PeHeaderOffset, SeekOrigin.Begin);
         fileStream.Read(bytes, 0, 4);

         return bytes;
      }

      //This reverses the bytes to that this tool will match dumpbin /headers and dotPeek
      public static byte[] ReadChecksum(FileStream fileStream, int offSet)
      {
         byte[] bytes = new byte[4];

         fileStream.Seek(offSet + CheckSumOffset, SeekOrigin.Begin);
         fileStream.Read(bytes, 0, 4);

         bytes = ReverseBytes(bytes);

         return bytes;
      }

      //The PE file seems to be written to the file system in Big Endian 
      //I need to read them in Small Endian to match dumpbin and dotPeek
      public static byte[] ReverseBytes(byte[] bytes)
      {
         byte[] tempBytes = new byte[4];

         tempBytes[0] = bytes[3];
         tempBytes[1] = bytes[2];
         tempBytes[2] = bytes[1];
         tempBytes[3] = bytes[0];

         return tempBytes;
      }

      public static string ByteArrayToHexString(byte[] ba)
      {
         StringBuilder hex = new StringBuilder(ba.Length * 2);
         foreach (byte b in ba)
            hex.AppendFormat("{0:x2}", b);
         return hex.ToString().ToUpper();
      }
   }
}

我不完全确定为什么BitConverter使用Little Endian但是dll是用Big Endian编写的。这就是为什么一些字节数组被反转而其中一些没有被反转的原因。