Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Using the information from the answers from Luke and Marty I was able to do this. Here is the console program I wrote that checks that an assembly is compiled with the specified platform. It's messy because I haven't cleaned it up, but it works.</p> <pre><code>using System; using System.IO; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; namespace MyApp { static class App { [STAThread] static void Main(string[] args) { if (args.GetUpperBound(0) != 1) { Console.WriteLine("Usage:"); Console.WriteLine(" checkPlatform [anycpu|x86|x64] filename"); return; } CheckPlatform(args[0], args[1]); } public static bool CheckPlatform(string targetPlatform, string filename) { //see http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx //offset to PE header is always at 0x3C //PE header starts with "PE\0\0" = 0x50 0x45 0x00 0x00 //followed by 2-byte machine type field (see document above for enum) FileStream fs = new FileStream(filename, FileMode.Open, System.IO.FileAccess.Read); BinaryReader br = new BinaryReader(fs); fs.Seek(0x3c, SeekOrigin.Begin); Int32 peOffset = br.ReadInt32(); fs.Seek(peOffset, SeekOrigin.Begin); UInt32 peHead = br.ReadUInt32(); if(peHead!=0x00004550) // "PE\0\0", little-endian throw new Exception("Can't find PE header"); int machineType = (int) br.ReadUInt16(); // The number that identifies the type of target machine. int numberOfSections = (int)br.ReadUInt16(); // The number of sections. This indicates the size of the section table, which immediately follows the headers. int timeDateStamp = (int)br.ReadUInt32(); // The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created. int pointerToSymbolTable = (int)br.ReadUInt32(); // The file offset of the COFF symbol table, or zero if no COFF symbol table is present. This value should be zero for an image because COFF debugging information is deprecated. int numberOfSymbols = (int)br.ReadUInt32(); // The number of entries in the symbol table. This data can be used to locate the string table, which immediately follows the symbol table. This value should be zero for an image because COFF debugging information is deprecated. int sizeOfOptionalHeader = (int)br.ReadUInt16(); // The size of the optional header, which is required for executable files but not for object files. This value should be zero for an object file. For a description of the header format, see section 3.4, “Optional Header (Image Only).” int characteristics = (int)br.ReadUInt16(); // The flags that indicate the attributes of the file. For specific flag values, see section 3.3.2, “Characteristics.” int sectionoffset = (int)fs.Position + sizeOfOptionalHeader; int magic = (int)br.ReadUInt16(); /* Now we are at the end of the PE Header and from here, the PE Optional Headers starts... To go directly to the datadictionary, we'll increase the stream’s current position to with 96 (0x60). 96 because, 28 for Standard fields 68 for NT-specific fields From here DataDictionary starts...and its of total 128 bytes. DataDictionay has 16 directories in total, doing simple maths 128/16 = 8. So each directory is of 8 bytes. In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size. btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :) */ ushort dataDictionaryStart; uint[] dataDictionaryRVA = new uint[16]; uint[] dataDictionarySize = new uint[16]; dataDictionaryStart = Convert.ToUInt16 (Convert.ToUInt16(fs.Position) + 0x60); fs.Position = dataDictionaryStart - 2; for (int i = 0; i &lt; 15; i++) { dataDictionaryRVA[i] = br.ReadUInt32(); dataDictionarySize[i] = br.ReadUInt32(); } if (dataDictionaryRVA[14] == 0) { MessageBox.Show("This is NOT a valid CLR File!!"); return false; } fs.Position = sectionoffset; int[] SVirtualAddress = new int[numberOfSections]; int[] SSizeOfRawData = new int[numberOfSections]; int[] SPointerToRawData = new int[numberOfSections]; for ( int i = 0 ; i &lt;numberOfSections; i++) { br.ReadBytes(12); SVirtualAddress[i] = br.ReadInt32(); SSizeOfRawData[i] = br.ReadInt32(); SPointerToRawData[i] = br.ReadInt32(); br.ReadBytes(16); } fs.Position = ConvertRVA(numberOfSections, SVirtualAddress, SSizeOfRawData, SPointerToRawData, dataDictionaryRVA[14]); int size = br.ReadInt32(); int majorruntimeversion = br.ReadInt16(); int minorruntimeversion = br.ReadInt16(); int metadatarva = br.ReadInt32(); int metadatasize = br.ReadInt32(); int corflags = br.ReadInt32(); br.Close(); fs.Close(); bool is32bit = false; if ((characteristics &amp; 0x0100) == (0x0100)) is32bit = true; string s = ""; if (magic == 0x10b) s += "Magic=PE\r\n"; else if (magic == 0x20b) s += "Magic=PE+\r\n"; else s += "Magic=" + magic.ToString("X") + "\r\n"; s += "machineType=" + machineType.ToString() + "\r\n"; s += "is32bit=" + is32bit.ToString() + "\r\n"; s += "numberOfSections=" + numberOfSections.ToString() + "\r\n"; s += "sizeOfOptionalHeader=" + sizeOfOptionalHeader.ToString() + "\r\n"; s += "Characteristics=" + characteristics.ToString() + "\r\n"; s += "corflags=" + corflags.ToString("X") + "\r\n"; //· anycpu: PE = PE32 and 32BIT = 0 //· x86: PE = PE32 and 32BIT = 1 //· 64-bit: PE = PE32+ and 32BIT = 0 if ((corflags &amp; 2) == 2) is32bit = true; else is32bit = false; string platform = "Unknown"; if (magic == 0x10b) { // PE32 if (is32bit) platform = "x86"; else platform = "anycpu"; } else if (magic == 0x20b) { // PE32+ if (is32bit == false) platform = "x64"; } if (platform.ToUpper() != targetPlatform.ToUpper()) { MessageBox.Show(filename + " is " + platform + ", not " + targetPlatform + ".\r\n" + s); return false; } return true; } public static long ConvertRVA(int numberOfSections, int[] SVirtualAddress, int[] SSizeOfRawData, int[] SPointerToRawData, long rva) { int i; for ( i = 0 ; i &lt;numberOfSections; i++) { if ( rva &gt;= SVirtualAddress [i] &amp;&amp; ( rva &lt; SVirtualAddress[i] + SSizeOfRawData [i] )) break ; } return SPointerToRawData [i] + ( rva - SVirtualAddress[i] ); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload