private void ProcessAndCacheStreams(MemoryBlock metadataRoot) { _metadataStreamKind = MetadataStreamKind.Illegal; foreach (StreamHeader streamHeader in _streamHeaders) { if ((long)streamHeader.Offset + streamHeader.Size > metadataRoot.Length) { throw new BadImageFormatException(); } MemoryBlock block = metadataRoot.GetRange((int)streamHeader.Offset, (int)streamHeader.Size); switch (streamHeader.Name) { case COR20Constants.StringStreamName: if (_stringStream != null) { throw new BadImageFormatException(); } // the first and the last byte of the heap must be zero: if (block.Length == 0 || block.ReadByte(0) != 0 || block.ReadByte(block.Length - 1) != 0) { throw new BadImageFormatException(); } _stringStream = block; break; case COR20Constants.BlobStreamName: if (_blobStream != null) { throw new BadImageFormatException(); } _blobStream = block; break; case COR20Constants.GUIDStreamName: if (_guidStream != null) { throw new BadImageFormatException(); } _guidStream = block; break; case COR20Constants.UserStringStreamName: if (_userStringStream != null) { throw new BadImageFormatException(); } _userStringStream = block; break; case COR20Constants.CompressedMetadataTableStreamName: if (_metadataStreamKind != MetadataStreamKind.Illegal) { throw new BadImageFormatException(); } _metadataStreamKind = MetadataStreamKind.Compressed; _metadataTableStream = block; break; case COR20Constants.UncompressedMetadataTableStreamName: if (_metadataStreamKind != MetadataStreamKind.Illegal) { throw new BadImageFormatException(); } _metadataStreamKind = MetadataStreamKind.UnCompressed; _metadataTableStream = block; break; default: throw new BadImageFormatException(); } } // mandatory streams: if (_stringStream == null || _guidStream == null || _metadataStreamKind == MetadataStreamKind.Illegal) { throw new BadImageFormatException(); } }
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); } }
internal EnCLogTableReader( int numberOfRows, MemoryBlock containingBlock, int containingBlockOffset, MetadataStreamKind metadataStreamKind) { // EnC tables are not allowed in a compressed stream. // However when asked for a snapshot of the current metadata after an EnC change has been applied // the CLR includes the EnCLog table into the snapshot (but not EnCMap). We pretend EnCLog is empty. this.NumberOfRows = (metadataStreamKind == MetadataStreamKind.Compressed) ? 0 : numberOfRows; _TokenOffset = 0; _FuncCodeOffset = _TokenOffset + sizeof(uint); this.RowSize = _FuncCodeOffset + sizeof(uint); this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows)); }
bool ProcessAndCacheStreams( ref MemoryBlock metadataRoot ) //^ requires this.ReaderState >= ReaderState.PEFile; { foreach (StreamHeader streamHeader in this.StreamHeaders) { switch (streamHeader.Name) { case COR20Constants.StringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForStringStream); return false; } this.StringStream.MemoryReader = new MemoryReader( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; case COR20Constants.BlobStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForBlobStream); return false; } this.BlobStream.MemoryReader = new MemoryReader( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; case COR20Constants.GUIDStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForGUIDStream); return false; } this.GUIDStream.MemoryReader = new MemoryReader( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; case COR20Constants.UserStringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForBlobStream); return false; } this.UserStringStream.MemoryReader = new MemoryReader( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; case COR20Constants.CompressedMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForMetadataStream); return false; } this.MetadataStreamKind = MetadataStreamKind.Compressed; this.MetadataTableStream = new MemoryBlock( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; case COR20Constants.UncompressedMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.NotEnoughSpaceForMetadataStream); return false; } this.MetadataStreamKind = MetadataStreamKind.UnCompressed; this.MetadataTableStream = new MemoryBlock( metadataRoot.Buffer + streamHeader.Offset, streamHeader.Size ); break; default: this.ErrorContainer.AddDirectoryError(Directories.Cor20HeaderMetaData, streamHeader.Offset, MetadataReaderErrorKind.UnknownMetadataStream); break; } } return true; }
private void InitializeStreamReaders( ref MemoryBlock metadataRoot, StreamHeader[] streamHeaders, out MetadataStreamKind metadataStreamKind, out MemoryBlock metadataTableStream, out MemoryBlock standalonePdbStream) { metadataTableStream = default(MemoryBlock); standalonePdbStream = default(MemoryBlock); metadataStreamKind = MetadataStreamKind.Illegal; foreach (StreamHeader streamHeader in streamHeaders) { switch (streamHeader.Name) { case COR20Constants.StringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForStringStream"); } break; case COR20Constants.BlobStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForBlobStream"); } this.BlobHeap = new BlobHeap(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), _metadataKind); break; case COR20Constants.GUIDStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForGUIDStream"); } break; case COR20Constants.UserStringStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForBlobStream"); } break; case COR20Constants.CompressedMetadataTableStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForMetadataStream"); } 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("NotEnoughSpaceForMetadataStream"); } 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("NotEnoughSpaceForMetadataStream"); } // the content of the stream is ignored this.IsMinimalDelta = true; break; case COR20Constants.StandalonePdbStreamName: if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size) { throw new BadImageFormatException("NotEnoughSpaceForMetadataStream"); } standalonePdbStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size); break; default: // Skip unknown streams. Some obfuscators insert invalid streams. continue; } } if (IsMinimalDelta && metadataStreamKind != MetadataStreamKind.Uncompressed) { throw new BadImageFormatException("InvalidMetadataStreamFormat"); } }