private void InitializeStreamReaders(ref MemoryBlock metadataRoot, StreamHeader[] streamHeaders, out MemoryBlock metadataTableStream) { metadataTableStream = default(MemoryBlock); foreach (StreamHeader streamHeader in streamHeaders) { switch (streamHeader.Name) { case COR20Constants.StringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForStringStream); } this.StringStream = new StringStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), this.metadataKind); break; case COR20Constants.BlobStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForBlobStream); } this.BlobStream = new BlobStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), this.metadataKind); break; case COR20Constants.GUIDStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForGUIDStream); } this.GuidStream = new GuidStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size)); break; case COR20Constants.UserStringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForBlobStream); } this.UserStringStream = new UserStringStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size)); break; case COR20Constants.CompressedMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForMetadataStream); } this.metadataStreamKind = MetadataStreamKind.Compressed; metadataTableStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size); break; case COR20Constants.UncompressedMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForMetadataStream); } this.metadataStreamKind = MetadataStreamKind.Uncompressed; metadataTableStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size); break; case COR20Constants.MinimalDeltaMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForMetadataStream); } // the content of the stream is ignored this.IsMinimalDelta = true; break; default: // Skip unknown streams. Some obfuscators insert invalid streams. continue; } } if (IsMinimalDelta && metadataStreamKind != MetadataStreamKind.Uncompressed) { throw new BadImageFormatException(MetadataResources.InvalidMetadataStreamFormat); } }
/// <summary> /// Reads stream headers described in Ecma-335 24.2.2 Stream header /// </summary> private StreamHeader[] ReadStreamHeaders(ref BlobReader memReader) { // storage header: memReader.ReadUInt16(); int streamCount = memReader.ReadInt16(); var streamHeaders = new StreamHeader[streamCount]; for (int i = 0; i < streamHeaders.Length; i++) { if (memReader.RemainingBytes < COR20Constants.MinimumSizeofStreamHeader) { throw new BadImageFormatException(MetadataResources.StreamHeaderTooSmall); } streamHeaders[i].Offset = memReader.ReadUInt32(); streamHeaders[i].Size = memReader.ReadInt32(); streamHeaders[i].Name = memReader.ReadUtf8NullTerminated(); bool aligned = memReader.TryAlign(4); if (!aligned || memReader.RemainingBytes == 0) { throw new BadImageFormatException(MetadataResources.NotEnoughSpaceForStreamHeaderName); } } return streamHeaders; }