2017-05-04 3 views
0

マネージドPEファイルでdumpbinを使用すると、オプションのヘッダ値にチェックサムが含まれていることがわかります。C#を使ってマネージドPE32ファイルのチェックサムを取得

私はそれを保存できるようにチェックサムを取得して、私たちのビルドマシンで生成されたPEファイルを誰も置き換えないようにしたいと考えています。このチェックサムが暗号的に安全であれば、私たちは間違ってPEファイルを間違った場所に置いたかどうかを判断するためにしか使用していないので、私は心配していません。私はPEファイルからチェックサムを取得する方法についてはわかりません。 C#には、PEファイルのチェックサムを取得するための管理APIがありますか?

diagramが正しい場合は、FileStreamを使用してPEファイルの正しいバイトを調べることができますが、可能であれば.NETフレームワークを使用することをお勧めします。

ここには、コマンド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がリトルエンディアンを使用しているが、dllがビッグエンディアンで書かれている理由は完全にはわかりません。そのため、バイト配列の一部が逆転され、そのうちのいくつかが逆転していないのです。

関連する問題