Search code examples
c#.netportable-executablecoff

Why I didn't get the "PE\0\0"?


From PE specification:

At location 0x3c, the stub has the file offset to the PE signature. This information enables Windows to properly execute the image file, even though it has an MS DOS stub. This file offset is placed at location 0x3c during linking.

2.2. Signature (Image Only)
After the MS DOS stub, at the file offset specified at offset 0x3c, is a 4-byte signature that identifies the file as a PE format image file. This signature is “PE\0\0” (the letters “P” and “E” followed by two null bytes).

I try read these bytes:

using System;
using System.IO;

class Program {
  const String fileName = @".\some_application.exe";
  const Int64 peMarkerPosition = 0x3c;

  static void Main(string[] args) {
    using (FileStream fs = new FileStream(fileName, FileMode.Open,
      FileAccess.Read)) {
      Byte[] marker = new Byte[4];
      fs.Position = peMarkerPosition;
      fs.Read(marker, 0, marker.Length);
      // Now I expect 'marker'has such bytes: "PE\0\0".
      fs.Close();

      foreach (Byte b in marker) {
        Console.Write(Convert.ToChar(b)); // But I see other values...
      }

      Console.WriteLine("\nPress any key for exit...");
      Console.ReadKey();
    }
  }
}

But the marker variable has 0x08, 0x01, 0x00 and x0x00 bytes (first and second are not P and E chars)... Why I get such result?


Solution

  • The PE header itself does not start at offset 0x3C - rather, there's a pointer there (a 32-bit file offset from the beginning of the file) to where the PE header starts.