Esempio n. 1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="reader">PE file reader pointing to the start of this section</param>
 /// <param name="runtime">Runtime reader kind</param>
 /// <param name="verify">Verify section</param>
 /// <exception cref="BadImageFormatException">Thrown if verification fails</exception>
 public MetadataHeader(ref DataReader reader, CLRRuntimeReaderKind runtime, bool verify)
 {
     SetStartOffset(ref reader);
     signature = reader.ReadUInt32();
     if (verify && signature != 0x424A5342)
     {
         throw new BadImageFormatException("Invalid metadata header signature");
     }
     majorVersion  = reader.ReadUInt16();
     minorVersion  = reader.ReadUInt16();
     reserved1     = reader.ReadUInt32();
     stringLength  = reader.ReadUInt32();
     versionString = ReadString(ref reader, stringLength, runtime);
     offset2ndPart = (FileOffset)reader.CurrentOffset;
     flags         = (StorageFlags)reader.ReadByte();
     reserved2     = reader.ReadByte();
     streams       = reader.ReadUInt16();
     streamHeaders = new StreamHeader[streams];
     for (int i = 0; i < streamHeaders.Count; i++)
     {
         // Mono doesn't verify all of these so we can't either
         var sh = new StreamHeader(ref reader, throwOnError: false, verify, runtime, out bool failedVerification);
         if (failedVerification || (ulong)sh.Offset + sh.StreamSize > reader.EndOffset)
         {
             sh = new StreamHeader(0, 0, "<invalid>");
         }
         streamHeaders[i] = sh;
     }
     SetEndoffset(ref reader);
 }
 internal StreamHeader(ref DataReader reader, bool throwOnError, bool verify, CLRRuntimeReaderKind runtime, out bool failedVerification)
 {
     failedVerification = false;
     SetStartOffset(ref reader);
     offset     = reader.ReadUInt32();
     streamSize = reader.ReadUInt32();
     name       = ReadString(ref reader, 32, verify, ref failedVerification);
     SetEndoffset(ref reader);
     if (runtime == CLRRuntimeReaderKind.Mono)
     {
         if (offset > reader.Length)
         {
             offset = reader.Length;
         }
         // Mono ignores the size (eg. it can be 0 or max value) so set it to the max possible value
         streamSize = reader.Length - offset;
     }
     if (verify && offset + size < offset)
     {
         failedVerification = true;
     }
     if (throwOnError && failedVerification)
     {
         throw new BadImageFormatException("Invalid stream header");
     }
 }
Esempio n. 3
0
        internal static MetadataBase Load(IntPtr addr, CLRRuntimeReaderKind runtime)
        {
            IPEImage peImage = null;

            // We don't know what layout it is. Memory is more common so try that first.
            try {
                return(Load(peImage = new PEImage(addr, ImageLayout.Memory, true), runtime));
            }
            catch {
                if (!(peImage is null))
                {
                    peImage.Dispose();
                }
                peImage = null;
            }

            try {
                return(Load(peImage = new PEImage(addr, ImageLayout.File, true), runtime));
            }
            catch {
                if (!(peImage is null))
                {
                    peImage.Dispose();
                }
                throw;
            }
        }
Esempio n. 4
0
        static string ReadString(ref DataReader reader, uint maxLength, CLRRuntimeReaderKind runtime)
        {
            ulong endOffset = (ulong)reader.CurrentOffset + maxLength;

            if (runtime == CLRRuntimeReaderKind.Mono)
            {
                endOffset = (endOffset + 3) / 4 * 4;
            }
            if (endOffset > reader.EndOffset)
            {
                throw new BadImageFormatException("Invalid MD version string");
            }
            var  utf8Bytes = new byte[maxLength];
            uint i;

            for (i = 0; i < maxLength; i++)
            {
                byte b = reader.ReadByte();
                if (b == 0)
                {
                    break;
                }
                utf8Bytes[i] = b;
            }
            reader.CurrentOffset = (uint)endOffset;
            return(Encoding.UTF8.GetString(utf8Bytes, 0, (int)i));
        }
