public unsafe void GetString_Empty() { var blobHeapData = new byte[] { 0, // 0 1, // 1: blob size (byte)'a', // 2 6, // 3: blob size 0, // 4: separator 0, // 5: part #1 0, // 6: part #2 0, // 7: part #3 0, // 8: part #4 0, // 9: part #5 }; fixed(byte *ptr = blobHeapData) { var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335); var handle = DocumentNameBlobHandle.FromOffset(3); var name = blobHeap.GetDocumentName(handle); Assert.Equal(@"", name); Assert.True(blobHeap.DocumentNameEquals(handle, @"", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"a", ignoreCase: false)); } }
public unsafe void GetString_Errors() { var blobHeapData = new byte[] { 0, // 0 2, // 1: blob size 0x80, // 2: separator 0, // 3: part #1 }; fixed(byte *ptr = blobHeapData) { var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335); var handle = DocumentNameBlobHandle.FromOffset(1); Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(handle)); Assert.False(blobHeap.DocumentNameEquals(handle, "", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, "a", ignoreCase: false)); Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(default(DocumentNameBlobHandle))); Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(DocumentNameBlobHandle.FromOffset(8))); } }
public MetadataHeaps() { Guids = new GuidHeap(); Blobs = new BlobHeap(); Strings = new StringHeap(); UserStrings = new UserStringHeap(); Tables = new TableHeap(this); }
void WriteBlobToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val) { BlobHeap bh = wtr.BaseStream.Root[MetadataStreamType.Blob].Heap as BlobHeap; if (bh.Stream.Length > ushort.MaxValue) { wtr.Write((uint)(val as BlobToken).Token.Value); } else { wtr.Write((ushort)(val as BlobToken).Token.Value); } }
TokenTypes IMetadataProvider.Read(TokenTypes token, out byte[] result) { if (TokenTypes.Blob == (TokenTypes.TableMask & token)) { BlobHeap bheap = (BlobHeap)_streams[(int)HeapType.Blob]; result = bheap.ReadBlob(ref token); } else { throw new ArgumentException(@"Invalid token for a blob.", @"token"); } return(token); }
public uint CreateAssemblyRef(IAssembly assembly) { var rid = TablesHeap.AssemblyRefTable.Create(); var row = new RawAssemblyRefRow((ushort)assembly.Version.Major, (ushort)assembly.Version.Minor, (ushort)assembly.Version.Build, (ushort)assembly.Version.Revision, (uint)assembly.Attributes, BlobHeap.Create(GetPublicKeyOrTokenBytes(assembly.PublicKeyOrToken)), StringsHeap.Create(assembly.Name), StringsHeap.Create(assembly.Culture), BlobHeap.Create((assembly as AssemblyRef)?.Hash)); TablesHeap.AssemblyRefTable.Set(rid, ref row); return(rid); }
public uint CreateAssemblyRef(IAssembly assembly) { var rid = TablesHeap.AssemblyRefTable.Create(); var row = TablesHeap.AssemblyRefTable.Get(rid); row.MajorVersion = (ushort)assembly.Version.Major; row.MinorVersion = (ushort)assembly.Version.Minor; row.BuildNumber = (ushort)assembly.Version.Build; row.RevisionNumber = (ushort)assembly.Version.Revision; row.Flags = (uint)assembly.Attributes; row.PublicKeyOrToken = BlobHeap.Create(GetPublicKeyOrTokenBytes(assembly.PublicKeyOrToken)); row.Name = StringsHeap.Create(assembly.Name); row.Locale = StringsHeap.Create(assembly.Culture); row.HashValue = BlobHeap.Create((assembly as AssemblyRef)?.Hash); return(rid); }
public unsafe void GetString1() { var blobHeapData = new byte[] { 0, // 0 2, // 1: blob size (byte)'a', // 2 (byte)'b', // 3 3, // 4: blob size (byte)'x', // 5 (byte)'y', // 6 (byte)'z', // 7 3, // 8: blob size (byte)'\\', // 9: separator 1, // 10: part #1 4, // 11: part #2 }; fixed(byte *ptr = blobHeapData) { var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335); var handle = DocumentNameBlobHandle.FromOffset(8); var name = blobHeap.GetDocumentName(handle); Assert.Equal(@"ab\xyz", name); Assert.True(blobHeap.DocumentNameEquals(handle, @"ab\xyz", ignoreCase: false)); Assert.True(blobHeap.DocumentNameEquals(handle, @"Ab\xYz", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, @"", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"a", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"ab", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\x", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\xy", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"abc\xyz", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, @"Ab\xYzz", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, @"Ab\xYz\", ignoreCase: true)); } }
static object ReadBlobToken(int col, MetadataTable tbl, MetadataReader rdr, uint[] lens) { if (rdr.BaseStream.Root[MetadataStreamType.Blob] == null) { rdr.ReadUInt16(); return(BlobToken.Null); } BlobHeap bh = rdr.BaseStream.Root[MetadataStreamType.Blob].Heap as BlobHeap; uint tkn; if (bh.Stream.Length > ushort.MaxValue) { tkn = rdr.ReadUInt32(); } else { tkn = rdr.ReadUInt16(); } return(bh.Resolve(new MetadataToken(tkn))); }
public unsafe void GetString_NonAscii() { var blobHeapData = new byte[] { 0, // 0 3, // 1: blob size 0xe1, // 2: U+1234 in UTF8 0x88, // 3 0xb4, // 4 1, // 5: blob size (byte)'b', // 6 4, // 7: blob size (byte)'a', // 8: separator 5, // 9: part #1 1, // 10: part #2 5, // 11: part #3 }; fixed(byte *ptr = blobHeapData) { var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335); var handle = DocumentNameBlobHandle.FromOffset(7); var name = blobHeap.GetDocumentName(handle); Assert.Equal("ba\u1234ab", name); Assert.True(blobHeap.DocumentNameEquals(handle, "ba\u1234ab", ignoreCase: false)); Assert.True(blobHeap.DocumentNameEquals(handle, "BA\u1234AB", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, "b\u1234ab", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, "a\u1234ab", ignoreCase: false)); Assert.False(blobHeap.DocumentNameEquals(handle, "ba\u1234abb", ignoreCase: false)); } }
/// <summary> /// We want to know if a given method implements a redirected interface. /// For example, if we are given the method RemoveAt on a class "A" /// which implements the IVector interface (which is redirected /// to IList in .NET) then this method would return true. The most /// likely reason why we would want to know this is that we wish to hide /// (mark private) all methods which implement methods on a redirected /// interface. /// </summary> /// <param name="memberRef">The declaration token for the method</param> /// <param name="isIDisposable"> /// Returns true if the redirected interface is <see cref="IDisposable"/>. /// </param> /// <returns>True if the method implements a method on a redirected interface. /// False otherwise.</returns> private bool ImplementsRedirectedInterface(MemberReferenceHandle memberRef, out bool isIDisposable) { isIDisposable = false; EntityHandle parent = MemberRefTable.GetClass(memberRef); TypeReferenceHandle typeRef; if (parent.Kind == HandleKind.TypeReference) { typeRef = (TypeReferenceHandle)parent; } else if (parent.Kind == HandleKind.TypeSpecification) { BlobHandle blob = TypeSpecTable.GetSignature((TypeSpecificationHandle)parent); BlobReader sig = new BlobReader(BlobHeap.GetMemoryBlock(blob)); if (sig.Length < 2 || sig.ReadByte() != (byte)CorElementType.ELEMENT_TYPE_GENERICINST || sig.ReadByte() != (byte)CorElementType.ELEMENT_TYPE_CLASS) { return(false); } EntityHandle token = sig.ReadTypeHandle(); if (token.Kind != HandleKind.TypeReference) { return(false); } typeRef = (TypeReferenceHandle)token; } else { return(false); } return(GetProjectionIndexForTypeReference(typeRef, out isIDisposable) >= 0); }
public unsafe void GetString_IgnoreSeparatorCase() { var blobHeapData = new byte[] { 0, // 0 1, // 1: blob size (byte)'b', // 2 3, // 3: blob size (byte)'a', // 4: separator 1, // 5: part #1 1, // 6: part #2 }; fixed(byte *ptr = blobHeapData) { var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335); var handle = DocumentNameBlobHandle.FromOffset(3); var name = blobHeap.GetDocumentName(handle); Assert.Equal("bab", name); Assert.True(blobHeap.DocumentNameEquals(handle, "bab", ignoreCase: false)); Assert.True(blobHeap.DocumentNameEquals(handle, "BAB", ignoreCase: true)); Assert.True(blobHeap.DocumentNameEquals(handle, "bAb", ignoreCase: true)); Assert.True(blobHeap.DocumentNameEquals(handle, "BaB", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, "", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, "B", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, "bA", ignoreCase: true)); Assert.False(blobHeap.DocumentNameEquals(handle, "bAbA", ignoreCase: true)); } }
DotNetHeap[] CreateENCHeaps() { var list = new List <DotNetHeap>(); StringsHeap stringsHeap = null; USHeap usHeap = null; BlobHeap blobHeap = null; GUIDHeap guidHeap = null; TablesHeap tablesHeap = null; foreach (var ssh in storageStreamHeaders) { var span = new HexBufferSpan(file.Buffer, ssh.DataSpan); switch (ssh.Name.ToUpperInvariant()) { case "#STRINGS": if (stringsHeap == null) { stringsHeap = new StringsHeapImpl(span); list.Add(stringsHeap); continue; } break; case "#US": if (usHeap == null) { usHeap = new USHeapImpl(span); list.Add(usHeap); continue; } break; case "#BLOB": if (blobHeap == null) { blobHeap = new BlobHeapImpl(span); list.Add(blobHeap); continue; } break; case "#GUID": if (guidHeap == null) { guidHeap = new GUIDHeapImpl(span); list.Add(guidHeap); continue; } break; case "#~": // Only if #Schema is used case "#-": if (tablesHeap == null && span.Length >= TablesHeapImpl.MinimumSize) { tablesHeap = new TablesHeapImpl(span, TablesHeapType.ENC); list.Add(tablesHeap); continue; } break; } list.Add(new UnknownHeapImpl(span)); } return(list.ToArray()); }
internal MetaDataRoot m_mdr; // MetaData Root table /********************************************************************************************************************* * 1) Parse the MetaData Root table. * * 2) Initialize the various heaps. * * 3) Initialize "m_oldNameHash", "m_classTree", and "m_freeSpaceList". * * 4) Initialize the various BitArrays. * * 5) Set the total numbers of the elements (types, methods, fields, properties, events, and parameters). *********************************************************************************************************************/ internal MetaData(ref byte[] buf) { int i, ptHeapIndex = -1; Exception toBeThrown; m_buffer = buf; // Ok. Now we can build a reader and a writer over the memory m_buffer. MemoryStream memStream = new MemoryStream(m_buffer); BinaryReader reader = new BinaryReader(memStream); BinaryWriter writer = new BinaryWriter(memStream); AllHeaders all = new AllHeaders(ref reader); NTHeader nth = all.m_ntHeader; SectionHeader[] sh = all.m_sectionHeaders; #if DEBUG0 Console.WriteLine("Runtime Header Data Directory"); Console.WriteLine("rva: " + nth.m_DataDirectory[14].RVA + "; size: " + nth.m_DataDirectory[14].Size + Environment.NewLine); Console.WriteLine("offset to MetaData section: " + (long)(nth.m_DataDirectory[14].RVA + 8)); #endif // Read the RVA of the physical MetaData section from the Runtime Header Data Directory. reader.BaseStream.Seek((long)(nth.m_DataDirectory[14].RVA + 8), SeekOrigin.Begin); m_startPos = reader.ReadUInt64(); // Theoretically, startPos can be 64 bit long, but in practice, 32 bits are enough. // TODO : Check the docs. The following assertion will fail. // Debug.Assert((startPos >> 32) == 0); m_startPos = m_startPos & 0xffffffff; // use the least significant 4 bytes as the offset m_mdr = new MetaDataRoot(ref reader, ref m_buffer, m_startPos); // We need to initialize the #Strings heap and the #Blob heap before dealing with the #~ heap. for (i = 0; i < m_mdr.m_numStreams; i++) { if (m_mdr.m_streamHeaders[i].name.Equals("#Strings\0")) { m_strHeap = new StringHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#Blob\0")) { m_blobHeap = new BlobHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size); } else if (m_mdr.m_streamHeaders[i].name.Equals("#~\0") || m_mdr.m_streamHeaders[i].name.Equals("#-\0")) { ptHeapIndex = i; } } if (ptHeapIndex != -1) { m_heap = new PTHeap(ref reader, ref writer, ref m_strHeap, m_startPos + m_mdr.m_streamHeaders[ptHeapIndex].offset); } else { toBeThrown = new InvalidFileFormat("Invalid CIL binary file format."); throw toBeThrown; } }
public override void VisitBlobHeap(BlobHeap heap) { this.asm.StaticArray(moduleName + " BlobHeap", heap.Data); }
public static void Write(IWriterError helper, Metadata systemMetadata, DataWriter writer, BlobHeap blobHeap, IList <PdbImport> imports) { var blobWriter = new ImportScopeBlobWriter(helper, systemMetadata, blobHeap); blobWriter.Write(writer, imports); }
ImportScopeBlobWriter(IWriterError helper, Metadata systemMetadata, BlobHeap blobHeap) { this.helper = helper; this.systemMetadata = systemMetadata; this.blobHeap = blobHeap; }
public virtual void VisitBlobHeap(BlobHeap heap) { }
internal BlobToken(BlobHeap h) : base(h) { }
DotNetHeap[] CreateCompressedHeaps() { var list = new List <DotNetHeap>(); StringsHeap stringsHeap = null; USHeap usHeap = null; BlobHeap blobHeap = null; GUIDHeap guidHeap = null; TablesHeap tablesHeap = null; PdbHeap pdbHeap = null; for (int i = storageStreamHeaders.Length - 1; i >= 0; i--) { var ssh = storageStreamHeaders[i]; var span = new HexBufferSpan(file.Buffer, ssh.DataSpan); switch (ssh.Name) { case "#Strings": if (stringsHeap == null) { stringsHeap = new StringsHeapImpl(span); list.Add(stringsHeap); continue; } break; case "#US": if (usHeap == null) { usHeap = new USHeapImpl(span); list.Add(usHeap); continue; } break; case "#Blob": if (blobHeap == null) { blobHeap = new BlobHeapImpl(span); list.Add(blobHeap); continue; } break; case "#GUID": if (guidHeap == null) { guidHeap = new GUIDHeapImpl(span); list.Add(guidHeap); continue; } break; case "#~": if (tablesHeap == null && span.Length >= TablesHeapImpl.MinimumSize) { tablesHeap = new TablesHeapImpl(span, TablesHeapType.Compressed); list.Add(tablesHeap); continue; } break; case "#!": list.Add(new HotHeapImpl(span)); continue; case "#Pdb": if (pdbHeap == null && span.Length >= PdbHeapImpl.MinimumSize) { pdbHeap = new PdbHeapImpl(span); list.Add(pdbHeap); continue; } break; } list.Add(new UnknownHeapImpl(span)); } list.Reverse(); return(list.ToArray()); }
private void CacheBlobs(BlobHeap blobHeap) { Constructor.Log("Caching .NET blob signatures."); blobHeap.ReadAllBlobs(); }
/// <summary> /// Reads a blob heap entry. /// </summary> /// <param name="token">The token of the blob heap entry to read.</param> /// <returns></returns> byte[] IMetadataProvider.ReadBlob(HeapIndexToken token) { BlobHeap bheap = (BlobHeap)_streams[(int)HeapType.Blob]; return(bheap.ReadBlob(token)); }
internal MetadataRow(MetadataTable tbl, bool needInit) : base(tbl) { vals = new object[tbl.TableDef.Columns.Length]; par = tbl; if (!needInit) { return; } BlobHeap bh = tbl.Heap.Stream.Root[MetadataStreamType.Blob].Heap as BlobHeap; StringsHeap sh = tbl.Heap.Stream.Root[MetadataStreamType.Strings].Heap as StringsHeap; GUIDHeap gh = tbl.Heap.Stream.Root[MetadataStreamType.GUID].Heap as GUIDHeap; foreach (MetadataColumn col in tbl.Columns) { if (col.Type is Type) { if ((col.Type as Type).IsEnum) { this[col.Index] = Enum.ToObject(col.Type as Type, 0); } else { switch ((col.Type as Type).FullName) { case "System.Byte": this[col.Index] = (byte)0; break; case "System.UInt16": this[col.Index] = (ushort)0; break; case "System.UInt32": this[col.Index] = (uint)0; break; case "NetPE.Core.Rva": this[col.Index] = (Rva)0; break; case "NetPE.Core.Metadata.BlobToken": this[col.Index] = bh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0)); break; case "NetPE.Core.Metadata.GUIDToken": this[col.Index] = gh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0)); break; case "NetPE.Core.Metadata.StringToken": this[col.Index] = sh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0)); break; } } } else if (col.Type is TableType) { this[col.Index] = new TableToken(tbl.Heap, new MetadataToken((MetadataTokenType)(TableType)col.Type, 0)); } else if (col.Type is CodedIndex) { this[col.Index] = new TableToken(tbl.Heap, new MetadataToken((MetadataTokenType)CodedIndexDefs.MdCodedIndexDefs[(CodedIndex)col.Type].TableTypes[0].Key, 0)); } } }
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"); } }