84 lines
3 KiB
C#
84 lines
3 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
|
|
namespace JD.Reflection
|
|
{
|
|
public static class AssemblyExtensions
|
|
{
|
|
/// <summary>
|
|
/// Returns the right location of the assembly even in a ShadowCopy scenario.
|
|
/// </summary>
|
|
public static string Location(this Assembly assembly)
|
|
{
|
|
string codeBase = assembly.CodeBase;
|
|
UriBuilder builder = new UriBuilder(codeBase);
|
|
string path = Uri.UnescapeDataString(builder.Uri.LocalPath);
|
|
return path;
|
|
}
|
|
|
|
public static bool IsManagedAssembly(string fileName)
|
|
{
|
|
using (Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
|
|
using (BinaryReader binaryReader = new BinaryReader(fileStream))
|
|
{
|
|
if (fileStream.Length < 64)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//PE Header starts @ 0x3C (60). Its a 4 byte header.
|
|
fileStream.Position = 0x3C;
|
|
uint peHeaderPointer = binaryReader.ReadUInt32();
|
|
if (peHeaderPointer == 0)
|
|
{
|
|
peHeaderPointer = 0x80;
|
|
}
|
|
|
|
// Ensure there is at least enough room for the following structures:
|
|
// 24 byte PE Signature & Header
|
|
// 28 byte Standard Fields (24 bytes for PE32+)
|
|
// 68 byte NT Fields (88 bytes for PE32+)
|
|
// >= 128 byte Data Dictionary Table
|
|
if (peHeaderPointer > fileStream.Length - 256)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check the PE signature. Should equal 'PE\0\0'.
|
|
fileStream.Position = peHeaderPointer;
|
|
uint peHeaderSignature = binaryReader.ReadUInt32();
|
|
if (peHeaderSignature != 0x00004550)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// skip over the PEHeader fields
|
|
fileStream.Position += 20;
|
|
|
|
const ushort PE32 = 0x10b;
|
|
const ushort PE32Plus = 0x20b;
|
|
|
|
// Read PE magic number from Standard Fields to determine format.
|
|
var peFormat = binaryReader.ReadUInt16();
|
|
if (peFormat != PE32 && peFormat != PE32Plus)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Read the 15th Data Dictionary RVA field which contains the CLI header RVA.
|
|
// When this is non-zero then the file contains CLI data otherwise not.
|
|
ushort dataDictionaryStart = (ushort) (peHeaderPointer + (peFormat == PE32 ? 232 : 248));
|
|
fileStream.Position = dataDictionaryStart;
|
|
|
|
uint cliHeaderRva = binaryReader.ReadUInt32();
|
|
if (cliHeaderRva == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|