2017-05-04 31 views
0

在託管PE文件上使用dumpbin我可以看到它包含可選標題值中的校驗和。使用C#獲取託管PE32文件的校驗和

我希望能夠獲得該校驗和,以便我可以存儲它,並確保沒有人正在替換我們的構建機器生成的PE文件。我並不擔心這個校驗和是否具有密碼安全性,因爲我們只是用它來確定是否有人錯誤地將PE文件放在錯誤的位置,而且我們也沒有防範故意的攻擊。我不知道如何去獲取PE文件中的校驗和。 C#有一個用於獲取PE文件校驗和的託管API嗎?

如果diagram是正確的,我可以只使用一個FileStream,檢查PE文件的正確字節,但我更願意使用.NET Framework如果在所有可能得到這個信息。

這裏是從命令dumpbin /HEADERS MyDLL.dll的字段的圖像。我在我想要檢索的場地周圍放置一個黃色正方形。

enter image description here

EDIT1: 我是複雜的事情時,我說,我可以使用不安全的C#項目讀取頭。正如@xanatos指出的,我可以使用文件流來讀取頭部的字節。

EDIT2: 我刪除了關於這是否是PE32(+)文件的問題,因爲我可以確定它只是一個PE32文件。

+0

要打開一個二進制文件(一個EXE或DLL),你不需要「不安全」的代碼......你只需要用'FileStream'打開它。 – xanatos

+0

你知道我從來沒有真正想過這個,那應該只是一個字節流。 –

+0

您可以使用此Windows API:[ImageNtHeader](https://msdn.microsoft.com/en-us/library/windows/desktop/ms680212(v = vs.85).aspx)。它會返回一個指向「IMAGE_NT_HEADERS」的指針,而在OptionalHeader裏面則是「Checksum」。 – xanatos

回答

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編寫的。這就是爲什麼一些字節數組被顛倒的原因,其中一些字符串沒有被反轉。