Esempio n. 5
0
        /// <summary>
        /// Create a standalone portable PDB <see cref="MetadataBase"/> instance
        /// </summary>
        /// <param name="mdReaderFactory">Metadata stream</param>
        /// <param name="verify"><c>true</c> if we should verify that it's a .NET PE file</param>
        /// <returns>A new <see cref="MetadataBase"/> instance</returns>
        internal static MetadataBase CreateStandalonePortablePDB(DataReaderFactory mdReaderFactory, bool verify)
        {
            const CLRRuntimeReaderKind runtime = CLRRuntimeReaderKind.CLR;
            MetadataBase md = null;

            try {
                var reader   = mdReaderFactory.CreateReader();
                var mdHeader = new MetadataHeader(ref reader, runtime, verify);
                if (verify)
                {
                    foreach (var sh in mdHeader.StreamHeaders)
                    {
                        if (sh.Offset + sh.StreamSize < sh.Offset || sh.Offset + sh.StreamSize > reader.Length)
                        {
                            throw new BadImageFormatException("Invalid stream header");
                        }
                    }
                }

                md = GetMetadataType(mdHeader.StreamHeaders, runtime) switch {
                    MetadataType.Compressed => new CompressedMetadata(mdHeader, true, runtime),
                    MetadataType.ENC => new ENCMetadata(mdHeader, true, runtime),
                    _ => throw new BadImageFormatException("No #~ or #- stream found"),
                };
                md.Initialize(mdReaderFactory);

                return(md);
            }
            catch {
                md?.Dispose();
                throw;
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Create a <see cref="MetadataBase"/> instance
        /// </summary>
        /// <param name="peImage">The PE image</param>
        /// <param name="runtime">Runtime reader kind</param>
        /// <param name="verify"><c>true</c> if we should verify that it's a .NET PE file</param>
        /// <returns>A new <see cref="MetadataBase"/> instance</returns>
        static MetadataBase Create(IPEImage peImage, CLRRuntimeReaderKind runtime, bool verify)
        {
            MetadataBase md = null;

            try {
                var dotNetDir = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[14];
                // Mono doesn't check that the Size field is >= 0x48
                if (dotNetDir.VirtualAddress == 0)
                {
                    throw new BadImageFormatException(".NET data directory RVA is 0");
                }
                var cor20HeaderReader = peImage.CreateReader(dotNetDir.VirtualAddress, 0x48);
                var cor20Header       = new ImageCor20Header(ref cor20HeaderReader, verify && runtime == CLRRuntimeReaderKind.CLR);
                if (cor20Header.Metadata.VirtualAddress == 0)
                {
                    throw new BadImageFormatException(".NET metadata RVA is 0");
                }
                var mdRva = cor20Header.Metadata.VirtualAddress;
                // Don't use the size field, Mono ignores it. Create a reader that can read to EOF.
                var mdHeaderReader = peImage.CreateReader(mdRva);
                var mdHeader       = new MetadataHeader(ref mdHeaderReader, runtime, verify);
                if (verify)
                {
                    foreach (var sh in mdHeader.StreamHeaders)
                    {
                        if ((ulong)sh.Offset + sh.StreamSize > mdHeaderReader.EndOffset)
                        {
                            throw new BadImageFormatException("Invalid stream header");
                        }
                    }
                }

                switch (GetMetadataType(mdHeader.StreamHeaders, runtime))
                {
                case MetadataType.Compressed:
                    md = new CompressedMetadata(peImage, cor20Header, mdHeader, runtime);
                    break;

                case MetadataType.ENC:
                    md = new ENCMetadata(peImage, cor20Header, mdHeader, runtime);
                    break;

                default:
                    throw new BadImageFormatException("No #~ or #- stream found");
                }
                md.Initialize(null);

                return(md);
            }
            catch {
                if (!(md is null))
                {
                    md.Dispose();
                }
                throw;
            }
        }
Esempio n. 7
0
        static MetadataType GetMetadataType(IList <StreamHeader> streamHeaders, CLRRuntimeReaderKind runtime)
        {
            MetadataType?mdType = null;

            if (runtime == CLRRuntimeReaderKind.CLR)
            {
                foreach (var sh in streamHeaders)
                {
                    if (mdType is null)
                    {
                        if (sh.Name == "#~")
                        {
                            mdType = MetadataType.Compressed;
                        }
                        else if (sh.Name == "#-")
                        {
                            mdType = MetadataType.ENC;
                        }
                    }
                    if (sh.Name == "#Schema")
                    {
                        mdType = MetadataType.ENC;
                    }
                }
            }
            else if (runtime == CLRRuntimeReaderKind.Mono)
            {
                foreach (var sh in streamHeaders)
                {
                    if (sh.Name == "#~")
                    {
                        mdType = MetadataType.Compressed;
                    }
                    else if (sh.Name == "#-")
                    {
                        mdType = MetadataType.ENC;
                        break;
                    }
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(runtime));
            }
            if (mdType is null)
            {
                return(MetadataType.Unknown);
            }
            return(mdType.Value);
        }
Esempio n. 8
0
        internal static MetadataBase Load(IntPtr addr, ImageLayout imageLayout, CLRRuntimeReaderKind runtime)
        {
            IPEImage peImage = null;

            try {
                return(Load(peImage = new PEImage(addr, imageLayout, true), runtime));
            }
            catch {
                if (!(peImage is null))
                {
                    peImage.Dispose();
                }
                throw;
            }
        }
Esempio n. 9
0
        internal static MetadataBase Load(byte[] data, CLRRuntimeReaderKind runtime)
        {
            IPEImage peImage = null;

            try {
                return(Load(peImage = new PEImage(data), runtime));
            }
            catch {
                if (!(peImage is null))
                {
                    peImage.Dispose();
                }
                throw;
            }
        }
        internal static MetadataBase Load(string fileName, CLRRuntimeReaderKind runtime)
        {
            IPEImage peImage = null;

            try {
                return(Load(peImage = new PEImage(fileName), runtime));
            }
            catch {
                if (peImage is not null)
                {
                    peImage.Dispose();
                }
                throw;
            }
        }
Esempio n. 11
0
 /// <inheritdoc/>
 internal CompressedMetadata(MetadataHeader mdHeader, bool isStandalonePortablePdb, CLRRuntimeReaderKind runtime)
     : base(mdHeader, isStandalonePortablePdb)
 {
     this.runtime = runtime;
 }
Esempio n. 12
0
 /// <inheritdoc/>
 public CompressedMetadata(IPEImage peImage, ImageCor20Header cor20Header, MetadataHeader mdHeader, CLRRuntimeReaderKind runtime)
     : base(peImage, cor20Header, mdHeader)
 {
     this.runtime = runtime;
 }
Esempio n. 13
0
 internal static MetadataBase Load(IPEImage peImage, CLRRuntimeReaderKind runtime) => Create(peImage, runtime, true);
Esempio n. 14
0
 /// <summary>
 /// Create a <see cref="Metadata"/> instance
 /// </summary>
 /// <param name="peImage">The PE image</param>
 /// <param name="runtime">Runtime reader kind</param>
 /// <param name="verify"><c>true</c> if we should verify that it's a .NET PE file</param>
 /// <returns>A new <see cref="Metadata"/> instance</returns>
 public static Metadata CreateMetadata(IPEImage peImage, CLRRuntimeReaderKind runtime, bool verify) => Create(peImage, runtime, verify);
Esempio n. 15
0
 /// <summary>
 /// Create a <see cref="Metadata"/> instance
 /// </summary>
 /// <param name="peImage">The PE image</param>
 /// <param name="runtime">Runtime reader kind</param>
 /// <returns>A new <see cref="Metadata"/> instance</returns>
 public static Metadata CreateMetadata(IPEImage peImage, CLRRuntimeReaderKind runtime) => Create(peImage, runtime, true);