using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using AsmResolver.Collections; using AsmResolver.IO; using AsmResolver.PE.Builder; using AsmResolver.PE.Certificates; using AsmResolver.PE.Code; using AsmResolver.PE.Debug; using AsmResolver.PE.Debug.Builder; using AsmResolver.PE.DotNet; using AsmResolver.PE.DotNet.Cil; using AsmResolver.PE.DotNet.Metadata; using AsmResolver.PE.DotNet.Metadata.Tables; using AsmResolver.PE.DotNet.ReadyToRun; using AsmResolver.PE.DotNet.Resources; using AsmResolver.PE.DotNet.VTableFixups; using AsmResolver.PE.Exceptions; using AsmResolver.PE.Exports; using AsmResolver.PE.Exports.Builder; using AsmResolver.PE.File; using AsmResolver.PE.Imports; using AsmResolver.PE.Imports.Builder; using AsmResolver.PE.Platforms; using AsmResolver.PE.Relocations; using AsmResolver.PE.Relocations.Builder; using AsmResolver.PE.Tls; using AsmResolver.PE.Win32Resources; using AsmResolver.PE.Win32Resources.Builder; using AsmResolver.Patching; using AsmResolver.Shims; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: AssemblyCompany("AsmResolver.PE")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © Washi 2016-2024")] [assembly: AssemblyDescription("PE image models for the AsmResolver executable file inspection toolsuite.")] [assembly: AssemblyFileVersion("6.0.0.0")] [assembly: AssemblyInformationalVersion("6.0.0-beta.1+f70da7936c203b4ecfb19c9ad71d08c6eb4b5bd3")] [assembly: AssemblyProduct("AsmResolver.PE")] [assembly: AssemblyTitle("AsmResolver.PE")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Washi1337/AsmResolver")] [assembly: AssemblyVersion("6.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace AsmResolver.PE { public class PEImage { private IList? _imports; private readonly LazyVariable _exports; private readonly LazyVariable _resources; private readonly LazyVariable _exceptions; private IList? _relocations; private readonly LazyVariable _dotNetDirectory; private IList? _debugData; private readonly LazyVariable _tlsDirectory; private CertificateCollection? _certificates; public virtual PEFile? PEFile => null; public string? FilePath { get; protected set; } public MachineType MachineType { get; set; } = (MachineType)332; public Characteristics Characteristics { get; set; } = (Characteristics)34; public DateTime TimeDateStamp { get; set; } = new DateTime(1970, 1, 1); public OptionalHeaderMagic PEKind { get; set; } = (OptionalHeaderMagic)267; public SubSystem SubSystem { get; set; } = (SubSystem)3; public DllCharacteristics DllCharacteristics { get; set; } = (DllCharacteristics)34112; public ulong ImageBase { get; set; } = 4194304uL; public IList Imports { get { if (_imports == null) { Interlocked.CompareExchange(ref _imports, GetImports(), null); } return _imports; } } public ExportDirectory? Exports { get { return _exports.GetValue(this); } set { _exports.SetValue(value); } } public ResourceDirectory? Resources { get { return _resources.GetValue(this); } set { _resources.SetValue(value); } } public IExceptionDirectory? Exceptions { get { return _exceptions.GetValue(this); } set { _exceptions.SetValue(value); } } public IList Relocations { get { if (_relocations == null) { Interlocked.CompareExchange(ref _relocations, GetRelocations(), null); } return _relocations; } } public DotNetDirectory? DotNetDirectory { get { return _dotNetDirectory.GetValue(this); } set { _dotNetDirectory.SetValue(value); } } public IList DebugData { get { if (_debugData == null) { Interlocked.CompareExchange(ref _debugData, GetDebugData(), null); } return _debugData; } } public TlsDirectory? TlsDirectory { get { return _tlsDirectory.GetValue(this); } set { _tlsDirectory.SetValue(value); } } public CertificateCollection Certificates { get { if (_certificates == null) { Interlocked.CompareExchange(ref _certificates, GetCertificates(), null); } return _certificates; } } public static PEImage FromFile(string filePath) { return FromFile(PEFile.FromFile(filePath)); } public static PEImage FromFile(string filePath, PEReaderParameters readerParameters) { return FromFile(PEFile.FromFile(readerParameters.FileService.OpenFile(filePath)), readerParameters); } public static PEImage FromBytes(byte[] bytes) { return FromFile(PEFile.FromBytes(bytes)); } public static PEImage FromBytes(byte[] bytes, PEReaderParameters readerParameters) { return FromFile(PEFile.FromBytes(bytes), readerParameters); } public static PEImage FromModuleBaseAddress(IntPtr hInstance) { return FromModuleBaseAddress(hInstance, (PEMappingMode)1, new PEReaderParameters()); } public static PEImage FromModuleBaseAddress(IntPtr hInstance, PEReaderParameters readerParameters) { return FromFile(PEFile.FromModuleBaseAddress(hInstance), readerParameters); } public static PEImage FromModuleBaseAddress(IntPtr hInstance, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile(PEFile.FromModuleBaseAddress(hInstance, mode), readerParameters); } public static PEImage FromDataSource(IDataSource dataSource, PEMappingMode mode = 0) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(dataSource, dataSource.BaseAddress, 0u, (uint)dataSource.Length); return FromReader(in reader, mode); } public static PEImage FromDataSource(IDataSource dataSource, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(dataSource, dataSource.BaseAddress, 0u, (uint)dataSource.Length); return FromReader(in reader, mode, readerParameters); } public static PEImage FromReader(in BinaryStreamReader reader, PEMappingMode mode = 0) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile(PEFile.FromReader(ref reader, mode)); } public static PEImage FromReader(in BinaryStreamReader reader, PEMappingMode mode, PEReaderParameters readerParameters) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromFile(PEFile.FromReader(ref reader, mode), readerParameters); } public static PEImage FromFile(IInputFile inputFile) { return FromFile(inputFile, new PEReaderParameters()); } public static PEImage FromFile(IInputFile inputFile, PEReaderParameters readerParameters) { return FromFile(PEFile.FromFile(inputFile), readerParameters); } public static PEImage FromFile(PEFile peFile) { return FromFile(peFile, new PEReaderParameters()); } public static PEImage FromFile(PEFile peFile, PEReaderParameters readerParameters) { return new SerializedPEImage(peFile, readerParameters); } public PEImage() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) _exports = new LazyVariable((Func)((PEImage x) => x.GetExports())); _resources = new LazyVariable((Func)((PEImage x) => x.GetResources())); _exceptions = new LazyVariable((Func)((PEImage x) => x.GetExceptions())); _dotNetDirectory = new LazyVariable((Func)((PEImage x) => x.GetDotNetDirectory())); _tlsDirectory = new LazyVariable((Func)((PEImage x) => x.GetTlsDirectory())); } public PEFile ToPEFile(IPEFileBuilder builder) { return builder.CreateFile(this); } protected virtual IList GetImports() { return new List(); } protected virtual ExportDirectory? GetExports() { return null; } protected virtual ResourceDirectory? GetResources() { return null; } protected virtual IExceptionDirectory? GetExceptions() { return null; } protected virtual IList GetRelocations() { return new List(); } protected virtual DotNetDirectory? GetDotNetDirectory() { return null; } protected virtual IList GetDebugData() { return new List(); } protected virtual TlsDirectory? GetTlsDirectory() { return null; } protected virtual CertificateCollection GetCertificates() { return new CertificateCollection(); } } public class PEReaderContext : IErrorListener { public PEFile File { get; } public PEReaderParameters Parameters { get; } public PEReaderContext(PEFile file) : this(file, new PEReaderParameters()) { } public PEReaderContext(PEFile file, PEReaderParameters parameters) { File = file; Parameters = parameters; } public RelocationParameters GetRelocation(ulong offset, uint rva) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) return new RelocationParameters(File.OptionalHeader.ImageBase, offset, rva, (int)File.OptionalHeader.Magic == 267); } public void MarkAsFatal() { Parameters.ErrorListener.MarkAsFatal(); } public void RegisterException(Exception exception) { Parameters.ErrorListener.RegisterException(exception); } } public class PEReaderParameters { public IErrorListener ErrorListener { get; set; } public IMetadataStreamReader MetadataStreamReader { get; set; } public IDebugDataReader DebugDataReader { get; set; } public ICertificateReader CertificateReader { get; set; } public IFileService FileService { get; set; } public IReadyToRunSectionReader ReadyToRunSectionReader { get; set; } public PEReaderParameters() : this((IErrorListener)(object)EmptyErrorListener.Instance) { } public PEReaderParameters(IErrorListener errorListener) { MetadataStreamReader = DefaultMetadataStreamReader.Instance; DebugDataReader = DefaultDebugDataReader.Instance; CertificateReader = DefaultCertificateReader.Instance; FileService = (IFileService)(object)UncachedFileService.Instance; ReadyToRunSectionReader = DefaultReadyToRunSectionReader.Instance; ErrorListener = errorListener ?? throw new ArgumentNullException("errorListener"); } } public class SerializedPEImage : PEImage { private readonly MachineType _originalArchitecture; public override PEFile PEFile { get; } public PEReaderContext ReaderContext { get; } public SerializedPEImage(PEFile peFile, PEReaderParameters readerParameters) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) PEFile = peFile ?? throw new ArgumentNullException("peFile"); ReaderContext = new PEReaderContext(peFile, readerParameters); base.FilePath = peFile.FilePath; base.MachineType = peFile.FileHeader.Machine; base.Characteristics = peFile.FileHeader.Characteristics; base.TimeDateStamp = new DateTime(1970, 1, 1) + TimeSpan.FromSeconds(peFile.FileHeader.TimeDateStamp); base.PEKind = peFile.OptionalHeader.Magic; base.SubSystem = peFile.OptionalHeader.SubSystem; base.DllCharacteristics = peFile.OptionalHeader.DllCharacteristics; base.ImageBase = peFile.OptionalHeader.ImageBase; _originalArchitecture = base.MachineType; } protected override IList GetImports() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)1); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE) { return new List(); } return (IList)new SerializedImportedModuleList(ReaderContext, in dataDirectory); } protected override ExportDirectory? GetExports() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)0); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedExportDirectory(ReaderContext, ref reader); } protected override ResourceDirectory? GetResources() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); BinaryStreamReader directoryReader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref directoryReader)) { return null; } return new SerializedResourceDirectory(ReaderContext, null, ref directoryReader); } protected override IExceptionDirectory? GetExceptions() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)3); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } if ((int)_originalArchitecture == 34404) { return new X64ExceptionDirectory(ReaderContext, in reader); } return ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)ReaderContext); } protected override IList GetRelocations() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) DataDirectory relocDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)5); if (!((DataDirectory)(ref relocDirectory)).IsPresentInPE) { return new List(); } return (IList)new SerializedRelocationList(ReaderContext, in relocDirectory); } protected override DotNetDirectory? GetDotNetDirectory() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)14); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedDotNetDirectory(ReaderContext, ref reader); } protected override IList GetDebugData() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)6); List list = new List(); BinaryStreamReader directoryReader = default(BinaryStreamReader); if (((DataDirectory)(ref dataDirectory)).IsPresentInPE && PEFile.TryCreateDataDirectoryReader(dataDirectory, ref directoryReader)) { uint num = ((DataDirectory)(ref dataDirectory)).Size / 28; for (int i = 0; i < num; i++) { list.Add(new SerializedDebugDataEntry(ReaderContext, ref directoryReader)); } } return list; } protected override TlsDirectory? GetTlsDirectory() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)9); BinaryStreamReader reader = default(BinaryStreamReader); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE || !PEFile.TryCreateDataDirectoryReader(dataDirectory, ref reader)) { return null; } return new SerializedTlsDirectory(ReaderContext, ref reader); } protected override CertificateCollection GetCertificates() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) CertificateCollection certificateCollection = new CertificateCollection(); DataDirectory dataDirectory = PEFile.OptionalHeader.GetDataDirectory((DataDirectoryIndex)4); if (!((DataDirectory)(ref dataDirectory)).IsPresentInPE) { return certificateCollection; } BinaryStreamReader val = default(BinaryStreamReader); if (!PEFile.TryCreateReaderAtFileOffset(((DataDirectory)(ref dataDirectory)).VirtualAddress, ((DataDirectory)(ref dataDirectory)).Size, ref val)) { return certificateCollection; } RelocationParameters parameters = new RelocationParameters((ulong)((DataDirectory)(ref dataDirectory)).VirtualAddress, ((DataDirectory)(ref dataDirectory)).VirtualAddress); certificateCollection.UpdateOffsets(in parameters); ICertificateReader certificateReader = ReaderContext.Parameters.CertificateReader; while (((BinaryStreamReader)(ref val)).CanRead(8u)) { uint num = ((BinaryStreamReader)(ref val)).ReadUInt32(); CertificateRevision revision = (CertificateRevision)((BinaryStreamReader)(ref val)).ReadUInt16(); CertificateType type = (CertificateType)((BinaryStreamReader)(ref val)).ReadUInt16(); BinaryStreamReader reader = ((BinaryStreamReader)(ref val)).ForkRelative(8u, num - 8); certificateCollection.Add(certificateReader.ReadCertificate(ReaderContext, revision, type, reader)); ((BinaryStreamReader)(ref val)).RelativeOffset = ((BinaryStreamReader)(ref val)).RelativeOffset + (num - 8); ((BinaryStreamReader)(ref val)).Align(8u); } return certificateCollection; } } } namespace AsmResolver.PE.Win32Resources { public interface IResourceEntry : IOwnedCollectionElement { ResourceDirectory? ParentDirectory { get; } string? Name { get; set; } uint Id { get; set; } bool IsDirectory { get; } bool IsData { get; } } public class ResourceData : IResourceEntry, IOwnedCollectionElement { private readonly LazyVariable _contents; public ResourceDirectory? ParentDirectory { get; private set; } ResourceDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } public string? Name { get; set; } public uint Id { get; set; } bool IResourceEntry.IsDirectory => false; bool IResourceEntry.IsData => true; public ISegment? Contents { get { return _contents.GetValue(this); } set { _contents.SetValue(value); } } public uint CodePage { get; set; } [MemberNotNullWhen(true, "Contents")] public bool CanRead { [MemberNotNullWhen(true, "Contents")] get { return Contents is IReadableSegment; } } protected ResourceData() { _contents = new LazyVariable((Func)((ResourceData x) => x.GetContents())); } public ResourceData(string name, ISegment contents) : this() { Name = name ?? throw new ArgumentNullException("name"); Contents = contents ?? throw new ArgumentNullException("contents"); } public ResourceData(uint id, ISegment contents) : this() { Id = id; Contents = contents ?? throw new ArgumentNullException("contents"); } public BinaryStreamReader CreateReader() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) ISegment? contents = Contents; IReadableSegment val = (IReadableSegment)(object)((contents is IReadableSegment) ? contents : null); if (val == null) { throw new InvalidOperationException("Resource file is not readable."); } return Extensions.CreateReader(val); } protected virtual ISegment? GetContents() { return null; } public override string ToString() { return "Data (" + (Name ?? Id.ToString()) + ")"; } } public class ResourceDirectory : IResourceEntry, IOwnedCollectionElement { private IList? _entries; public ResourceDirectory? ParentDirectory { get; private set; } ResourceDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } public string? Name { get; set; } public uint Id { get; set; } bool IResourceEntry.IsDirectory => true; bool IResourceEntry.IsData => false; public ResourceType Type { get { return (ResourceType)Id; } set { Id = (uint)value; } } public uint Characteristics { get; set; } public uint TimeDateStamp { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public IList Entries { get { if (_entries == null) { Interlocked.CompareExchange(ref _entries, GetEntries(), null); } return _entries; } } protected ResourceDirectory() { } public ResourceDirectory(string name) { Name = name ?? throw new ArgumentNullException("name"); } public ResourceDirectory(uint id) { Id = id; } public ResourceDirectory(ResourceType type) { Type = type; } private bool TryGetEntryIndex(uint id, out int index) { for (int i = 0; i < Entries.Count; i++) { IResourceEntry resourceEntry = Entries[i]; if (resourceEntry.Id == id) { index = i; return true; } if (resourceEntry.Id > id) { index = i; return false; } } index = Entries.Count; return false; } public IResourceEntry GetEntry(uint id) { if (!TryGetEntry(id, out IResourceEntry entry)) { throw new KeyNotFoundException($"Directory does not contain an entry with id {id}."); } return entry; } public ResourceDirectory GetDirectory(uint id) { if (!TryGetDirectory(id, out ResourceDirectory directory)) { throw new KeyNotFoundException($"Directory does not contain a directory with id {id}."); } return directory; } public ResourceDirectory GetDirectory(ResourceType type) { if (!TryGetDirectory(type, out ResourceDirectory directory)) { throw new KeyNotFoundException($"Directory does not contain a directory of type {type}."); } return directory; } public ResourceData GetData(uint id) { if (!TryGetData(id, out ResourceData data)) { throw new KeyNotFoundException($"Directory does not contain a data entry with id {id}."); } return data; } public bool TryGetEntry(uint id, [NotNullWhen(true)] out IResourceEntry? entry) { if (!TryGetEntryIndex(id, out var index)) { entry = null; return false; } entry = Entries[index]; return true; } public bool TryGetDirectory(uint id, [NotNullWhen(true)] out ResourceDirectory? directory) { if (TryGetEntry(id, out IResourceEntry entry) && entry.IsDirectory) { directory = (ResourceDirectory)entry; return true; } directory = null; return false; } public bool TryGetDirectory(ResourceType type, [NotNullWhen(true)] out ResourceDirectory? directory) { return TryGetDirectory((uint)type, out directory); } public bool TryGetData(uint id, [NotNullWhen(true)] out ResourceData? data) { if (TryGetEntry(id, out IResourceEntry entry) && entry.IsData) { data = (ResourceData)entry; return true; } data = null; return false; } public void InsertOrReplaceEntry(IResourceEntry entry) { if (TryGetEntryIndex(entry.Id, out var index)) { Entries[index] = entry; } else { Entries.Insert(index, entry); } } public bool RemoveEntry(uint id) { if (!TryGetEntryIndex(id, out var index)) { return false; } Entries.RemoveAt(index); return true; } public bool RemoveEntry(ResourceType type) { return RemoveEntry((uint)type); } protected virtual IList GetEntries() { return (IList)new OwnedCollection(this); } public override string ToString() { return "Directory (" + (Name ?? Id.ToString()) + ")"; } } public readonly struct ResourceDirectoryEntry { public const int EntrySize = 8; private readonly uint _idOrNameOffset; private readonly uint _dataOrSubDirOffset; public string? Name { get; } public uint IdOrNameOffset => _idOrNameOffset & 0x7FFFFFFFu; public bool IsByName => (_idOrNameOffset & 0x80000000u) != 0; public uint DataOrSubDirOffset => _dataOrSubDirOffset & 0x7FFFFFFFu; public bool IsData => (_dataOrSubDirOffset & 0x80000000u) == 0; public bool IsSubDirectory => (_dataOrSubDirOffset & 0x80000000u) != 0; public ResourceDirectoryEntry(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _idOrNameOffset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _dataOrSubDirOffset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); Name = null; if (IsByName) { DataDirectory dataDirectory = context.File.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); uint virtualAddress = ((DataDirectory)(ref dataDirectory)).VirtualAddress; BinaryStreamReader val = default(BinaryStreamReader); if (!context.File.TryCreateReaderAtRva(virtualAddress + IdOrNameOffset, ref val)) { ErrorListenerExtensions.BadImage(context.Parameters.ErrorListener, "Resource directory entry contains an invalid name RVA."); return; } int num = ((BinaryStreamReader)(ref val)).ReadUInt16() * 2; byte[] array = new byte[num]; num = ((BinaryStreamReader)(ref val)).ReadBytes(array, 0, num); Name = Encoding.Unicode.GetString(array, 0, num); } } public override string ToString() { return $"Entry: {(IsByName ? Name : IdOrNameOffset.ToString())}, Offset: {DataOrSubDirOffset:X8}"; } } public enum ResourceType { Cursor = 1, Bitmap = 2, Icon = 3, Menu = 4, Dialog = 5, String = 6, FontDirectory = 7, Font = 8, Accelerator = 9, RcData = 10, MessageTable = 11, GroupCursor = 12, GroupIcon = 14, Version = 16, DialogInclude = 17, PlugPlay = 18, Vxd = 20, AniCursor = 21, AniIcon = 22, Html = 23, Manifest = 24 } public class SerializedResourceData : ResourceData { public const uint ResourceDataEntrySize = 16u; private readonly PEReaderContext _context; private readonly uint _contentsRva; private readonly uint _contentsSize; public SerializedResourceData(PEReaderContext context, ResourceDirectoryEntry entry, ref BinaryStreamReader entryReader) { _context = context ?? throw new ArgumentNullException("context"); if (entry.IsByName) { base.Name = entry.Name; } else { base.Id = entry.IdOrNameOffset; } _contentsRva = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); _contentsSize = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); base.CodePage = ((BinaryStreamReader)(ref entryReader)).ReadUInt32(); } protected override ISegment? GetContents() { BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_contentsRva, _contentsSize, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource data entry contains an invalid RVA and/or size."); return null; } return (ISegment?)(object)DataSegment.FromReader(ref val); } } public class SerializedResourceDirectory : ResourceDirectory { public const uint ResourceDirectorySize = 16u; public const int MaxDepth = 10; private readonly PEReaderContext _context; private readonly ushort _namedEntries; private readonly ushort _idEntries; private readonly uint _entriesRva; private readonly int _depth; public SerializedResourceDirectory(PEReaderContext context, ResourceDirectoryEntry? entry, ref BinaryStreamReader directoryReader, int depth = 0) { _context = context ?? throw new ArgumentNullException("context"); _depth = depth; if (entry.HasValue) { ResourceDirectoryEntry value = entry.Value; if (value.IsByName) { base.Name = value.Name; } else { base.Id = value.IdOrNameOffset; } } if (((BinaryStreamReader)(ref directoryReader)).IsValid) { base.Characteristics = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _namedEntries = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _idEntries = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _entriesRva = ((BinaryStreamReader)(ref directoryReader)).Rva; ((BinaryStreamReader)(ref directoryReader)).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset + (ulong)((_namedEntries + _idEntries) * 8); } } protected override IList GetEntries() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) OwnedCollection val = new OwnedCollection((ResourceDirectory)this); if (_namedEntries + _idEntries == 0 || _depth >= 10) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Reached maximum recursion depth of {_depth} sub resource directories."); return (IList)val; } DataDirectory dataDirectory = _context.File.OptionalHeader.GetDataDirectory((DataDirectoryIndex)2); uint virtualAddress = ((DataDirectory)(ref dataDirectory)).VirtualAddress; uint num = (uint)((_namedEntries + _idEntries) * 8); BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_entriesRva, num, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource directory contains an invalid entry table RVA and/or entry count."); return (IList)val; } BinaryStreamReader entryReader = default(BinaryStreamReader); for (int i = 0; i < _namedEntries + _idEntries; i++) { ResourceDirectoryEntry resourceDirectoryEntry = new ResourceDirectoryEntry(_context, ref reader); if (!_context.File.TryCreateReaderAtRva(virtualAddress + resourceDirectoryEntry.DataOrSubDirOffset, ref entryReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Resource directory entry " + i + " has an invalid data offset."); } IResourceEntry resourceEntry2; if (!resourceDirectoryEntry.IsSubDirectory) { IResourceEntry resourceEntry = new SerializedResourceData(_context, resourceDirectoryEntry, ref entryReader); resourceEntry2 = resourceEntry; } else { IResourceEntry resourceEntry = new SerializedResourceDirectory(_context, resourceDirectoryEntry, ref entryReader, _depth + 1); resourceEntry2 = resourceEntry; } ((LazyList)(object)val).Add(resourceEntry2); } return (IList)val; } } } namespace AsmResolver.PE.Win32Resources.Builder { public class ResourceDataTableBuffer : ResourceTableBuffer { public ResourceDataTableBuffer(ISegment parentBuffer) : base(parentBuffer) { } public override uint GetEntrySize(ResourceData entry) { return 16u; } public override void Write(BinaryStreamWriter writer) { for (int i = 0; i < base.Entries.Count; i++) { WriteDataEntry(writer, base.Entries[i]); } } private static void WriteDataEntry(BinaryStreamWriter writer, ResourceData entry) { if (entry.Contents == null) { writer.WriteUInt64(0uL); } else { writer.WriteUInt32(((IOffsetProvider)entry.Contents).Rva); writer.WriteUInt32(((IWritable)entry.Contents).GetPhysicalSize()); } writer.WriteUInt32(entry.CodePage); writer.WriteUInt32(0u); } } public class ResourceDirectoryBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _segments; public ulong Offset => _segments.Offset; public uint Rva => _segments.Rva; public bool CanUpdateOffsets => true; public ResourceTableBuffer DirectoryTable { get; } public ResourceTableBuffer DataEntryTable { get; } public ResourceTableBuffer NameTable { get; } public SegmentBuilder DataTable { get; } public bool IsEmpty => DirectoryTable.IsEmpty; public ResourceDirectoryBuffer() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown NameTable = new ResourceNameTableBuffer((ISegment)(object)this); DataEntryTable = new ResourceDataTableBuffer((ISegment)(object)this); DirectoryTable = new ResourceDirectoryTableBuffer((ISegment)(object)this, NameTable, DataEntryTable); DataTable = new SegmentBuilder(); SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(object)DirectoryTable); val.Add((ISegment)(object)NameTable); val.Add((ISegment)(object)DataEntryTable); val.Add((ISegment)(object)DataTable); _segments = val; } public void AddDirectory(ResourceDirectory directory) { DirectoryTable.AddEntry(directory); if (directory.Name != null) { NameTable.AddEntry(directory.Name); } foreach (IResourceEntry entry in directory.Entries) { AddEntry(entry); } } private void AddEntry(IResourceEntry entry) { if (entry.IsDirectory) { AddDirectory((ResourceDirectory)entry); return; } if (entry.IsData) { AddDataEntry(entry); return; } throw new NotSupportedException(); } private void AddDataEntry(IResourceEntry entry) { ResourceData resourceData = (ResourceData)entry; DataEntryTable.AddEntry(resourceData); if (resourceData.Contents != null) { DataTable.Add(resourceData.Contents, 4u); } } public void UpdateOffsets(in RelocationParameters parameters) { _segments.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _segments.GetPhysicalSize(); } public uint GetVirtualSize() { return _segments.GetVirtualSize(); } public void Write(BinaryStreamWriter writer) { _segments.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class ResourceDirectoryTableBuffer : ResourceTableBuffer { private readonly ResourceTableBuffer _nameTable; private readonly ResourceTableBuffer _dataEntryTable; public ResourceDirectoryTableBuffer(ISegment parentBuffer, ResourceTableBuffer nameTable, ResourceTableBuffer dataEntryTable) : base(parentBuffer) { _nameTable = nameTable ?? throw new ArgumentNullException("nameTable"); _dataEntryTable = dataEntryTable ?? throw new ArgumentNullException("dataEntryTable"); } public override uint GetEntrySize(ResourceDirectory entry) { return (uint)(16 + entry.Entries.Count * 8); } public override void Write(BinaryStreamWriter writer) { foreach (ResourceDirectory entry in base.Entries) { WriteDirectory(writer, entry); } } private void WriteDirectory(BinaryStreamWriter writer, ResourceDirectory directory) { ushort num = (ushort)directory.Entries.Count((IResourceEntry e) => e.Name != null); ushort num2 = (ushort)(directory.Entries.Count - num); writer.WriteUInt32(directory.Characteristics); writer.WriteUInt32(directory.TimeDateStamp); writer.WriteUInt16(directory.MajorVersion); writer.WriteUInt16(directory.MinorVersion); writer.WriteUInt16(num); writer.WriteUInt16(num2); foreach (IResourceEntry entry in directory.Entries) { WriteEntry(writer, entry); } } private void WriteEntry(BinaryStreamWriter writer, IResourceEntry entry) { writer.WriteUInt32((entry.Name != null) ? (_nameTable.GetEntryOffset(entry.Name) | 0x80000000u) : entry.Id); writer.WriteUInt32(entry.IsDirectory ? (GetEntryOffset((ResourceDirectory)entry) | 0x80000000u) : _dataEntryTable.GetEntryOffset((ResourceData)entry)); } } public class ResourceNameTableBuffer : ResourceTableBuffer { public ResourceNameTableBuffer(ISegment parentBuffer) : base(parentBuffer) { } public override uint GetEntrySize(string entry) { return (uint)(2 + Encoding.Unicode.GetByteCount(entry)); } public override void Write(BinaryStreamWriter writer) { foreach (string entry in base.Entries) { writer.WriteUInt16((ushort)entry.Length); byte[] bytes = Encoding.Unicode.GetBytes(entry); writer.WriteBytes(bytes, 0, bytes.Length); } } } public abstract class ResourceTableBuffer : SegmentBase where TEntry : notnull { private readonly Dictionary _entryOffsets = new Dictionary(); private readonly ISegment _parentBuffer; private uint _length; public uint RelativeOffset => ((SegmentBase)this).Rva - ((IOffsetProvider)_parentBuffer).Rva; protected IList Entries { get; } = new List(); public bool IsEmpty => Entries.Count == 0; protected ResourceTableBuffer(ISegment parentBuffer) { _parentBuffer = parentBuffer ?? throw new ArgumentNullException("parentBuffer"); } public void AddEntry(TEntry entry) { if (!_entryOffsets.ContainsKey(entry)) { Entries.Add(entry); _entryOffsets[entry] = _length; _length += GetEntrySize(entry); } } public abstract uint GetEntrySize(TEntry entry); public uint GetEntryOffset(TEntry entry) { return RelativeOffset + _entryOffsets[entry]; } public override uint GetPhysicalSize() { return _length; } } } namespace AsmResolver.PE.Tls { public class SerializedTlsDirectory : TlsDirectory { private readonly PEReaderContext _context; private readonly ulong _templateStart; private readonly ulong _templateEnd; private readonly ulong _addressOfCallbacks; public SerializedTlsDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) _context = context; RelocationParameters relocation = context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); _templateStart = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); _templateEnd = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); base.Index = context.File.GetReferenceToRva((uint)(((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit) - ((RelocationParameters)(ref relocation)).ImageBase)); _addressOfCallbacks = ((BinaryStreamReader)(ref reader)).ReadNativeInt(((RelocationParameters)(ref relocation)).Is32Bit); base.SizeOfZeroFill = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.Characteristics = (TlsCharacteristics)((BinaryStreamReader)(ref reader)).ReadUInt32(); ((SegmentBase)this).UpdateOffsets(ref relocation); } protected override IReadableSegment? GetTemplateData() { if (_templateEnd < _templateStart) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, "End address of TLS template data is smaller than the start address."); } ulong imageBase = _context.File.OptionalHeader.ImageBase; BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva((uint)(_templateStart - imageBase), ref val)) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, $"TLS template data start address 0x{_templateStart:X8} is invalid."); } uint num = (uint)(_templateEnd - _templateStart); if (!((BinaryStreamReader)(ref val)).CanRead(num)) { return ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)_context, $"TLS template data end address 0x{_templateEnd:X8} is invalid."); } return ((BinaryStreamReader)(ref val)).ReadSegment(num); } protected override ReferenceTable GetCallbackFunctions() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 ReferenceTable callbackFunctions = base.GetCallbackFunctions(); PEFile file = _context.File; OptionalHeader optionalHeader = file.OptionalHeader; ulong imageBase = optionalHeader.ImageBase; bool flag = (int)optionalHeader.Magic == 267; BinaryStreamReader val = default(BinaryStreamReader); if (!file.TryCreateReaderAtRva((uint)(_addressOfCallbacks - imageBase), ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"TLS callback function table start address 0x{_addressOfCallbacks:X8} is invalid."); return callbackFunctions; } while (true) { if (!((BinaryStreamReader)(ref val)).CanRead(flag ? 4u : 8u)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "TLS callback function table does not end with a zero entry."); break; } ulong num = ((BinaryStreamReader)(ref val)).ReadNativeInt(flag); if (num == 0L) { break; } ((Collection)(object)callbackFunctions).Add(file.GetReferenceToRva((uint)(num - imageBase))); } return callbackFunctions; } } public enum TlsCharacteristics { Align1Bytes = 1048576, Align2Bytes = 2097152, Align4Bytes = 3145728, Align8Bytes = 4194304, Align16Bytes = 5242880, Align32Bytes = 6291456, Align64Bytes = 7340032, Align128Bytes = 8388608, Align256Bytes = 9437184, Align512Bytes = 10485760, Align1024Bytes = 11534336, Align2048Bytes = 12582912, Align4096Bytes = 13631488, Align8192Bytes = 14680064 } public class TlsDirectory : SegmentBase { private readonly LazyVariable _templateData; private ReferenceTable? _callbackFunctions; private ulong _imageBase = 4194304uL; private bool _is32Bit = true; public IReadableSegment? TemplateData { get { return _templateData.GetValue(this); } set { _templateData.SetValue(value); } } public ISegmentReference Index { get; set; } public ReferenceTable CallbackFunctions { get { if (_callbackFunctions == null) { Interlocked.CompareExchange(ref _callbackFunctions, GetCallbackFunctions(), null); } return _callbackFunctions; } } public uint SizeOfZeroFill { get; set; } public TlsCharacteristics Characteristics { get; set; } public TlsDirectory() { _templateData = new LazyVariable((Func)((TlsDirectory x) => x.GetTemplateData())); Index = SegmentReference.Null; } public override void UpdateOffsets(in RelocationParameters parameters) { _imageBase = ((RelocationParameters)(ref parameters)).ImageBase; _is32Bit = ((RelocationParameters)(ref parameters)).Is32Bit; ((SegmentBase)this).UpdateOffsets(ref parameters); } protected virtual IReadableSegment? GetTemplateData() { return null; } protected virtual ReferenceTable GetCallbackFunctions() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown return new ReferenceTable((ReferenceTableAttributes)18); } public IEnumerable GetRequiredBaseRelocations() { int num = (_is32Bit ? 4 : 8); RelocationType type = (_is32Bit ? RelocationType.HighLow : RelocationType.Dir64); List list = new List(4 + ((Collection)(object)CallbackFunctions).Count); if (TemplateData != null) { list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)this, 0))); list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)this, num))); } list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)this, 2 * num))); list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)this, 3 * num))); for (int i = 0; i < ((Collection)(object)CallbackFunctions).Count; i++) { list.Add(new BaseRelocation(type, Extensions.ToReference((ISegment)(object)CallbackFunctions, i * num))); } return list; } public override uint GetPhysicalSize() { return (uint)((_is32Bit ? 4 : 8) * 4 + 8); } public override void Write(BinaryStreamWriter writer) { ulong imageBase = _imageBase; bool is32Bit = _is32Bit; IReadableSegment templateData = TemplateData; if (templateData != null) { writer.WriteNativeInt(imageBase + ((IOffsetProvider)templateData).Rva, is32Bit); writer.WriteNativeInt(imageBase + ((IOffsetProvider)templateData).Rva + ((IWritable)templateData).GetPhysicalSize(), is32Bit); } else { writer.WriteNativeInt(0uL, is32Bit); writer.WriteNativeInt(0uL, is32Bit); } writer.WriteNativeInt(imageBase + ((IOffsetProvider)Index).Rva, is32Bit); writer.WriteNativeInt(imageBase + CallbackFunctions.Rva, is32Bit); writer.WriteUInt32(SizeOfZeroFill); writer.WriteUInt32((uint)Characteristics); } } } namespace AsmResolver.PE.Relocations { public readonly struct BaseRelocation { public RelocationType Type { get; } public ISegmentReference Location { get; } public BaseRelocation(RelocationType type, ISegmentReference location) { Type = type; Location = location ?? throw new ArgumentNullException("location"); } public override string ToString() { return $"{((IOffsetProvider)Location).Rva:X8} ({Type})"; } public bool Equals(BaseRelocation other) { if (Type == other.Type) { return ((IOffsetProvider)Location).Rva == ((IOffsetProvider)other.Location).Rva; } return false; } public override bool Equals(object? obj) { if (obj is BaseRelocation other) { return Equals(other); } return false; } public override int GetHashCode() { return ((int)Type * 397) ^ (int)((IOffsetProvider)Location).Rva; } } public readonly struct RelocatableSegment { public ISegment Segment { get; } public IList Relocations { get; } public RelocatableSegment(ISegment segment, IList relocations) { Segment = segment; Relocations = relocations; } } public class RelocatableSegmentBuilder : ISegment, IOffsetProvider, IWritable, IEnumerable, IEnumerable { private readonly SegmentBuilder _contents = new SegmentBuilder(); private readonly List _relocations = new List(); public ulong Offset => _contents.Offset; public uint Rva => _contents.Rva; public bool CanUpdateOffsets => _contents.CanUpdateOffsets; public int Count => _contents.Count; public void Add(ISegment segment) { Add(segment, 1u); } public void Add(ISegment segment, uint alignment) { _contents.Add(segment, alignment); } public void Add(RelocatableSegment segment) { Add(segment, 1u); } public void Add(RelocatableSegment segment, uint alignment) { _relocations.AddRange(segment.Relocations); _contents.Add(segment.Segment, alignment); } public IEnumerable GetRequiredBaseRelocations() { return _relocations; } public uint GetPhysicalSize() { return _contents.GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { _contents.Write(writer); } public uint GetVirtualSize() { return _contents.GetVirtualSize(); } public void UpdateOffsets(in RelocationParameters parameters) { _contents.UpdateOffsets(ref parameters); } public IEnumerator GetEnumerator() { return _contents.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_contents).GetEnumerator(); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public enum RelocationType { Absolute = 0, High = 1, Low = 2, HighLow = 3, HighAdj = 4, MipsJmpAddr = 5, ArmMov32 = 5, RiscVHigh20 = 5, ThumbMov32 = 7, RiscVLow12I = 7, RiscVLow12S = 8, MipsJmpAddr16 = 9, Dir64 = 10 } [DebuggerDisplay("Count = {Count}")] public class SerializedRelocationList : LazyList { private readonly PEReaderContext _context; private readonly DataDirectory _relocDirectory; public SerializedRelocationList(PEReaderContext context, in DataDirectory relocDirectory) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _relocDirectory = relocDirectory; } protected override void Initialize() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_relocDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid base relocation data directory RVA and/or size."); return; } while (((BinaryStreamReader)(ref reader)).Offset < ((BinaryStreamReader)(ref reader)).StartOffset + ((BinaryStreamReader)(ref reader)).Length) { ReadBlock(ref reader); } } private void ReadBlock(ref BinaryStreamReader reader) { uint pageRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); int num = (int)((((BinaryStreamReader)(ref reader)).ReadUInt32() - 8) / 2); for (int i = 0; i < num; i++) { ReadRelocationEntry(ref reader, pageRva); } } private void ReadRelocationEntry(ref BinaryStreamReader reader, uint pageRva) { ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); RelocationType type = (RelocationType)(num >> 12); int num2 = num & 0xFFF; base.Items.Add(new BaseRelocation(type, _context.File.GetReferenceToRva((uint)(pageRva + num2)))); } } } namespace AsmResolver.PE.Relocations.Builder { public sealed class RelocationBlock : SegmentBase { public uint PageRva { get; } public IList Entries { get; } public RelocationBlock(uint pageRva) { PageRva = pageRva; Entries = new List(); } public override uint GetPhysicalSize() { return (uint)((Entries.Count + 1) * 2 + 8); } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32(PageRva); writer.WriteUInt32(((SegmentBase)this).GetPhysicalSize()); for (int i = 0; i < Entries.Count; i++) { Entries[i].Write(writer); } default(RelocationEntry).Write(writer); } } public readonly struct RelocationEntry : IWritable { private readonly ushort _value; public RelocationType RelocationType => (RelocationType)(_value >> 12); public int Offset => _value & 0xFFF; public RelocationEntry(ushort value) { _value = value; } public RelocationEntry(RelocationType type, int offset) { if (offset >= 0) { if (offset > 4095) { throw new ArgumentOutOfRangeException("offset", "Offset cannot be larger than 0xFFF."); } ushort value = (ushort)((uint)((byte)type << 12) | ((uint)offset & 0xFFFu)); _value = value; return; } throw new ArgumentOutOfRangeException("offset", "Offset cannot be negative."); } public uint GetPhysicalSize() { return 2u; } public void Write(BinaryStreamWriter writer) { writer.WriteUInt16(_value); } } public class RelocationsDirectoryBuffer : SegmentBase { private readonly List _relocations = new List(); private List? _blocks = new List(); public bool IsEmpty => _relocations.Count == 0; public void Add(BaseRelocation relocation) { _relocations.Add(relocation); _blocks = null; } private void EnsureBlocksCreated() { if (_blocks == null) { _blocks = CreateBlocks(); } } private List CreateBlocks() { Dictionary dictionary = new Dictionary(); for (int i = 0; i < _relocations.Count; i++) { BaseRelocation relocation = _relocations[i]; uint pageRva = GetPageRva(relocation); GetOrCreateBlock(dictionary, pageRva).Entries.Add(CreateEntry(relocation)); } return (from x in dictionary orderby x.Key select x.Value).ToList(); } private static uint GetPageRva(BaseRelocation relocation) { return (uint)(((IOffsetProvider)relocation.Location).Rva & -4096); } private static RelocationEntry CreateEntry(BaseRelocation relocation) { return new RelocationEntry(relocation.Type, (int)(((IOffsetProvider)relocation.Location).Rva & 0xFFF)); } private static RelocationBlock GetOrCreateBlock(IDictionary blocks, uint pageRva) { if (!blocks.TryGetValue(pageRva, out RelocationBlock value)) { value = new RelocationBlock(pageRva); blocks.Add(pageRva, value); } return value; } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); _blocks = null; } public override uint GetPhysicalSize() { EnsureBlocksCreated(); return (uint)_blocks.Sum((RelocationBlock b) => ((SegmentBase)b).GetPhysicalSize()); } public override void Write(BinaryStreamWriter writer) { EnsureBlocksCreated(); for (int i = 0; i < _blocks.Count; i++) { ((SegmentBase)_blocks[i]).Write(writer); } } } } namespace AsmResolver.PE.Platforms { public abstract class AddressTableInitializerStub : ISegment, IOffsetProvider, IWritable { private readonly RelocatableSegment _slotInitializer; private readonly SegmentBuilder _contents; public ulong Offset => _contents.Offset; public uint Rva => _contents.Rva; public bool CanUpdateOffsets => _contents.CanUpdateOffsets; public ISymbol EntryPoint { get; } protected ISymbol SlotInitializer { get; } protected RelocatableSegmentBuilder Body { get; } protected AddressTableInitializerStub(ISegment prologue, ISegment epilogue, RelocatableSegment slotInitializer) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown _slotInitializer = slotInitializer; Body = new RelocatableSegmentBuilder(); EntryPoint = (ISymbol)new Symbol(Extensions.ToReference(prologue)); SlotInitializer = (ISymbol)new Symbol(Extensions.ToReference(slotInitializer.Segment)); SegmentBuilder val = new SegmentBuilder(); val.Add(slotInitializer.Segment); val.Add(prologue); val.Add((ISegment)(object)Body); val.Add(epilogue); _contents = val; } public abstract void AddInitializer(ISymbol originalSlot, ISymbol newSlot); public IEnumerable GetRequiredBaseRelocations() { return _slotInitializer.Relocations.Concat(Body.GetRequiredBaseRelocations()); } public void UpdateOffsets(in RelocationParameters parameters) { _contents.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _contents.GetPhysicalSize(); } public uint GetVirtualSize() { return _contents.GetVirtualSize(); } public void Write(BinaryStreamWriter writer) { _contents.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class Amd64Platform : Platform { private sealed class Amd64AddressTableInitializerStub : AddressTableInitializerStub { private static readonly byte[] PrologueStub = new byte[7] { 72, 131, 250, 1, 116, 1, 195 }; private static readonly byte[] EpilogueStub = new byte[1] { 195 }; private static readonly byte[] SlotInitializerCode = new byte[91] { 85, 72, 137, 229, 72, 131, 236, 64, 72, 137, 85, 240, 72, 137, 77, 248, 76, 141, 77, 232, 65, 184, 4, 0, 0, 0, 186, 8, 0, 0, 0, 72, 139, 77, 248, 72, 184, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 72, 139, 69, 248, 72, 139, 77, 240, 72, 137, 8, 76, 141, 77, 232, 69, 139, 1, 186, 8, 0, 0, 0, 72, 139, 77, 248, 72, 184, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 72, 137, 236, 93, 195 }; public Amd64AddressTableInitializerStub(ISymbol virtualProtect) : base((ISegment)new DataSegment(PrologueStub), (ISegment)new DataSegment(EpilogueStub), CreateSlotInitializer(virtualProtect)) { }//IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0020: Expected O, but got Unknown private static RelocatableSegment CreateSlotInitializer(ISymbol virtualProtect) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(SlotInitializerCode)).Patch(37u, AddressFixupType.Absolute64BitAddress, virtualProtect).Patch(76u, AddressFixupType.Absolute64BitAddress, virtualProtect); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[2] { new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 37)), new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 76)) }); } public override void AddInitializer(ISymbol originalSlot, ISymbol newSlot) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[28] { 72, 161, 0, 0, 0, 0, 0, 0, 0, 0, 72, 139, 208, 72, 185, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 0 })).Patch(2u, AddressFixupType.Absolute64BitAddress, newSlot).Patch(15u, AddressFixupType.Absolute64BitAddress, originalSlot) .Patch(24u, AddressFixupType.Relative32BitAddress, base.SlotInitializer); base.Body.Add(new RelocatableSegment((ISegment)(object)val, new BaseRelocation[2] { new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 2)), new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 15)) })); } } public static Amd64Platform Instance { get; } = new Amd64Platform(); public override MachineType TargetMachine => (MachineType)34404; public override bool IsClrBootstrapperRequired => false; public override bool Is32Bit => false; public override RelocatableSegment CreateThunkStub(ISymbol entryPoint) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[12] { 72, 161, 0, 0, 0, 0, 0, 0, 0, 0, 255, 224 })).Patch(2u, AddressFixupType.Absolute64BitAddress, entryPoint); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[1] { new BaseRelocation(RelocationType.Dir64, Extensions.ToReference((ISegment)(object)val, 2)) }); } public override bool TryExtractThunkAddress(PEImage image, BinaryStreamReader reader, out uint rva) { if (((BinaryStreamReader)(ref reader)).ReadUInt16() != 41288) { rva = 0u; return false; } rva = (uint)(((BinaryStreamReader)(ref reader)).ReadUInt64() - image.ImageBase); return ((BinaryStreamReader)(ref reader)).ReadUInt16() == 57599; } public override AddressTableInitializerStub CreateAddressTableInitializer(ISymbol virtualProtect) { return new Amd64AddressTableInitializerStub(virtualProtect); } } public class I386Platform : Platform { private sealed class I386AddressTableInitializerStub : AddressTableInitializerStub { private static readonly byte[] PrologueStub = new byte[10] { 131, 124, 36, 8, 1, 116, 3, 194, 12, 0 }; private static readonly byte[] EpilogueStub = new byte[3] { 194, 12, 0 }; private static readonly byte[] SlotInitializerCode = new byte[54] { 85, 137, 229, 131, 236, 4, 141, 69, 252, 80, 106, 4, 106, 4, 255, 117, 8, 255, 21, 0, 0, 0, 0, 139, 85, 8, 139, 69, 12, 137, 2, 141, 85, 252, 82, 255, 50, 106, 4, 255, 117, 8, 255, 21, 0, 0, 0, 0, 137, 236, 93, 194, 8, 0 }; public I386AddressTableInitializerStub(ISymbol virtualProtect) : base((ISegment)new DataSegment(PrologueStub), (ISegment)new DataSegment(EpilogueStub), CreateSlotInitializer(virtualProtect)) { }//IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0020: Expected O, but got Unknown private static RelocatableSegment CreateSlotInitializer(ISymbol virtualProtect) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(SlotInitializerCode)).Patch(19u, AddressFixupType.Absolute32BitAddress, virtualProtect).Patch(44u, AddressFixupType.Absolute32BitAddress, virtualProtect); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[2] { new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 19)), new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 44)) }); } public override void AddInitializer(ISymbol originalSlot, ISymbol newSlot) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[16] { 255, 53, 0, 0, 0, 0, 104, 0, 0, 0, 0, 232, 0, 0, 0, 0 })).Patch(2u, AddressFixupType.Absolute32BitAddress, newSlot).Patch(7u, AddressFixupType.Absolute32BitAddress, originalSlot) .Patch(12u, AddressFixupType.Relative32BitAddress, base.SlotInitializer); base.Body.Add(new RelocatableSegment((ISegment)(object)val, new BaseRelocation[2] { new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 2)), new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 7)) })); } } public static I386Platform Instance { get; } = new I386Platform(); public override MachineType TargetMachine => (MachineType)332; public override bool IsClrBootstrapperRequired => true; public override bool Is32Bit => true; public override RelocatableSegment CreateThunkStub(ISymbol entryPoint) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown PatchedSegment val = Extensions.AsPatchedSegment((ISegment)new DataSegment(new byte[6] { 255, 37, 0, 0, 0, 0 })).Patch(2u, AddressFixupType.Absolute32BitAddress, entryPoint); return new RelocatableSegment((ISegment)(object)val, new BaseRelocation[1] { new BaseRelocation(RelocationType.HighLow, Extensions.ToReference((ISegment)(object)val, 2)) }); } public override bool TryExtractThunkAddress(PEImage image, BinaryStreamReader reader, out uint rva) { if (((BinaryStreamReader)(ref reader)).ReadUInt16() != 9727) { rva = 0u; return false; } rva = (uint)(((BinaryStreamReader)(ref reader)).ReadUInt32() - image.ImageBase); return true; } public override AddressTableInitializerStub CreateAddressTableInitializer(ISymbol virtualProtect) { return new I386AddressTableInitializerStub(virtualProtect); } } public abstract class Platform { public abstract MachineType TargetMachine { get; } public abstract bool IsClrBootstrapperRequired { get; } public abstract bool Is32Bit { get; } public bool Is64Bit => !Is32Bit; public int PointerSize { get { if (!Is32Bit) { return 8; } return 4; } } public static Platform Get(MachineType machineType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!TryGet(machineType, out Platform platform)) { throw new NotSupportedException($"Unsupported machine type {machineType}."); } return platform; } public static bool TryGet(MachineType machineType, [NotNullWhen(true)] out Platform? platform) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 if ((int)machineType <= 31285) { if ((int)machineType <= 6367) { if ((int)machineType == 332 || machineType - 6366 <= 1) { goto IL_0074; } } else { if ((int)machineType == 11168) { goto IL_007c; } if ((int)machineType == 18184 || (int)machineType == 31285) { goto IL_0074; } } } else if ((int)machineType <= 40951) { if ((int)machineType == 34404 || machineType - 40950 <= 1) { goto IL_007c; } } else { if ((int)machineType == 44168) { goto IL_0074; } if ((int)machineType == 49184 || (int)machineType == 64797) { goto IL_007c; } } Platform platform2 = null; goto IL_0086; IL_0086: platform = platform2; return platform != null; IL_0074: platform2 = I386Platform.Instance; goto IL_0086; IL_007c: platform2 = Amd64Platform.Instance; goto IL_0086; } public abstract RelocatableSegment CreateThunkStub(ISymbol entryPoint); public abstract bool TryExtractThunkAddress(PEImage image, BinaryStreamReader reader, out uint rva); public abstract AddressTableInitializerStub CreateAddressTableInitializer(ISymbol virtualProtect); } } namespace AsmResolver.PE.Imports { public sealed class DefaultSymbolResolver : ISymbolResolver { private static readonly Dictionary _ws2_32OrdinalMapping = new Dictionary { [1u] = "accept", [2u] = "bind", [3u] = "closesocket", [4u] = "connect", [5u] = "getpeername", [6u] = "getsockname", [7u] = "getsockopt", [8u] = "htonl", [9u] = "htons", [10u] = "ioctlsocket", [11u] = "inet_addr", [12u] = "inet_ntoa", [13u] = "listen", [14u] = "ntohl", [15u] = "ntohs", [16u] = "recv", [17u] = "recvfrom", [18u] = "select", [19u] = "send", [20u] = "sendto", [21u] = "setsockopt", [22u] = "shutdown", [23u] = "socket", [24u] = "WSApSetPostRoutine", [25u] = "FreeAddrInfoEx", [26u] = "FreeAddrInfoExW", [27u] = "FreeAddrInfoW", [28u] = "GetAddrInfoExA", [29u] = "GetAddrInfoExCancel", [30u] = "GetAddrInfoExOverlappedResult", [31u] = "GetAddrInfoExW", [32u] = "GetAddrInfoW", [33u] = "GetHostNameW", [34u] = "GetNameInfoW", [35u] = "InetNtopW", [36u] = "InetPtonW", [37u] = "SetAddrInfoExA", [38u] = "SetAddrInfoExW", [39u] = "WPUCompleteOverlappedRequest", [40u] = "WPUGetProviderPathEx", [41u] = "WSAAccept", [42u] = "WSAAddressToStringA", [43u] = "WSAAddressToStringW", [44u] = "WSAAdvertiseProvider", [45u] = "WSACloseEvent", [46u] = "WSAConnect", [47u] = "WSAConnectByList", [48u] = "WSAConnectByNameA", [49u] = "WSAConnectByNameW", [50u] = "WSACreateEvent", [51u] = "gethostbyaddr", [52u] = "gethostbyname", [53u] = "getprotobyname", [54u] = "getprotobynumber", [55u] = "getservbyname", [56u] = "getservbyport", [57u] = "gethostname", [58u] = "WSADuplicateSocketA", [59u] = "WSADuplicateSocketW", [60u] = "WSAEnumNameSpaceProvidersA", [61u] = "WSAEnumNameSpaceProvidersExA", [62u] = "WSAEnumNameSpaceProvidersExW", [63u] = "WSAEnumNameSpaceProvidersW", [64u] = "WSAEnumNetworkEvents", [65u] = "WSAEnumProtocolsA", [66u] = "WSAEnumProtocolsW", [67u] = "WSAEventSelect", [68u] = "WSAGetOverlappedResult", [69u] = "WSAGetQOSByName", [70u] = "WSAGetServiceClassInfoA", [71u] = "WSAGetServiceClassInfoW", [72u] = "WSAGetServiceClassNameByClassIdA", [73u] = "WSAGetServiceClassNameByClassIdW", [74u] = "WSAHtonl", [75u] = "WSAHtons", [76u] = "WSAInstallServiceClassA", [77u] = "WSAInstallServiceClassW", [78u] = "WSAIoctl", [79u] = "WSAJoinLeaf", [80u] = "WSALookupServiceBeginA", [81u] = "WSALookupServiceBeginW", [82u] = "WSALookupServiceEnd", [83u] = "WSALookupServiceNextA", [84u] = "WSALookupServiceNextW", [85u] = "WSANSPIoctl", [86u] = "WSANtohl", [87u] = "WSANtohs", [88u] = "WSAPoll", [89u] = "WSAProviderCompleteAsyncCall", [90u] = "WSAProviderConfigChange", [91u] = "WSARecv", [92u] = "WSARecvDisconnect", [93u] = "WSARecvFrom", [94u] = "WSARemoveServiceClass", [95u] = "WSAResetEvent", [96u] = "WSASend", [97u] = "WSASendDisconnect", [98u] = "WSASendMsg", [99u] = "WSASendTo", [100u] = "WSASetEvent", [101u] = "WSAAsyncSelect", [102u] = "WSAAsyncGetHostByAddr", [103u] = "WSAAsyncGetHostByName", [104u] = "WSAAsyncGetProtoByNumber", [105u] = "WSAAsyncGetProtoByName", [106u] = "WSAAsyncGetServByPort", [107u] = "WSAAsyncGetServByName", [108u] = "WSACancelAsyncRequest", [109u] = "WSASetBlockingHook", [110u] = "WSAUnhookBlockingHook", [111u] = "WSAGetLastError", [112u] = "WSASetLastError", [113u] = "WSACancelBlockingCall", [114u] = "WSAIsBlocking", [115u] = "WSAStartup", [116u] = "WSACleanup", [117u] = "WSASetServiceA", [118u] = "WSASetServiceW", [119u] = "WSASocketA", [120u] = "WSASocketW", [121u] = "WSAStringToAddressA", [122u] = "WSAStringToAddressW", [123u] = "WSAUnadvertiseProvider", [124u] = "WSAWaitForMultipleEvents", [125u] = "WSCDeinstallProvider", [126u] = "WSCDeinstallProvider32", [127u] = "WSCDeinstallProviderEx", [128u] = "WSCEnableNSProvider", [129u] = "WSCEnableNSProvider32", [130u] = "WSCEnumNameSpaceProviders32", [131u] = "WSCEnumNameSpaceProvidersEx32", [132u] = "WSCEnumProtocols", [133u] = "WSCEnumProtocols32", [134u] = "WSCEnumProtocolsEx", [135u] = "WSCGetApplicationCategory", [136u] = "WSCGetApplicationCategoryEx", [137u] = "WSCGetProviderInfo", [138u] = "WSCGetProviderInfo32", [139u] = "WSCGetProviderPath", [140u] = "WSCGetProviderPath32", [141u] = "WSCInstallNameSpace", [142u] = "WSCInstallNameSpace32", [143u] = "WSCInstallNameSpaceEx", [144u] = "WSCInstallNameSpaceEx2", [145u] = "WSCInstallNameSpaceEx32", [146u] = "WSCInstallProvider", [147u] = "WSCInstallProvider64_32", [148u] = "WSCInstallProviderAndChains64_32", [149u] = "WSCInstallProviderEx", [150u] = "WSCSetApplicationCategory", [151u] = "__WSAFDIsSet", [152u] = "WSCSetApplicationCategoryEx", [153u] = "WSCSetProviderInfo", [154u] = "WSCSetProviderInfo32", [155u] = "WSCUnInstallNameSpace", [156u] = "WSCUnInstallNameSpace32", [157u] = "WSCUnInstallNameSpaceEx2", [158u] = "WSCUpdateProvider", [159u] = "WSCUpdateProvider32", [160u] = "WSCUpdateProviderEx", [161u] = "WSCWriteNameSpaceOrder", [162u] = "WSCWriteNameSpaceOrder32", [163u] = "WSCWriteProviderOrder", [164u] = "WSCWriteProviderOrder32", [165u] = "WSCWriteProviderOrderEx", [166u] = "WahCloseApcHelper", [167u] = "WahCloseHandleHelper", [168u] = "WahCloseNotificationHandleHelper", [169u] = "WahCloseSocketHandle", [170u] = "WahCloseThread", [171u] = "WahCompleteRequest", [172u] = "WahCreateHandleContextTable", [173u] = "WahCreateNotificationHandle", [174u] = "WahCreateSocketHandle", [175u] = "WahDestroyHandleContextTable", [176u] = "WahDisableNonIFSHandleSupport", [177u] = "WahEnableNonIFSHandleSupport", [178u] = "WahEnumerateHandleContexts", [179u] = "WahInsertHandleContext", [180u] = "WahNotifyAllProcesses", [181u] = "WahOpenApcHelper", [182u] = "WahOpenCurrentThread", [183u] = "WahOpenHandleHelper", [184u] = "WahOpenNotificationHandleHelper", [185u] = "WahQueueUserApc", [186u] = "WahReferenceContextByHandle", [187u] = "WahRemoveHandleContext", [188u] = "WahWaitForNotification", [189u] = "WahWriteLSPEvent", [190u] = "freeaddrinfo", [191u] = "getaddrinfo", [192u] = "getnameinfo", [193u] = "inet_ntop", [194u] = "inet_pton", [500u] = "WEP" }; private static readonly Dictionary _oleaut32OrdinalMapping = new Dictionary { [2u] = "SysAllocString", [3u] = "SysReAllocString", [4u] = "SysAllocStringLen", [5u] = "SysReAllocStringLen", [6u] = "SysFreeString", [7u] = "SysStringLen", [8u] = "VariantInit", [9u] = "VariantClear", [10u] = "VariantCopy", [11u] = "VariantCopyInd", [12u] = "VariantChangeType", [13u] = "VariantTimeToDosDateTime", [14u] = "DosDateTimeToVariantTime", [15u] = "SafeArrayCreate", [16u] = "SafeArrayDestroy", [17u] = "SafeArrayGetDim", [18u] = "SafeArrayGetElemsize", [19u] = "SafeArrayGetUBound", [20u] = "SafeArrayGetLBound", [21u] = "SafeArrayLock", [22u] = "SafeArrayUnlock", [23u] = "SafeArrayAccessData", [24u] = "SafeArrayUnaccessData", [25u] = "SafeArrayGetElement", [26u] = "SafeArrayPutElement", [27u] = "SafeArrayCopy", [28u] = "DispGetParam", [29u] = "DispGetIDsOfNames", [30u] = "DispInvoke", [31u] = "CreateDispTypeInfo", [32u] = "CreateStdDispatch", [33u] = "RegisterActiveObject", [34u] = "RevokeActiveObject", [35u] = "GetActiveObject", [36u] = "SafeArrayAllocDescriptor", [37u] = "SafeArrayAllocData", [38u] = "SafeArrayDestroyDescriptor", [39u] = "SafeArrayDestroyData", [40u] = "SafeArrayRedim", [41u] = "SafeArrayAllocDescriptorEx", [42u] = "SafeArrayCreateEx", [43u] = "SafeArrayCreateVectorEx", [44u] = "SafeArraySetRecordInfo", [45u] = "SafeArrayGetRecordInfo", [46u] = "VarParseNumFromStr", [47u] = "VarNumFromParseNum", [48u] = "VarI2FromUI1", [49u] = "VarI2FromI4", [50u] = "VarI2FromR4", [51u] = "VarI2FromR8", [52u] = "VarI2FromCy", [53u] = "VarI2FromDate", [54u] = "VarI2FromStr", [55u] = "VarI2FromDisp", [56u] = "VarI2FromBool", [57u] = "SafeArraySetIID", [58u] = "VarI4FromUI1", [59u] = "VarI4FromI2", [60u] = "VarI4FromR4", [61u] = "VarI4FromR8", [62u] = "VarI4FromCy", [63u] = "VarI4FromDate", [64u] = "VarI4FromStr", [65u] = "VarI4FromDisp", [66u] = "VarI4FromBool", [67u] = "SafeArrayGetIID", [68u] = "VarR4FromUI1", [69u] = "VarR4FromI2", [70u] = "VarR4FromI4", [71u] = "VarR4FromR8", [72u] = "VarR4FromCy", [73u] = "VarR4FromDate", [74u] = "VarR4FromStr", [75u] = "VarR4FromDisp", [76u] = "VarR4FromBool", [77u] = "SafeArrayGetVartype", [78u] = "VarR8FromUI1", [79u] = "VarR8FromI2", [80u] = "VarR8FromI4", [81u] = "VarR8FromR4", [82u] = "VarR8FromCy", [83u] = "VarR8FromDate", [84u] = "VarR8FromStr", [85u] = "VarR8FromDisp", [86u] = "VarR8FromBool", [87u] = "VarFormat", [88u] = "VarDateFromUI1", [89u] = "VarDateFromI2", [90u] = "VarDateFromI4", [91u] = "VarDateFromR4", [92u] = "VarDateFromR8", [93u] = "VarDateFromCy", [94u] = "VarDateFromStr", [95u] = "VarDateFromDisp", [96u] = "VarDateFromBool", [97u] = "VarFormatDateTime", [98u] = "VarCyFromUI1", [99u] = "VarCyFromI2", [100u] = "VarCyFromI4", [101u] = "VarCyFromR4", [102u] = "VarCyFromR8", [103u] = "VarCyFromDate", [104u] = "VarCyFromStr", [105u] = "VarCyFromDisp", [106u] = "VarCyFromBool", [107u] = "VarFormatNumber", [108u] = "VarBstrFromUI1", [109u] = "VarBstrFromI2", [110u] = "VarBstrFromI4", [111u] = "VarBstrFromR4", [112u] = "VarBstrFromR8", [113u] = "VarBstrFromCy", [114u] = "VarBstrFromDate", [115u] = "VarBstrFromDisp", [116u] = "VarBstrFromBool", [117u] = "VarFormatPercent", [118u] = "VarBoolFromUI1", [119u] = "VarBoolFromI2", [120u] = "VarBoolFromI4", [121u] = "VarBoolFromR4", [122u] = "VarBoolFromR8", [123u] = "VarBoolFromDate", [124u] = "VarBoolFromCy", [125u] = "VarBoolFromStr", [126u] = "VarBoolFromDisp", [127u] = "VarFormatCurrency", [128u] = "VarWeekdayName", [129u] = "VarMonthName", [130u] = "VarUI1FromI2", [131u] = "VarUI1FromI4", [132u] = "VarUI1FromR4", [133u] = "VarUI1FromR8", [134u] = "VarUI1FromCy", [135u] = "VarUI1FromDate", [136u] = "VarUI1FromStr", [137u] = "VarUI1FromDisp", [138u] = "VarUI1FromBool", [139u] = "VarFormatFromTokens", [140u] = "VarTokenizeFormatString", [141u] = "VarAdd", [142u] = "VarAnd", [143u] = "VarDiv", [144u] = "BSTR_UserFree64", [145u] = "BSTR_UserMarshal64", [146u] = "DispCallFunc", [147u] = "VariantChangeTypeEx", [148u] = "SafeArrayPtrOfIndex", [149u] = "SysStringByteLen", [150u] = "SysAllocStringByteLen", [151u] = "BSTR_UserSize64", [152u] = "VarEqv", [153u] = "VarIdiv", [154u] = "VarImp", [155u] = "VarMod", [156u] = "VarMul", [157u] = "VarOr", [158u] = "VarPow", [159u] = "VarSub", [160u] = "CreateTypeLib", [161u] = "LoadTypeLib", [162u] = "LoadRegTypeLib", [163u] = "RegisterTypeLib", [164u] = "QueryPathOfRegTypeLib", [165u] = "LHashValOfNameSys", [166u] = "LHashValOfNameSysA", [167u] = "VarXor", [168u] = "VarAbs", [169u] = "VarFix", [170u] = "OaBuildVersion", [171u] = "ClearCustData", [172u] = "VarInt", [173u] = "VarNeg", [174u] = "VarNot", [175u] = "VarRound", [176u] = "VarCmp", [177u] = "VarDecAdd", [178u] = "VarDecDiv", [179u] = "VarDecMul", [180u] = "CreateTypeLib2", [181u] = "VarDecSub", [182u] = "VarDecAbs", [183u] = "LoadTypeLibEx", [184u] = "SystemTimeToVariantTime", [185u] = "VariantTimeToSystemTime", [186u] = "UnRegisterTypeLib", [187u] = "VarDecFix", [188u] = "VarDecInt", [189u] = "VarDecNeg", [190u] = "VarDecFromUI1", [191u] = "VarDecFromI2", [192u] = "VarDecFromI4", [193u] = "VarDecFromR4", [194u] = "VarDecFromR8", [195u] = "VarDecFromDate", [196u] = "VarDecFromCy", [197u] = "VarDecFromStr", [198u] = "VarDecFromDisp", [199u] = "VarDecFromBool", [200u] = "GetErrorInfo", [201u] = "SetErrorInfo", [202u] = "CreateErrorInfo", [203u] = "VarDecRound", [204u] = "VarDecCmp", [205u] = "VarI2FromI1", [206u] = "VarI2FromUI2", [207u] = "VarI2FromUI4", [208u] = "VarI2FromDec", [209u] = "VarI4FromI1", [210u] = "VarI4FromUI2", [211u] = "VarI4FromUI4", [212u] = "VarI4FromDec", [213u] = "VarR4FromI1", [214u] = "VarR4FromUI2", [215u] = "VarR4FromUI4", [216u] = "VarR4FromDec", [217u] = "VarR8FromI1", [218u] = "VarR8FromUI2", [219u] = "VarR8FromUI4", [220u] = "VarR8FromDec", [221u] = "VarDateFromI1", [222u] = "VarDateFromUI2", [223u] = "VarDateFromUI4", [224u] = "VarDateFromDec", [225u] = "VarCyFromI1", [226u] = "VarCyFromUI2", [227u] = "VarCyFromUI4", [228u] = "VarCyFromDec", [229u] = "VarBstrFromI1", [230u] = "VarBstrFromUI2", [231u] = "VarBstrFromUI4", [232u] = "VarBstrFromDec", [233u] = "VarBoolFromI1", [234u] = "VarBoolFromUI2", [235u] = "VarBoolFromUI4", [236u] = "VarBoolFromDec", [237u] = "VarUI1FromI1", [238u] = "VarUI1FromUI2", [239u] = "VarUI1FromUI4", [240u] = "VarUI1FromDec", [241u] = "VarDecFromI1", [242u] = "VarDecFromUI2", [243u] = "VarDecFromUI4", [244u] = "VarI1FromUI1", [245u] = "VarI1FromI2", [246u] = "VarI1FromI4", [247u] = "VarI1FromR4", [248u] = "VarI1FromR8", [249u] = "VarI1FromDate", [250u] = "VarI1FromCy", [251u] = "VarI1FromStr", [252u] = "VarI1FromDisp", [253u] = "VarI1FromBool", [254u] = "VarI1FromUI2", [255u] = "VarI1FromUI4", [256u] = "VarI1FromDec", [257u] = "VarUI2FromUI1", [258u] = "VarUI2FromI2", [259u] = "VarUI2FromI4", [260u] = "VarUI2FromR4", [261u] = "VarUI2FromR8", [262u] = "VarUI2FromDate", [263u] = "VarUI2FromCy", [264u] = "VarUI2FromStr", [265u] = "VarUI2FromDisp", [266u] = "VarUI2FromBool", [267u] = "VarUI2FromI1", [268u] = "VarUI2FromUI4", [269u] = "VarUI2FromDec", [270u] = "VarUI4FromUI1", [271u] = "VarUI4FromI2", [272u] = "VarUI4FromI4", [273u] = "VarUI4FromR4", [274u] = "VarUI4FromR8", [275u] = "VarUI4FromDate", [276u] = "VarUI4FromCy", [277u] = "VarUI4FromStr", [278u] = "VarUI4FromDisp", [279u] = "VarUI4FromBool", [280u] = "VarUI4FromI1", [281u] = "VarUI4FromUI2", [282u] = "VarUI4FromDec", [283u] = "BSTR_UserSize", [284u] = "BSTR_UserMarshal", [285u] = "BSTR_UserUnmarshal", [286u] = "BSTR_UserFree", [287u] = "VARIANT_UserSize", [288u] = "VARIANT_UserMarshal", [289u] = "VARIANT_UserUnmarshal", [290u] = "VARIANT_UserFree", [291u] = "LPSAFEARRAY_UserSize", [292u] = "LPSAFEARRAY_UserMarshal", [293u] = "LPSAFEARRAY_UserUnmarshal", [294u] = "LPSAFEARRAY_UserFree", [295u] = "LPSAFEARRAY_Size", [296u] = "LPSAFEARRAY_Marshal", [297u] = "LPSAFEARRAY_Unmarshal", [298u] = "VarDecCmpR8", [299u] = "VarCyAdd", [300u] = "BSTR_UserUnmarshal64", [301u] = "DllCanUnloadNow", [302u] = "DllGetClassObject", [303u] = "VarCyMul", [304u] = "VarCyMulI4", [305u] = "VarCySub", [306u] = "VarCyAbs", [307u] = "VarCyFix", [308u] = "VarCyInt", [309u] = "VarCyNeg", [310u] = "VarCyRound", [311u] = "VarCyCmp", [312u] = "VarCyCmpR8", [313u] = "VarBstrCat", [314u] = "VarBstrCmp", [315u] = "VarR8Pow", [316u] = "VarR4CmpR8", [317u] = "VarR8Round", [318u] = "VarCat", [319u] = "VarDateFromUdateEx", [320u] = "DllRegisterServer", [321u] = "DllUnregisterServer", [322u] = "GetRecordInfoFromGuids", [323u] = "GetRecordInfoFromTypeInfo", [324u] = "LPSAFEARRAY_UserFree64", [325u] = "SetVarConversionLocaleSetting", [326u] = "GetVarConversionLocaleSetting", [327u] = "SetOaNoCache", [328u] = "LPSAFEARRAY_UserMarshal64", [329u] = "VarCyMulI8", [330u] = "VarDateFromUdate", [331u] = "VarUdateFromDate", [332u] = "GetAltMonthNames", [333u] = "VarI8FromUI1", [334u] = "VarI8FromI2", [335u] = "VarI8FromR4", [336u] = "VarI8FromR8", [337u] = "VarI8FromCy", [338u] = "VarI8FromDate", [339u] = "VarI8FromStr", [340u] = "VarI8FromDisp", [341u] = "VarI8FromBool", [342u] = "VarI8FromI1", [343u] = "VarI8FromUI2", [344u] = "VarI8FromUI4", [345u] = "VarI8FromDec", [346u] = "VarI2FromI8", [347u] = "VarI2FromUI8", [348u] = "VarI4FromI8", [349u] = "VarI4FromUI8", [350u] = "LPSAFEARRAY_UserSize64", [351u] = "LPSAFEARRAY_UserUnmarshal64", [352u] = "OACreateTypeLib2", [353u] = "SafeArrayAddRef", [354u] = "SafeArrayReleaseData", [355u] = "SafeArrayReleaseDescriptor", [356u] = "SysAddRefString", [357u] = "SysReleaseString", [358u] = "VARIANT_UserFree64", [359u] = "VARIANT_UserMarshal64", [360u] = "VarR4FromI8", [361u] = "VarR4FromUI8", [362u] = "VarR8FromI8", [363u] = "VarR8FromUI8", [364u] = "VarDateFromI8", [365u] = "VarDateFromUI8", [366u] = "VarCyFromI8", [367u] = "VarCyFromUI8", [368u] = "VarBstrFromI8", [369u] = "VarBstrFromUI8", [370u] = "VarBoolFromI8", [371u] = "VarBoolFromUI8", [372u] = "VarUI1FromI8", [373u] = "VarUI1FromUI8", [374u] = "VarDecFromI8", [375u] = "VarDecFromUI8", [376u] = "VarI1FromI8", [377u] = "VarI1FromUI8", [378u] = "VarUI2FromI8", [379u] = "VarUI2FromUI8", [380u] = "VARIANT_UserSize64", [381u] = "VARIANT_UserUnmarshal64", [401u] = "OleLoadPictureEx", [402u] = "OleLoadPictureFileEx", [411u] = "SafeArrayCreateVector", [412u] = "SafeArrayCopyData", [413u] = "VectorFromBstr", [414u] = "BstrFromVector", [415u] = "OleIconToCursor", [416u] = "OleCreatePropertyFrameIndirect", [417u] = "OleCreatePropertyFrame", [418u] = "OleLoadPicture", [419u] = "OleCreatePictureIndirect", [420u] = "OleCreateFontIndirect", [421u] = "OleTranslateColor", [422u] = "OleLoadPictureFile", [423u] = "OleSavePictureFile", [424u] = "OleLoadPicturePath", [425u] = "VarUI4FromI8", [426u] = "VarUI4FromUI8", [427u] = "VarI8FromUI8", [428u] = "VarUI8FromI8", [429u] = "VarUI8FromUI1", [430u] = "VarUI8FromI2", [431u] = "VarUI8FromR4", [432u] = "VarUI8FromR8", [433u] = "VarUI8FromCy", [434u] = "VarUI8FromDate", [435u] = "VarUI8FromStr", [436u] = "VarUI8FromDisp", [437u] = "VarUI8FromBool", [438u] = "VarUI8FromI1", [439u] = "VarUI8FromUI2", [440u] = "VarUI8FromUI4", [441u] = "VarUI8FromDec", [442u] = "RegisterTypeLibForUser", [443u] = "UnRegisterTypeLibForUser", [444u] = "OaEnablePerUserTLibRegistration", [445u] = "HWND_UserFree", [446u] = "HWND_UserMarshal", [447u] = "HWND_UserSize", [448u] = "HWND_UserUnmarshal", [449u] = "HWND_UserFree64", [450u] = "HWND_UserMarshal64", [451u] = "HWND_UserSize64", [452u] = "HWND_UserUnmarshal64", [500u] = "OACleanup" }; private static readonly Dictionary> _staticMappings = new Dictionary> { ["ws2_32"] = _ws2_32OrdinalMapping, ["oleaut32"] = _oleaut32OrdinalMapping }; public static DefaultSymbolResolver Instance { get; } = new DefaultSymbolResolver(); private DefaultSymbolResolver() { } public ExportedSymbol? Resolve(ImportedSymbol symbol) { if (symbol.DeclaringModule?.Name == null) { return null; } string text = symbol.DeclaringModule.Name; if (text.EndsWith(".dll")) { text = text.Remove(text.Length - 4); } if (!_staticMappings.TryGetValue(text, out Dictionary value)) { return null; } if (!value.TryGetValue(symbol.Ordinal, out var value2)) { return null; } return new ExportedSymbol(SegmentReference.Null, value2); } } public class DelegatedSymbolClassifier : IImportedSymbolClassifier { private readonly Func _classify; public DelegatedSymbolClassifier(Func classify) { _classify = classify; } public ImportedSymbolType Classify(ImportedSymbol symbol) { return _classify(symbol); } } public sealed class EmptySymbolResolver : ISymbolResolver { public static EmptySymbolResolver Instance { get; } = new EmptySymbolResolver(); private EmptySymbolResolver() { } public ExportedSymbol? Resolve(ImportedSymbol symbol) { return null; } } public interface IImportedSymbolClassifier { ImportedSymbolType Classify(ImportedSymbol symbol); } public class ImportedModule { private IList? _members; public string? Name { get; set; } public uint TimeDateStamp { get; set; } public uint ForwarderChain { get; set; } public IList Symbols { get { if (_members == null) { Interlocked.CompareExchange(ref _members, GetSymbols(), null); } return _members; } } protected ImportedModule() { } public ImportedModule(string name) { Name = name ?? throw new ArgumentNullException("name"); } public static ImportedModule? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { SerializedImportedModule serializedImportedModule = new SerializedImportedModule(context, ref reader); if (!serializedImportedModule.IsEmpty) { return serializedImportedModule; } return null; } protected virtual IList GetSymbols() { return (IList)new OwnedCollection(this); } public override string ToString() { return Name + " (" + Symbols.Count + " symbols)"; } } public class ImportedSymbol : IOwnedCollectionElement, ISymbol { private ushort _ordinalOrHint; public ImportedModule? DeclaringModule { get; private set; } ImportedModule? IOwnedCollectionElement.Owner { get { return DeclaringModule; } set { DeclaringModule = value; } } public ushort Ordinal { get { return _ordinalOrHint; } set { _ordinalOrHint = value; Name = null; } } public ushort Hint { get { return _ordinalOrHint; } set { _ordinalOrHint = value; } } public string? Name { get; set; } public ISegmentReference? AddressTableEntry { get; set; } public bool IsImportByOrdinal => Name == null; [MemberNotNullWhen(true, "Name")] public bool IsImportByName { [MemberNotNullWhen(true, "Name")] get { return Name != null; } } public ImportedSymbol(ushort ordinal) { Ordinal = ordinal; } public ImportedSymbol(ushort hint, string name) { Hint = hint; Name = name ?? throw new ArgumentNullException("name"); } public override string ToString() { string value = ((DeclaringModule == null) ? string.Empty : (DeclaringModule.Name + "!")); string value2 = ((AddressTableEntry == null) ? "???" : ((IOffsetProvider)AddressTableEntry).Rva.ToString("X8")); if (IsImportByOrdinal) { return $"{value}#{Ordinal.ToString()} ({value2})"; } return $"{value}{Name} ({value2})"; } public ISegmentReference? GetReference() { return AddressTableEntry; } } public enum ImportedSymbolType { Function, Data } public static class ImportHash { private static readonly string[] Extensions = new string[3] { ".dll", ".sys", ".ocx" }; public static byte[] GetImportHash(this PEImage image) { return image.GetImportHash(DefaultSymbolResolver.Instance); } public static byte[] GetImportHash(this PEImage image, ISymbolResolver symbolResolver) { List list = new List(); for (int i = 0; i < image.Imports.Count; i++) { ImportedModule importedModule = image.Imports[i]; string text = FormatModuleName(importedModule); for (int j = 0; j < importedModule.Symbols.Count; j++) { list.Add(text + "." + FormatSymbolName(importedModule.Symbols[j], symbolResolver)); } } using MD5 mD = MD5.Create(); return mD.ComputeHash(Encoding.ASCII.GetBytes(StringShim.Join(",", (IEnumerable)list))); } private static string FormatModuleName(ImportedModule module) { string text = module.Name; if (string.IsNullOrEmpty(text)) { return text; } string[] extensions = Extensions; foreach (string text2 in extensions) { if (text.EndsWith(text2)) { text = text.Remove(text.Length - text2.Length); break; } } return text.ToLowerInvariant(); } private static string FormatSymbolName(ImportedSymbol symbol, ISymbolResolver symbolResolver) { if (symbol.IsImportByName) { return symbol.Name.ToLowerInvariant(); } ExportedSymbol? obj = symbolResolver.Resolve(symbol) ?? throw new ArgumentException($"Failed to resolve {symbol}."); if (!obj.IsByName) { throw new ArgumentException($"Resolved export for {symbol} has no name."); } return obj.Name.ToLowerInvariant(); } } public interface ISymbolResolver { ExportedSymbol? Resolve(ImportedSymbol symbol); } public class SerializedImportedModule : ImportedModule { public const uint ModuleImportSize = 20u; private readonly PEReaderContext _context; private readonly uint _originalFirstThunkRva; private readonly uint _firstThunkRva; public bool IsEmpty { get { if (_originalFirstThunkRva == 0 && base.TimeDateStamp == 0 && base.ForwarderChain == 0 && base.Name == null) { return _firstThunkRva == 0; } return false; } } public SerializedImportedModule(PEReaderContext context, ref BinaryStreamReader reader) { if (!((BinaryStreamReader)(ref reader)).IsValid) { throw new ArgumentNullException("reader"); } _context = context ?? throw new ArgumentNullException("context"); _originalFirstThunkRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.ForwarderChain = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _firstThunkRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); if (num != 0) { BinaryStreamReader val = default(BinaryStreamReader); if (_context.File.TryCreateReaderAtRva(num, ref val)) { base.Name = ((BinaryStreamReader)(ref val)).ReadAsciiString(); } else { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Import module contains an invalid name RVA."); } } } protected override IList GetSymbols() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 OwnedCollection val = new OwnedCollection((ImportedModule)this); if (IsEmpty) { return (IList)val; } bool flag = (int)_context.File.OptionalHeader.Magic == 267; ulong num; int num2; if (!flag) { num = 9223372036854775808uL; num2 = 8; } else { num = 2147483648uL; num2 = 4; } BinaryStreamReader val2 = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_originalFirstThunkRva, ref val2) && !_context.File.TryCreateReaderAtRva(_firstThunkRva, ref val2)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Imported module \"" + base.Name + "\" has an invalid import lookup thunk table RVA."); return (IList)val; } BinaryStreamReader val3 = default(BinaryStreamReader); while (true) { ulong num3 = ((BinaryStreamReader)(ref val2)).ReadNativeInt(flag); if (num3 == 0L) { break; } ImportedSymbol importedSymbol; if ((num3 & num) != 0L) { importedSymbol = new ImportedSymbol((ushort)(num3 & 0xFFFF)); } else { uint num4 = (uint)(num3 & 0xFFFFFFFFu); if (!_context.File.TryCreateReaderAtRva(num4, ref val3)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid Hint-Name RVA for import {base.Name}!#{((LazyList)(object)val).Count.ToString()}."); importedSymbol = new ImportedSymbol(0, "<<>>"); } else { importedSymbol = new ImportedSymbol(((BinaryStreamReader)(ref val3)).ReadUInt16(), ((BinaryStreamReader)(ref val3)).ReadAsciiString()); } } importedSymbol.AddressTableEntry = _context.File.GetReferenceToRva((uint)(_firstThunkRva + ((LazyList)(object)val).Count * num2)); ((LazyList)(object)val).Add(importedSymbol); } return (IList)val; } } [DebuggerDisplay("Count = {Count}")] public class SerializedImportedModuleList : LazyList { private readonly PEReaderContext _context; private readonly DataDirectory _dataDirectory; public SerializedImportedModuleList(PEReaderContext context, in DataDirectory dataDirectory) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _dataDirectory = dataDirectory; } protected override void Initialize() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_dataDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid import data directory RVA and/or size."); return; } while (true) { ImportedModule importedModule = ImportedModule.FromReader(_context, ref reader); if (importedModule != null) { base.Items.Add(importedModule); continue; } break; } } } } namespace AsmResolver.PE.Imports.Builder { public class HintNameTableBuffer : SegmentBase { private readonly List _modules = new List(); private readonly Dictionary _moduleNameOffsets = new Dictionary(); private readonly Dictionary _hintNameOffsets = new Dictionary(); private uint _length; public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); ulong num = ((RelocationParameters)(ref parameters)).Offset; foreach (ImportedModule module in _modules) { foreach (ImportedSymbol symbol in module.Symbols) { if (symbol.IsImportByName) { _hintNameOffsets[symbol] = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); num += (uint)(2 + Encoding.ASCII.GetByteCount(symbol.Name) + 1); num = Extensions.Align(num, 2uL); } } _moduleNameOffsets[module] = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); if (module.Name != null) { num += (uint)Encoding.ASCII.GetByteCount(module.Name); } num++; } _length = (uint)(num - ((RelocationParameters)(ref parameters)).Offset); } public void AddModule(ImportedModule module) { _modules.Add(module); } public uint GetModuleNameRva(ImportedModule module) { return ((SegmentBase)this).Rva + _moduleNameOffsets[module]; } public uint GetHintNameRva(ImportedSymbol member) { return ((SegmentBase)this).Rva + _hintNameOffsets[member]; } public override uint GetPhysicalSize() { return _length; } public override void Write(BinaryStreamWriter writer) { foreach (ImportedModule module in _modules) { foreach (ImportedSymbol symbol in module.Symbols) { if (symbol.IsImportByName) { WriteHintName(writer, symbol.Hint, symbol.Name); } } WriteModuleName(writer, module); } } private static void WriteHintName(BinaryStreamWriter writer, ushort hint, string name) { writer.WriteUInt16(hint); writer.WriteAsciiString(name); writer.WriteByte((byte)0); writer.Align(2u); } private static void WriteModuleName(BinaryStreamWriter writer, ImportedModule module) { writer.WriteAsciiString(module.Name ?? string.Empty); writer.WriteByte((byte)0); } } public interface IImportAddressProvider { uint GetThunkRva(string module, string member); } public class ImportAddressDirectoryBuffer : ImportDirectoryBufferBase { public ImportAddressDirectoryBuffer(HintNameTableBuffer hintNameTable, bool is32Bit) : base(hintNameTable, is32Bit) { } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = parameters; for (int i = 0; i < base.Modules.Count; i++) { ImportedModule module = base.Modules[i]; ThunkTableBuffer moduleThunkTable = GetModuleThunkTable(module); uint physicalSize = ((SegmentBase)moduleThunkTable).GetPhysicalSize(); ((SegmentBase)moduleThunkTable).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(physicalSize); } } protected override ThunkTableBuffer CreateThunkTable() { return new ThunkTableBuffer(base.HintNameTable, base.Is32Bit, isIat: true); } } public class ImportDirectoryBuffer : ImportDirectoryBufferBase { private uint _entriesLength; public ImportAddressDirectoryBuffer ImportAddressDirectory { get; } public bool IsEmpty => _entriesLength == 0; public ImportDirectoryBuffer(bool is32Bit) : base(new HintNameTableBuffer(), is32Bit) { ImportAddressDirectory = new ImportAddressDirectoryBuffer(base.HintNameTable, is32Bit); } public override void AddModule(ImportedModule module) { if (_entriesLength == 0) { _entriesLength = 20u; } _entriesLength += 20u; ImportAddressDirectory.AddModule(module); base.AddModule(module); base.HintNameTable.AddModule(module); } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(_entriesLength); foreach (ImportedModule module in base.Modules) { ThunkTableBuffer moduleThunkTable = GetModuleThunkTable(module); uint physicalSize = ((SegmentBase)moduleThunkTable).GetPhysicalSize(); ((SegmentBase)moduleThunkTable).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(physicalSize); } ((SegmentBase)base.HintNameTable).UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return _entriesLength + base.GetPhysicalSize() + ((SegmentBase)base.HintNameTable).GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { WriteModuleImportEntries(writer); base.Write(writer); ((SegmentBase)base.HintNameTable).Write(writer); } private void WriteModuleImportEntries(BinaryStreamWriter writer) { foreach (ImportedModule module in base.Modules) { WriteModuleImportEntry(writer, module); } WriteModuleImportEntry(writer, 0u, 0u, 0u, 0u, 0u); } private void WriteModuleImportEntry(BinaryStreamWriter writer, ImportedModule module) { WriteModuleImportEntry(writer, ((SegmentBase)GetModuleThunkTable(module)).Rva, module.TimeDateStamp, module.ForwarderChain, base.HintNameTable.GetModuleNameRva(module), ((SegmentBase)ImportAddressDirectory.GetModuleThunkTable(module)).Rva); } private static void WriteModuleImportEntry(BinaryStreamWriter writer, uint oft, uint timeDateStamp, uint forwarderChain, uint moduleNameRva, uint ft) { writer.WriteUInt32(oft); writer.WriteUInt32(timeDateStamp); writer.WriteUInt32(forwarderChain); writer.WriteUInt32(moduleNameRva); writer.WriteUInt32(ft); } } public abstract class ImportDirectoryBufferBase : SegmentBase, IImportAddressProvider { private readonly Dictionary _lookupTables = new Dictionary(); private uint _lookupTablesLength; public bool Is32Bit { get; } public int Count => Modules.Count; protected IList Modules { get; } = new List(); public HintNameTableBuffer HintNameTable { get; } protected ImportDirectoryBufferBase(HintNameTableBuffer hintNameTable, bool is32Bit) { HintNameTable = hintNameTable ?? throw new ArgumentNullException("hintNameTable"); Is32Bit = is32Bit; } public virtual void AddModule(ImportedModule module) { Modules.Add(module); AddLookupTable(module); } public ThunkTableBuffer GetModuleThunkTable(ImportedModule module) { return _lookupTables[module]; } public uint GetThunkRva(string moduleName, string memberName) { string moduleName2 = moduleName; string memberName2 = memberName; ImportedModule importedModule = Modules.FirstOrDefault((ImportedModule x) => x.Name == moduleName2); if (importedModule == null) { throw new ArgumentException("Module " + moduleName2 + " is not imported.", "moduleName"); } ImportedSymbol importedSymbol = importedModule.Symbols.FirstOrDefault((ImportedSymbol x) => x.Name == memberName2); if (importedSymbol == null) { throw new ArgumentException($"Member {moduleName2}!{memberName2} is not imported.", "memberName"); } return GetModuleThunkTable(importedModule).GetMemberThunkRva(importedSymbol); } private void AddLookupTable(ImportedModule module) { ThunkTableBuffer thunkTableBuffer = CreateThunkTable(); foreach (ImportedSymbol symbol in module.Symbols) { thunkTableBuffer.AddMember(symbol); } _lookupTables.Add(module, thunkTableBuffer); _lookupTablesLength += ((SegmentBase)thunkTableBuffer).GetPhysicalSize(); } protected virtual ThunkTableBuffer CreateThunkTable() { return new ThunkTableBuffer(HintNameTable, Is32Bit, isIat: false); } public override uint GetPhysicalSize() { return _lookupTablesLength; } public override void Write(BinaryStreamWriter writer) { foreach (ImportedModule module in Modules) { ((SegmentBase)_lookupTables[module]).Write(writer); } } } public class ThunkTableBuffer : SegmentBase { private readonly List _members = new List(); private readonly Dictionary _memberOffsets = new Dictionary(); private readonly HintNameTableBuffer _hintNameTable; private readonly bool _isIat; private uint _length; public bool Is32Bit { get; } public uint ThunkSize { get { if (!Is32Bit) { return 8u; } return 4u; } } public ThunkTableBuffer(HintNameTableBuffer hintNameTable, bool is32Bit, bool isIat) { _hintNameTable = hintNameTable ?? throw new ArgumentNullException("hintNameTable"); _isIat = isIat; Is32Bit = is32Bit; _length = ThunkSize; } public void AddMember(ImportedSymbol entry) { uint num = _length - ThunkSize; if (_isIat) { entry.AddressTableEntry = Extensions.ToReference((ISegment)(object)this, (int)num); } _memberOffsets.Add(entry, num); _members.Add(entry); _length += ThunkSize; } public uint GetMemberThunkRva(ImportedSymbol member) { return ((SegmentBase)this).Rva + _memberOffsets[member]; } public override uint GetPhysicalSize() { return _length; } public override void Write(BinaryStreamWriter writer) { foreach (ImportedSymbol member in _members) { ulong num = (ulong)(member.IsImportByName ? _hintNameTable.GetHintNameRva(member) : (member.Ordinal | (1L << (Is32Bit ? 31 : 63)))); if (Is32Bit) { writer.WriteUInt32((uint)num); } else { writer.WriteUInt64(num); } } if (Is32Bit) { writer.WriteUInt32(0u); } else { writer.WriteUInt64(0uL); } } } } namespace AsmResolver.PE.Exports { public class ExportDirectory { private readonly LazyVariable _name; private IList? _exports; public uint ExportFlags { get; set; } public uint TimeDateStamp { get; set; } = uint.MaxValue; public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public string? Name { get { return _name.GetValue(this); } set { _name.SetValue(value); } } public uint BaseOrdinal { get; set; } = 1u; public IList Entries { get { if (_exports == null) { Interlocked.CompareExchange(ref _exports, GetExports(), null); } return _exports; } } protected ExportDirectory() { _name = new LazyVariable((Func)((ExportDirectory x) => x.GetName())); } public ExportDirectory(string name) { _name = new LazyVariable(name ?? throw new ArgumentNullException("name")); } protected virtual string? GetName() { return null; } protected virtual IList GetExports() { return (IList)new ExportedSymbolCollection(this); } } public class ExportedSymbol : IOwnedCollectionElement, ISymbol { public ExportDirectory? ParentDirectory { get; private set; } ExportDirectory? IOwnedCollectionElement.Owner { get { return ParentDirectory; } set { ParentDirectory = value; } } internal int Index { get; set; } public uint Ordinal { get { if (Index != -1) { return (uint)Index + (ParentDirectory?.BaseOrdinal ?? 0); } return 0u; } } [MemberNotNullWhen(false, "Name")] public bool IsByOrdinal { [MemberNotNullWhen(false, "Name")] get { return Name == null; } } [MemberNotNullWhen(true, "Name")] public bool IsByName { [MemberNotNullWhen(true, "Name")] get { return Name != null; } } public string? Name { get; set; } public ISegmentReference Address { get; set; } public string? ForwarderName { get; set; } [MemberNotNullWhen(true, "ForwarderName")] public bool IsForwarder { [MemberNotNullWhen(true, "ForwarderName")] get { return ForwarderName != null; } } public ExportedSymbol(ISegmentReference address) { Name = null; Address = address; } public ExportedSymbol(ISegmentReference address, string? name) { Name = name; Address = address; } public ExportedSymbol(ISegmentReference address, string? name, string? forwarderName) { Name = name; Address = address; ForwarderName = forwarderName; } public string FormatNameAsForwarderSymbol() { return FormatFullName('.'); } private string FormatFullName(char separator) { string text = Name ?? ("#" + Ordinal); ExportDirectory parentDirectory = ParentDirectory; if (parentDirectory != null) { string text2 = parentDirectory.Name; if (text2 != null) { if (string.Equals(Path.GetExtension(text2), ".dll", StringComparison.OrdinalIgnoreCase)) { text2 = Path.GetFileNameWithoutExtension(text2); } return $"{text2}{separator}{text}"; } } return text; } public override string ToString() { return FormatFullName('!'); } public ISegmentReference GetReference() { return Address; } } public class ExportedSymbolCollection : OwnedCollection { public ExportedSymbolCollection(ExportDirectory owner) : base(owner) { } private void UpdateIndicesAfterIndex(int index) { for (int i = index; i < ((LazyList)(object)this).Count; i++) { ((LazyList)(object)this).Items[i].Index = i; } } protected override void OnClearItems() { lock (((LazyList)(object)this).Items) { foreach (ExportedSymbol item in ((LazyList)(object)this).Items) { item.Index = -1; } base.OnClearItems(); } } protected override void OnInsertItem(int index, ExportedSymbol item) { lock (((LazyList)(object)this).Items) { base.OnInsertItem(index, item); UpdateIndicesAfterIndex(index); } } protected override void OnInsertRange(int index, IEnumerable items) { lock (((LazyList)(object)this).Items) { ExportedSymbol[] array = (items as ExportedSymbol[]) ?? items.ToArray(); base.OnInsertRange(index, (IEnumerable)array); for (int i = index; i < ((LazyList)(object)this).Count; i++) { ((LazyList)(object)this).Items[i].Index = i; } } } protected override void OnRemoveItem(int index) { lock (((LazyList)(object)this).Items) { ((LazyList)(object)this).Items[index].Index = -1; base.OnRemoveItem(index); UpdateIndicesAfterIndex(index); } } protected override void OnSetItem(int index, ExportedSymbol item) { lock (((LazyList)(object)this).Items) { base.AssertNotNullAndHasNoOwner(item); ((LazyList)(object)this).Items[index].Index = -1; base.OnSetItem(index, item); item.Index = index; } } } public class SerializedExportDirectory : ExportDirectory { private readonly PEReaderContext _context; private readonly DataDirectory _dataDirectory; private readonly uint _nameRva; private readonly uint _numberOfFunctions; private readonly uint _numberOfNames; private readonly uint _addressTableRva; private readonly uint _namePointerRva; private readonly uint _ordinalTableRva; public SerializedExportDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!((BinaryStreamReader)(ref reader)).IsValid) { throw new ArgumentNullException("reader"); } _context = context ?? throw new ArgumentNullException("context"); _dataDirectory = new DataDirectory(((BinaryStreamReader)(ref reader)).StartRva, ((BinaryStreamReader)(ref reader)).Length); base.ExportFlags = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); _nameRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.BaseOrdinal = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _numberOfFunctions = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _numberOfNames = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _addressTableRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _namePointerRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _ordinalTableRva = ((BinaryStreamReader)(ref reader)).ReadUInt32(); } protected override string? GetName() { BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_nameRva, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid name RVA."); return null; } return ((BinaryStreamReader)(ref val)).ReadAsciiString(); } protected override IList GetExports() { ExportedSymbolCollection exportedSymbolCollection = new ExportedSymbolCollection(this); if (_numberOfFunctions == 0) { return (IList)exportedSymbolCollection; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_addressTableRva, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid address table RVA."); return (IList)exportedSymbolCollection; } IDictionary dictionary = null; if (_namePointerRva != 0 || _ordinalTableRva != 0) { BinaryStreamReader namePointerReader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_namePointerRva, ref namePointerReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid name pointer table RVA."); } BinaryStreamReader ordinalReader = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_ordinalTableRva, ref ordinalReader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Export directory contains an invalid ordinal table RVA."); } if (((BinaryStreamReader)(ref namePointerReader)).IsValid || ((BinaryStreamReader)(ref ordinalReader)).IsValid) { dictionary = ReadOrdinalNameTable(ref namePointerReader, ref ordinalReader); } } BinaryStreamReader val2 = default(BinaryStreamReader); for (uint num = 0u; num < _numberOfFunctions; num++) { uint num2 = ((BinaryStreamReader)(ref val)).ReadUInt32(); string value = null; dictionary?.TryGetValue(num, out value); string forwarderName = null; if (num2 >= ((DataDirectory)(ref _dataDirectory)).VirtualAddress && num2 < ((DataDirectory)(ref _dataDirectory)).VirtualAddress + ((DataDirectory)(ref _dataDirectory)).Size && _context.File.TryCreateReaderAtRva(num2, ref val2)) { forwarderName = ((BinaryStreamReader)(ref val2)).ReadAsciiString(); } ((LazyList)(object)exportedSymbolCollection).Add(new ExportedSymbol(_context.File.GetReferenceToRva(num2), value, forwarderName)); } return (IList)exportedSymbolCollection; } private Dictionary ReadOrdinalNameTable(ref BinaryStreamReader namePointerReader, ref BinaryStreamReader ordinalReader) { Dictionary dictionary = new Dictionary(); BinaryStreamReader val = default(BinaryStreamReader); for (int i = 0; i < _numberOfNames; i++) { uint key = ((BinaryStreamReader)(ref ordinalReader)).ReadUInt16(); uint num = ((BinaryStreamReader)(ref namePointerReader)).ReadUInt32(); if (_context.File.TryCreateReaderAtRva(num, ref val)) { dictionary[key] = ((BinaryStreamReader)(ref val)).ReadAsciiString(); } } return dictionary; } } } namespace AsmResolver.PE.Exports.Builder { public class ExportAddressTableBuffer : SegmentBase { private readonly List _entries = new List(); private readonly NameTableBuffer _nameTableBuffer; public ExportAddressTableBuffer(NameTableBuffer nameTableBuffer) { _nameTableBuffer = nameTableBuffer; } public void AddSymbol(ExportedSymbol symbol) { _entries.Add(symbol); } public override uint GetPhysicalSize() { return (uint)(_entries.Count * 4); } public override void Write(BinaryStreamWriter writer) { foreach (ExportedSymbol entry in _entries) { writer.WriteUInt32(entry.IsForwarder ? _nameTableBuffer.GetNameRva(entry.ForwarderName) : ((IOffsetProvider)entry.Address).Rva); } } } public class ExportDirectoryBuffer : SegmentBase { public const uint ExportDirectoryHeaderSize = 40u; private readonly SegmentBuilder _contentsBuilder; private readonly ExportAddressTableBuffer _addressTableBuffer; private readonly OrdinalNamePointerTableBuffer _ordinalNamePointerTable; private readonly NameTableBuffer _nameTableBuffer; private ExportDirectory? _exportDirectory; [MemberNotNullWhen(false, "_exportDirectory")] public bool IsEmpty { [MemberNotNullWhen(false, "_exportDirectory")] get { return _exportDirectory == null; } } public ExportDirectoryBuffer() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown _nameTableBuffer = new NameTableBuffer(); _addressTableBuffer = new ExportAddressTableBuffer(_nameTableBuffer); _ordinalNamePointerTable = new OrdinalNamePointerTableBuffer(_nameTableBuffer); SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(object)_addressTableBuffer); val.Add((ISegment)(object)_ordinalNamePointerTable); val.Add((ISegment)(object)_nameTableBuffer); _contentsBuilder = val; } public void AddDirectory(ExportDirectory exportDirectory) { if (!IsEmpty) { throw new InvalidProgramException("Cannot add a secondary export directory to the buffer."); } _exportDirectory = exportDirectory; _nameTableBuffer.AddName(exportDirectory.Name); foreach (ExportedSymbol entry in exportDirectory.Entries) { _addressTableBuffer.AddSymbol(entry); _ordinalNamePointerTable.AddSymbol(entry); if (entry.IsByName) { _nameTableBuffer.AddName(entry.Name); } if (entry.IsForwarder) { _nameTableBuffer.AddName(entry.ForwarderName); } } } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); SegmentBuilder contentsBuilder = _contentsBuilder; RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(40u); contentsBuilder.UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return 40 + _contentsBuilder.GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { WriteExportDirectoryHeader(writer); _contentsBuilder.Write(writer); } private void WriteExportDirectoryHeader(BinaryStreamWriter writer) { if (_exportDirectory == null) { _exportDirectory = new ExportDirectory(string.Empty); } writer.WriteUInt32(_exportDirectory.ExportFlags); writer.WriteUInt32(_exportDirectory.TimeDateStamp); writer.WriteUInt16(_exportDirectory.MajorVersion); writer.WriteUInt16(_exportDirectory.MinorVersion); writer.WriteUInt32(_nameTableBuffer.GetNameRva(_exportDirectory.Name)); writer.WriteUInt32(_exportDirectory.BaseOrdinal); writer.WriteUInt32((uint)_exportDirectory.Entries.Count); writer.WriteUInt32((uint)_exportDirectory.Entries.Count((ExportedSymbol e) => e.IsByName)); writer.WriteUInt32(((SegmentBase)_addressTableBuffer).Rva); writer.WriteUInt32(_ordinalNamePointerTable.NamePointerTableRva); writer.WriteUInt32(_ordinalNamePointerTable.OrdinalTableRva); } } public class NameTableBuffer : SegmentBase { private readonly List _entries = new List(); private readonly Dictionary _nameOffsets = new Dictionary(); private uint _length; public void AddName(string? name) { if (!string.IsNullOrEmpty(name) && !_nameOffsets.ContainsKey(name)) { _entries.Add(name); _nameOffsets.Add(name, _length); _length += (uint)(Encoding.ASCII.GetByteCount(name) + 1); } } public uint GetNameRva(string? name) { if (name == null) { return 0u; } return ((SegmentBase)this).Rva + _nameOffsets[name]; } public override uint GetPhysicalSize() { return _length; } public override void Write(BinaryStreamWriter writer) { foreach (string entry in _entries) { writer.WriteAsciiString(entry); writer.WriteByte((byte)0); } } } public class OrdinalNamePointerTableBuffer : SegmentBase { private readonly NameTableBuffer _nameTableBuffer; private readonly List _ordinals = new List(); private readonly List _namedEntries = new List(); public uint OrdinalTableRva => ((SegmentBase)this).Rva; public uint OrdinalTableSize => (uint)(_ordinals.Count * 2); public uint NamePointerTableRva => ((SegmentBase)this).Rva + OrdinalTableSize; public uint NamePointerTableSize => (uint)(_namedEntries.Count * 4); public OrdinalNamePointerTableBuffer(NameTableBuffer nameTableBuffer) { _nameTableBuffer = nameTableBuffer ?? throw new ArgumentNullException("nameTableBuffer"); } public void AddSymbol(ExportedSymbol symbol) { if (symbol.ParentDirectory == null) { throw new ArgumentException("Symbol was not added to an export directory."); } if (symbol.IsByName) { _namedEntries.Add(symbol); _ordinals.Add((ushort)(symbol.Ordinal - symbol.ParentDirectory.BaseOrdinal)); } } public override uint GetPhysicalSize() { return OrdinalTableSize + NamePointerTableSize; } public override void Write(BinaryStreamWriter writer) { WriteOrdinalTable(writer); WriteNamePointerTable(writer); } private void WriteNamePointerTable(BinaryStreamWriter writer) { foreach (ExportedSymbol namedEntry in _namedEntries) { writer.WriteUInt32(_nameTableBuffer.GetNameRva(namedEntry.Name)); } } private void WriteOrdinalTable(BinaryStreamWriter writer) { foreach (ushort ordinal in _ordinals) { writer.WriteUInt16(ordinal); } } } } namespace AsmResolver.PE.Exceptions { public class ExceptionDirectory : IExceptionDirectory where TFunction : IRuntimeFunction { private IList? _entries; public IList Entries { get { if (_entries == null) { Interlocked.CompareExchange(ref _entries, GetEntries(), null); } return _entries; } } protected virtual IList GetEntries() { return new List(); } IEnumerable IExceptionDirectory.GetEntries() { return (IEnumerable)Entries; } } public interface IExceptionDirectory { IEnumerable GetEntries(); } public interface IRuntimeFunction { ISegmentReference Begin { get; } ISegmentReference End { get; } } internal class X64ExceptionDirectory : ExceptionDirectory { private readonly PEReaderContext _context; private readonly BinaryStreamReader _reader; public X64ExceptionDirectory(PEReaderContext context, in BinaryStreamReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _reader = reader; } protected override IList GetEntries() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); List list = new List(); while (((BinaryStreamReader)(ref reader)).CanRead(12u)) { X64RuntimeFunction x64RuntimeFunction = X64RuntimeFunction.FromReader(_context, ref reader); if (x64RuntimeFunction == null) { break; } list.Add(x64RuntimeFunction); } return list; } } public class X64RuntimeFunction : IRuntimeFunction, IWritable { public const int EntrySize = 12; public ISegmentReference Begin { get; set; } public ISegmentReference End { get; set; } public X64UnwindInfo? UnwindInfo { get; set; } public X64RuntimeFunction(ISegmentReference begin, ISegmentReference end, X64UnwindInfo? unwindInfo) { Begin = begin; End = end; UnwindInfo = unwindInfo; } public static X64RuntimeFunction FromReader(PEReaderContext context, ref BinaryStreamReader reader) { uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num2 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num3 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); BinaryStreamReader reader2 = default(BinaryStreamReader); X64UnwindInfo unwindInfo = (context.File.TryCreateReaderAtRva(num3, ref reader2) ? X64UnwindInfo.FromReader(context, ref reader2) : ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)context, $"Invalid UnwindInfo RVA {num3:X8}.")); return new X64RuntimeFunction(context.File.GetReferenceToRva(num), context.File.GetReferenceToRva(num2), unwindInfo); } public uint GetPhysicalSize() { return 12u; } public void Write(BinaryStreamWriter writer) { writer.WriteUInt32(((IOffsetProvider)Begin).Rva); writer.WriteUInt32(((IOffsetProvider)End).Rva); X64UnwindInfo? unwindInfo = UnwindInfo; writer.WriteUInt32((unwindInfo != null) ? ((SegmentBase)unwindInfo).Rva : 0u); } } [Flags] public enum X64UnwindFlags : byte { NoHandler = 0, ExceptionHandler = 1, TerminationHandler = 2, ChainedUnwindInfo = 4 } public class X64UnwindInfo : SegmentBase { private byte _firstByte; private byte _frameByte; public byte Version { get { return (byte)(_firstByte & 7u); } set { _firstByte = (byte)((_firstByte & 0xF8u) | (value & 7u)); } } public X64UnwindFlags Flags { get { return (X64UnwindFlags)(_firstByte >> 3); } set { _firstByte = (byte)((_firstByte & 7u) | ((uint)value << 3)); } } public bool IsExceptionHandler { get { return (Flags & X64UnwindFlags.ExceptionHandler) != 0; } set { Flags = (Flags & ~X64UnwindFlags.ExceptionHandler) | (value ? X64UnwindFlags.ExceptionHandler : X64UnwindFlags.NoHandler); } } public bool IsTerminationHandler { get { return (Flags & X64UnwindFlags.TerminationHandler) != 0; } set { Flags = (Flags & ~X64UnwindFlags.TerminationHandler) | (value ? X64UnwindFlags.TerminationHandler : X64UnwindFlags.NoHandler); } } public bool IsChained { get { return (Flags & X64UnwindFlags.ChainedUnwindInfo) != 0; } set { Flags = (Flags & ~X64UnwindFlags.ChainedUnwindInfo) | (value ? X64UnwindFlags.ChainedUnwindInfo : X64UnwindFlags.NoHandler); } } public byte SizeOfProlog { get; set; } public byte FrameRegister { get { return (byte)(_frameByte & 0xFu); } set { _frameByte = (byte)((_frameByte & 0xF0u) | (value & 0xFu)); } } public byte FrameRegisterOffset { get { return (byte)(_frameByte >> 4); } set { _frameByte = (byte)((_frameByte & 0xFu) | (uint)(value << 4)); } } public ushort[] UnwindCodes { get; set; } public ISegmentReference ExceptionHandler { get; set; } public ISegmentReference ExceptionHandlerData { get; set; } public X64RuntimeFunction? ChainedFunction { get; set; } public X64UnwindInfo() { Version = 1; UnwindCodes = ArrayShim.Empty(); ExceptionHandler = SegmentReference.Null; ExceptionHandlerData = SegmentReference.Null; } public static X64UnwindInfo FromReader(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) X64UnwindInfo x64UnwindInfo = new X64UnwindInfo(); RelocationParameters relocation = context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); ((SegmentBase)x64UnwindInfo).UpdateOffsets(ref relocation); x64UnwindInfo._firstByte = ((BinaryStreamReader)(ref reader)).ReadByte(); x64UnwindInfo.SizeOfProlog = ((BinaryStreamReader)(ref reader)).ReadByte(); byte b = ((BinaryStreamReader)(ref reader)).ReadByte(); x64UnwindInfo._frameByte = ((BinaryStreamReader)(ref reader)).ReadByte(); ushort[] array = new ushort[b]; for (int i = 0; i < b; i++) { array[i] = ((BinaryStreamReader)(ref reader)).ReadUInt16(); } x64UnwindInfo.UnwindCodes = array; if (x64UnwindInfo.IsExceptionHandler || x64UnwindInfo.IsTerminationHandler) { x64UnwindInfo.ExceptionHandler = context.File.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()); x64UnwindInfo.ExceptionHandlerData = context.File.GetReferenceToRva(((BinaryStreamReader)(ref reader)).Rva); } else if (x64UnwindInfo.IsChained) { x64UnwindInfo.ChainedFunction = X64RuntimeFunction.FromReader(context, ref reader); } return x64UnwindInfo; } public override uint GetPhysicalSize() { uint num = (uint)(4 + UnwindCodes.Length * 2); if (IsExceptionHandler) { num += 4; } else if (IsChained) { num += 12; } return num; } public override void Write(BinaryStreamWriter writer) { writer.WriteByte(_firstByte); writer.WriteByte(SizeOfProlog); writer.WriteByte((byte)UnwindCodes.Length); writer.WriteByte(_frameByte); ushort[] unwindCodes = UnwindCodes; foreach (ushort num in unwindCodes) { writer.WriteUInt16(num); } if (IsExceptionHandler || IsTerminationHandler) { writer.WriteUInt32(((IOffsetProvider)ExceptionHandler).Rva); } else if (IsChained && ChainedFunction != null) { ChainedFunction.Write(writer); } } } } namespace AsmResolver.PE.DotNet { public class CustomManagedNativeHeader : SegmentBase, IManagedNativeHeader, ISegment, IOffsetProvider, IWritable { public ManagedNativeHeaderSignature Signature { get; } public ISegment Contents { get; } public CustomManagedNativeHeader(ManagedNativeHeaderSignature signature, ISegment contents) { Signature = signature; Contents = contents; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); ISegment contents = Contents; RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(4u); contents.UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return 4 + ((IWritable)Contents).GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32((uint)Signature); ((IWritable)Contents).Write(writer); } } public class DotNetDirectory : SegmentBase { private readonly LazyVariable _metadata; private readonly LazyVariable _resources; private readonly LazyVariable _strongName; private readonly LazyVariable _codeManagerTable; private readonly LazyVariable _exportAddressTable; private readonly LazyVariable _vtableFixups; private readonly LazyVariable _managedNativeHeader; public ushort MajorRuntimeVersion { get; set; } = 2; public ushort MinorRuntimeVersion { get; set; } = 5; public MetadataDirectory? Metadata { get { return _metadata.GetValue(this); } set { _metadata.SetValue(value); } } public DotNetDirectoryFlags Flags { get; set; } public DotNetEntryPoint EntryPoint { get; set; } public DotNetResourcesDirectory? DotNetResources { get { return _resources.GetValue(this); } set { _resources.SetValue(value); } } public IReadableSegment? StrongName { get { return _strongName.GetValue(this); } set { _strongName.SetValue(value); } } public IReadableSegment? CodeManagerTable { get { return _codeManagerTable.GetValue(this); } set { _codeManagerTable.SetValue(value); } } public VTableFixupsDirectory? VTableFixups { get { return _vtableFixups.GetValue(this); } set { _vtableFixups.SetValue(value); } } public IReadableSegment? ExportAddressTable { get { return _exportAddressTable.GetValue(this); } set { _exportAddressTable.SetValue(value); } } public IManagedNativeHeader? ManagedNativeHeader { get { return _managedNativeHeader.GetValue(this); } set { _managedNativeHeader.SetValue(value); } } public DotNetDirectory() { _metadata = new LazyVariable((Func)((DotNetDirectory x) => x.GetMetadata())); _resources = new LazyVariable((Func)((DotNetDirectory x) => x.GetResources())); _strongName = new LazyVariable((Func)((DotNetDirectory x) => x.GetStrongName())); _codeManagerTable = new LazyVariable((Func)((DotNetDirectory x) => x.GetCodeManagerTable())); _exportAddressTable = new LazyVariable((Func)((DotNetDirectory x) => x.GetExportAddressTable())); _vtableFixups = new LazyVariable((Func)((DotNetDirectory x) => x.GetVTableFixups())); _managedNativeHeader = new LazyVariable((Func)((DotNetDirectory x) => x.GetManagedNativeHeader())); } public override uint GetPhysicalSize() { return 72u; } public override void Write(BinaryStreamWriter writer) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) writer.WriteUInt32(((SegmentBase)this).GetPhysicalSize()); writer.WriteUInt16(MajorRuntimeVersion); writer.WriteUInt16(MinorRuntimeVersion); DataDirectory val = DataDirectory.CreateForSegment((ISegment)(object)Metadata); ((DataDirectory)(ref val)).Write(writer); writer.WriteUInt32((uint)Flags); writer.WriteUInt32(EntryPoint.GetRawValue()); val = DataDirectory.CreateForSegment((ISegment)(object)DotNetResources); ((DataDirectory)(ref val)).Write(writer); val = DataDirectory.CreateForSegment((ISegment)(object)StrongName); ((DataDirectory)(ref val)).Write(writer); val = DataDirectory.CreateForSegment((ISegment)(object)CodeManagerTable); ((DataDirectory)(ref val)).Write(writer); val = DataDirectory.CreateForSegment((ISegment)(object)VTableFixups); ((DataDirectory)(ref val)).Write(writer); val = DataDirectory.CreateForSegment((ISegment)(object)ExportAddressTable); ((DataDirectory)(ref val)).Write(writer); val = DataDirectory.CreateForSegment((ISegment)ManagedNativeHeader); ((DataDirectory)(ref val)).Write(writer); } protected virtual MetadataDirectory? GetMetadata() { return null; } protected virtual DotNetResourcesDirectory? GetResources() { return null; } protected virtual IReadableSegment? GetStrongName() { return null; } protected virtual IReadableSegment? GetCodeManagerTable() { return null; } protected virtual IReadableSegment? GetExportAddressTable() { return null; } protected virtual VTableFixupsDirectory? GetVTableFixups() { return null; } protected virtual IManagedNativeHeader? GetManagedNativeHeader() { return null; } } [Flags] public enum DotNetDirectoryFlags { ILOnly = 1, Bit32Required = 2, ILLibrary = 4, StrongNameSigned = 8, NativeEntryPoint = 0x10, TrackDebugData = 0x10000, Bit32Preferred = 0x20000 } public static class DotNetDirectoryFlagsExtensions { public static bool IsLoadedAs32Bit(this DotNetDirectoryFlags flags, Platform platform) { return flags.IsLoadedAs32Bit(platform, assume32BitSystem: false, canLoadAs32Bit: true); } public static bool IsLoadedAs32Bit(this DotNetDirectoryFlags flags, Platform platform, bool assume32BitSystem, bool canLoadAs32Bit) { if (!platform.Is32Bit) { return false; } if (!(platform is I386Platform)) { return true; } if ((flags & DotNetDirectoryFlags.ILOnly) == 0) { return true; } if ((flags & DotNetDirectoryFlags.Bit32Required) != 0) { return true; } if ((flags & DotNetDirectoryFlags.Bit32Preferred) != 0) { return assume32BitSystem || canLoadAs32Bit; } return assume32BitSystem; } } public readonly struct DotNetEntryPoint { public bool IsPresent { get { if (!IsManaged) { return IsNative; } return true; } } public bool IsManaged => MetadataToken != MetadataToken.Zero; [MemberNotNullWhen(true, "NativeCode")] public bool IsNative { [MemberNotNullWhen(true, "NativeCode")] get { return NativeCode != null; } } public MetadataToken MetadataToken { get; } public ISegmentReference? NativeCode { get; } public DotNetEntryPoint(MetadataToken token) { if (token != MetadataToken.Zero && token.Table != TableIndex.Method) { throw new ArgumentException("Managed entry points can only be metadata tokens referencing a method or a file."); } MetadataToken = token; NativeCode = null; } public DotNetEntryPoint(ISegmentReference nativeCode) { MetadataToken = MetadataToken.Zero; NativeCode = nativeCode; } public uint GetRawValue() { if (!IsNative) { return MetadataToken.ToUInt32(); } return ((IOffsetProvider)NativeCode).Rva; } public static implicit operator DotNetEntryPoint(MetadataToken token) { return new DotNetEntryPoint(token); } public static implicit operator DotNetEntryPoint(SegmentReference nativeCode) { return new DotNetEntryPoint((ISegmentReference)(object)nativeCode); } [Obsolete("Construct entry points via a MetadataToken or an ISegmentReference instead.")] public static implicit operator DotNetEntryPoint(uint value) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown MetadataToken token = new MetadataToken(value); TableIndex table = token.Table; if ((table != TableIndex.Method && table != TableIndex.File) || 1 == 0) { return new DotNetEntryPoint((ISegmentReference)new VirtualAddress(value)); } return new DotNetEntryPoint(token); } public static implicit operator uint(DotNetEntryPoint value) { return value.GetRawValue(); } } public interface IManagedNativeHeader : ISegment, IOffsetProvider, IWritable { ManagedNativeHeaderSignature Signature { get; } } public enum ManagedNativeHeaderSignature : uint { NGen = 1313163086u, Rtr = 5395538u } public class SerializedDotNetDirectory : DotNetDirectory { private readonly PEReaderContext _context; private readonly DataDirectory _metadataDirectory; private readonly DataDirectory _resourcesDirectory; private readonly DataDirectory _strongNameDirectory; private readonly DataDirectory _codeManagerDirectory; private readonly DataDirectory _vtableFixupsDirectory; private readonly DataDirectory _exportsDirectory; private readonly DataDirectory _nativeHeaderDirectory; public SerializedDotNetDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.MajorRuntimeVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.MinorRuntimeVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); _metadataDirectory = DataDirectory.FromReader(ref reader); base.Flags = (DotNetDirectoryFlags)((BinaryStreamReader)(ref reader)).ReadUInt32(); base.EntryPoint = (((base.Flags & DotNetDirectoryFlags.NativeEntryPoint) != 0) ? new DotNetEntryPoint(context.File.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32())) : new DotNetEntryPoint(new MetadataToken(((BinaryStreamReader)(ref reader)).ReadUInt32()))); _resourcesDirectory = DataDirectory.FromReader(ref reader); _strongNameDirectory = DataDirectory.FromReader(ref reader); _codeManagerDirectory = DataDirectory.FromReader(ref reader); _vtableFixupsDirectory = DataDirectory.FromReader(ref reader); _exportsDirectory = DataDirectory.FromReader(ref reader); _nativeHeaderDirectory = DataDirectory.FromReader(ref reader); } protected override MetadataDirectory? GetMetadata() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _metadataDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_metadataDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid metadata directory RVA and/or size."); return null; } return MetadataDirectory.FromReader(reader, MetadataReaderContext.FromReaderContext(_context)); } protected override DotNetResourcesDirectory? GetResources() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _resourcesDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_resourcesDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid resources directory RVA and/or size."); return null; } return new SerializedDotNetResourcesDirectory(in reader); } protected override IReadableSegment? GetStrongName() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _strongNameDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_strongNameDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid strong name directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override IReadableSegment? GetCodeManagerTable() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _codeManagerDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_codeManagerDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid code manager directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override VTableFixupsDirectory? GetVTableFixups() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _vtableFixupsDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_vtableFixupsDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid VTable fixups directory RVA and/or size."); return null; } VTableFixupsDirectory vTableFixupsDirectory = new VTableFixupsDirectory(); RelocationParameters parameters = _context.GetRelocation(((BinaryStreamReader)(ref reader)).Offset, ((BinaryStreamReader)(ref reader)).Rva); vTableFixupsDirectory.UpdateOffsets(in parameters); for (int i = 0; i < ((BinaryStreamReader)(ref reader)).Length / 8; i++) { VTableFixup vTableFixup = VTableFixup.FromReader(_context, ref reader); if (vTableFixup == null) { break; } vTableFixupsDirectory.Add(vTableFixup); } return vTableFixupsDirectory; } protected override IReadableSegment? GetExportAddressTable() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _exportsDirectory)).IsPresentInPE) { return null; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_exportsDirectory, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid export address directory RVA and/or size."); return null; } return (IReadableSegment?)(object)DataSegment.FromReader(ref val); } protected override IManagedNativeHeader? GetManagedNativeHeader() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!((DataDirectory)(ref _nativeHeaderDirectory)).IsPresentInPE) { return null; } BinaryStreamReader reader = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_nativeHeaderDirectory, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, ".NET data directory contains an invalid native header directory RVA and/or size."); return null; } BinaryStreamReader val = ((BinaryStreamReader)(ref reader)).Fork(); ManagedNativeHeaderSignature managedNativeHeaderSignature = (ManagedNativeHeaderSignature)((BinaryStreamReader)(ref val)).ReadUInt32(); if (managedNativeHeaderSignature == ManagedNativeHeaderSignature.Rtr) { return new SerializedReadyToRunDirectory(_context, ref reader); } return new CustomManagedNativeHeader(managedNativeHeaderSignature, (ISegment)(object)((BinaryStreamReader)(ref reader)).ReadSegment(((BinaryStreamReader)(ref reader)).RemainingLength)); } } } namespace AsmResolver.PE.DotNet.VTableFixups { public class VTableFixup : SegmentBase { public VTableTokenCollection Tokens { get; } = new VTableTokenCollection(); public VTableFixup(VTableType type) { Tokens.Type = type; } public static VTableFixup? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; BinaryStreamReader val = default(BinaryStreamReader); if (!context.File.TryCreateReaderAtRva(((BinaryStreamReader)(ref reader)).ReadUInt32(), ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)context, "VTable fixups directory contains an invalid RVA for the entries of a vtable."); return null; } ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); VTableFixup vTableFixup = new VTableFixup((VTableType)((BinaryStreamReader)(ref reader)).ReadUInt16()); RelocationParameters relocation = context.GetRelocation(offset, rva); ((SegmentBase)vTableFixup).UpdateOffsets(ref relocation); VTableTokenCollection tokens = vTableFixup.Tokens; relocation = context.GetRelocation(((BinaryStreamReader)(ref val)).Offset, ((BinaryStreamReader)(ref val)).Rva); tokens.UpdateOffsets(in relocation); for (int i = 0; i < num; i++) { vTableFixup.Tokens.Add(((vTableFixup.Tokens.Type & VTableType.VTable32Bit) != 0) ? new MetadataToken(((BinaryStreamReader)(ref val)).ReadUInt32()) : new MetadataToken((uint)((BinaryStreamReader)(ref val)).ReadInt64())); } return vTableFixup; } public override uint GetPhysicalSize() { return 8u; } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32(Tokens.Rva); writer.WriteUInt16((ushort)Tokens.Count); writer.WriteUInt16((ushort)Tokens.Type); } } public class VTableFixupsDirectory : Collection, ISegment, IOffsetProvider, IWritable { public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; public void UpdateOffsets(in RelocationParameters parameters) { Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; } public uint GetPhysicalSize() { return (uint)this.Sum((VTableFixup v) => ((SegmentBase)v).GetPhysicalSize()); } public void Write(BinaryStreamWriter writer) { for (int i = 0; i < base.Count; i++) { ((SegmentBase)base[i]).Write(writer); } } public uint GetVirtualSize() { return (uint)this.Sum((VTableFixup v) => ((SegmentBase)v).GetVirtualSize()); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class VTableTokenCollection : Collection, ISegment, IOffsetProvider, IWritable { public VTableType Type { get; set; } public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; protected override void InsertItem(int index, MetadataToken item) { if (base.Count >= 65535) { throw new InvalidOperationException("Number of VTable tokens exceeds the maximum of 65535."); } base.InsertItem(index, item); } public void UpdateOffsets(in RelocationParameters parameters) { Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; } public uint GetPhysicalSize() { return (uint)(base.Count * (((Type & VTableType.VTable32Bit) != 0) ? 4 : 8)); } public void Write(BinaryStreamWriter writer) { for (int i = 0; i < base.Items.Count; i++) { MetadataToken metadataToken = base.Items[i]; if ((Type & VTableType.VTable32Bit) != 0) { writer.WriteUInt32(metadataToken.ToUInt32()); } else { writer.WriteUInt64((ulong)metadataToken.ToUInt32()); } } } public uint GetVirtualSize() { return GetPhysicalSize(); } public ISegmentReference GetReferenceToIndex(int index) { return Extensions.ToReference((ISegment)(object)this, (int)GetOffsetToIndex(index)); } public uint GetOffsetToIndex(int index) { int num = (((Type & VTableType.VTable32Bit) != 0) ? 4 : 8); return (uint)(index * num); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } [Flags] public enum VTableType : ushort { VTable32Bit = 1, VTable64Bit = 2, VTableFromUnmanaged = 4, VTableCallMostDerived = 0x10 } } namespace AsmResolver.PE.DotNet.StrongName { public enum RsaPublicKeyMagic { Rsa1 = 826364754, Rsa2 = 843141970 } public enum SignatureAlgorithm : uint { RsaSign = 9216u } internal class StrongNameDataHashBuilder { private readonly Stream _imageStream; private readonly AssemblyHashAlgorithm _hashAlgorithm; private readonly List _includedRanges = new List(); private readonly List _zeroRanges = new List(); public StrongNameDataHashBuilder(Stream imageStream, AssemblyHashAlgorithm hashAlgorithm) { _imageStream = imageStream ?? throw new ArgumentNullException("imageStream"); _hashAlgorithm = hashAlgorithm; } public void IncludeRange(OffsetRange range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _includedRanges.Add(range); } public void ExcludeRange(OffsetRange range) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _includedRanges.Count; i++) { OffsetRange val = _includedRanges[i]; var (value, val2) = ((OffsetRange)(ref val)).Exclude(range); if (((OffsetRange)(ref value)).IsEmpty) { _includedRanges[i] = val2; continue; } if (((OffsetRange)(ref val2)).IsEmpty) { _includedRanges[i] = value; continue; } _includedRanges[i] = value; _includedRanges.Insert(i + 1, val2); i++; } } public void ZeroRange(OffsetRange range) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _zeroRanges.Add(range); } public byte[] ComputeHash() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) using HashAlgorithm hashAlgorithm = _hashAlgorithm switch { AssemblyHashAlgorithm.Md5 => MD5.Create(), AssemblyHashAlgorithm.Sha1 => SHA1.Create(), AssemblyHashAlgorithm.Sha256 => SHA256.Create(), AssemblyHashAlgorithm.Sha384 => SHA384.Create(), AssemblyHashAlgorithm.Sha512 => SHA512.Create(), _ => throw new NotSupportedException($"Invalid or unsupported hashing algorithm {_hashAlgorithm}."), }; byte[] array = new byte[4096]; OffsetRange currentRange = default(OffsetRange); foreach (OffsetRange includedRange in _includedRanges) { OffsetRange current = includedRange; _imageStream.Position = (long)((OffsetRange)(ref current)).Start; while ((ulong)_imageStream.Position < ((OffsetRange)(ref current)).End) { int num = Math.Min(array.Length, (int)((long)((OffsetRange)(ref current)).End - _imageStream.Position)); ((OffsetRange)(ref currentRange))..ctor((ulong)(uint)_imageStream.Position, (ulong)(uint)(_imageStream.Position + num)); _imageStream.Read(array, 0, num); ZeroRangesIfApplicable(array, currentRange); hashAlgorithm.TransformBlock(array, 0, num, array, 0); } } hashAlgorithm.TransformFinalBlock(ArrayShim.Empty(), 0, 0); return hashAlgorithm.Hash; } private void ZeroRangesIfApplicable(byte[] buffer, OffsetRange currentRange) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) foreach (OffsetRange zeroRange in _zeroRanges) { if (((OffsetRange)(ref currentRange)).Intersects(zeroRange)) { OffsetRange val = ((OffsetRange)(ref currentRange)).Intersect(zeroRange); for (ulong num = ((OffsetRange)(ref val)).Start; num < ((OffsetRange)(ref val)).End; num++) { buffer[num] = 0; } } } } } public abstract class StrongNameKeyStructure : SegmentBase { public abstract StrongNameKeyStructureType Type { get; } public abstract byte Version { get; } public abstract SignatureAlgorithm SignatureAlgorithm { get; } protected static void ReadBlobHeader(ref BinaryStreamReader reader, StrongNameKeyStructureType expectedType, byte expectedVersion, SignatureAlgorithm expectedAlgorithm) { if ((uint)((BinaryStreamReader)(ref reader)).ReadByte() != (uint)expectedType) { throw new FormatException("Input stream does not contain the expected structure type."); } if (((BinaryStreamReader)(ref reader)).ReadByte() != expectedVersion) { throw new NotSupportedException("Invalid or unsupported public/private key pair structure version number."); } ((BinaryStreamReader)(ref reader)).ReadUInt16(); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != (uint)expectedAlgorithm) { throw new NotSupportedException("Invalid or unsupported public key algorithm."); } } public override uint GetPhysicalSize() { return 8u; } public override void Write(BinaryStreamWriter writer) { writer.WriteByte((byte)Type); writer.WriteByte(Version); writer.WriteUInt16((ushort)0); writer.WriteUInt32((uint)SignatureAlgorithm); } } public enum StrongNameKeyStructureType : byte { SimpleBlob = 1, PublicKeyBlob = 6, PrivateKeyBlob = 7, PlainTextKeyBlob = 8, OpaqueKeyBlob = 9, PublicKeyBlobEx = 10, SymmetricWrapKeyBlob = 11, KeyStateBlob = 12 } public class StrongNamePrivateKey : StrongNamePublicKey { public override StrongNameKeyStructureType Type => StrongNameKeyStructureType.PrivateKeyBlob; public override byte Version => 2; public override RsaPublicKeyMagic Magic => RsaPublicKeyMagic.Rsa2; public byte[] P { get; set; } public byte[] Q { get; set; } public byte[] DP { get; set; } public byte[] DQ { get; set; } public byte[] InverseQ { get; set; } public byte[] PrivateExponent { get; set; } public new static StrongNamePrivateKey FromFile(string path) { BinaryStreamReader reader = default(BinaryStreamReader); ((BinaryStreamReader)(ref reader))..ctor(File.ReadAllBytes(path)); return FromReader(ref reader); } public new static StrongNamePrivateKey FromReader(ref BinaryStreamReader reader) { StrongNameKeyStructure.ReadBlobHeader(ref reader, StrongNameKeyStructureType.PrivateKeyBlob, 2, SignatureAlgorithm.RsaSign); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != 843141970) { throw new FormatException("Input stream does not contain a valid RSA private key header magic."); } StrongNamePrivateKey strongNamePrivateKey = new StrongNamePrivateKey(((BinaryStreamReader)(ref reader)).ReadUInt32()) { PublicExponent = ((BinaryStreamReader)(ref reader)).ReadUInt32() }; ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.Modulus, 0, strongNamePrivateKey.Modulus.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.P, 0, strongNamePrivateKey.P.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.Q, 0, strongNamePrivateKey.Q.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.DP, 0, strongNamePrivateKey.DP.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.DQ, 0, strongNamePrivateKey.DQ.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.InverseQ, 0, strongNamePrivateKey.InverseQ.Length); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePrivateKey.PrivateExponent, 0, strongNamePrivateKey.PrivateExponent.Length); Array.Reverse(strongNamePrivateKey.Modulus); Array.Reverse(strongNamePrivateKey.P); Array.Reverse(strongNamePrivateKey.Q); Array.Reverse(strongNamePrivateKey.DP); Array.Reverse(strongNamePrivateKey.DQ); Array.Reverse(strongNamePrivateKey.InverseQ); Array.Reverse(strongNamePrivateKey.PrivateExponent); return strongNamePrivateKey; } public StrongNamePrivateKey(uint bitLength) : base(new byte[bitLength / 8], 65537u) { uint num = bitLength / 8; uint num2 = bitLength / 16; P = new byte[num2]; Q = new byte[num2]; DP = new byte[num2]; DQ = new byte[num2]; InverseQ = new byte[num2]; PrivateExponent = new byte[num]; } public StrongNamePrivateKey(in RSAParameters parameters) : base(parameters.Modulus ?? throw new ArgumentException("The provided RSA parameters do not define a modulus."), ByteSwap(parameters)) { base.Modulus = parameters.Modulus; P = parameters.P ?? throw new ArgumentException("The provided RSA parameters do not define prime P."); Q = parameters.Q ?? throw new ArgumentException("The provided RSA parameters do not define prime Q."); DP = parameters.DP ?? throw new ArgumentException("The provided RSA parameters do not define DP."); DQ = parameters.DQ ?? throw new ArgumentException("The provided RSA parameters do not define DQ."); InverseQ = parameters.InverseQ ?? throw new ArgumentException("The provided RSA parameters do not define InverseQ."); PrivateExponent = parameters.D ?? throw new ArgumentException("The provided RSA parameters do not define D."); } public override RSAParameters ToRsaParameters() { List list = new List(4) { (byte)(base.PublicExponent & 0xFFu), (byte)((base.PublicExponent >> 8) & 0xFFu), (byte)((base.PublicExponent >> 16) & 0xFFu), (byte)((base.PublicExponent >> 24) & 0xFFu) }; int num = list.Count - 1; while (num >= 0 && list[num] == 0) { list.RemoveAt(num); num--; } RSAParameters result = default(RSAParameters); result.Modulus = base.Modulus; result.Exponent = list.ToArray(); result.P = P; result.Q = Q; result.DP = DP; result.DQ = DQ; result.D = PrivateExponent; result.InverseQ = InverseQ; return result; } public override uint GetPhysicalSize() { uint num = (uint)(base.BitLength / 8); uint num2 = (uint)(base.BitLength / 16); return base.GetPhysicalSize() + num2 + num2 + num2 + num2 + num2 + num; } public override void Write(BinaryStreamWriter writer) { base.Write(writer); writer.WriteBytes(P); writer.WriteBytes(Q); writer.WriteBytes(DP); writer.WriteBytes(DQ); writer.WriteBytes(InverseQ); writer.WriteBytes(PrivateExponent); } private static uint ByteSwap(RSAParameters parameters) { if (parameters.Exponent == null) { throw new ArgumentException("The provided RSA parameters do not define an exponent."); } uint num = 0u; for (int i = 0; i < Math.Min(4, parameters.Exponent.Length); i++) { num |= (uint)(parameters.Exponent[i] << 8 * i); } return num; } } public class StrongNamePublicKey : StrongNameKeyStructure { public override StrongNameKeyStructureType Type => StrongNameKeyStructureType.PublicKeyBlob; public override byte Version => 2; public override SignatureAlgorithm SignatureAlgorithm => SignatureAlgorithm.RsaSign; public virtual RsaPublicKeyMagic Magic => RsaPublicKeyMagic.Rsa1; public int BitLength => Modulus.Length * 8; public uint PublicExponent { get; set; } public byte[] Modulus { get; set; } public static StrongNamePublicKey FromFile(string path) { BinaryStreamReader reader = default(BinaryStreamReader); ((BinaryStreamReader)(ref reader))..ctor(File.ReadAllBytes(path)); return FromReader(ref reader); } public static StrongNamePublicKey FromReader(ref BinaryStreamReader reader) { StrongNameKeyStructure.ReadBlobHeader(ref reader, StrongNameKeyStructureType.PublicKeyBlob, 2, SignatureAlgorithm.RsaSign); if (((BinaryStreamReader)(ref reader)).ReadUInt32() != 826364754) { throw new FormatException("Input stream does not contain a valid RSA public key header magic."); } StrongNamePublicKey strongNamePublicKey = new StrongNamePublicKey(new byte[((BinaryStreamReader)(ref reader)).ReadUInt32() / 8], ((BinaryStreamReader)(ref reader)).ReadUInt32()); ((BinaryStreamReader)(ref reader)).ReadBytes(strongNamePublicKey.Modulus, 0, strongNamePublicKey.Modulus.Length); return strongNamePublicKey; } private byte[] CopyReversed(byte[] data) { byte[] array = new byte[data.Length]; for (int i = 0; i < data.Length; i++) { array[array.Length - i - 1] = data[i]; } return array; } public StrongNamePublicKey(byte[] modulus, uint publicExponent) { Modulus = modulus ?? throw new ArgumentNullException("modulus"); PublicExponent = publicExponent; } public StrongNamePublicKey(in RSAParameters parameters) { if (parameters.Modulus == null) { throw new ArgumentException("RSA parameters does not define a modulus."); } if (parameters.Exponent == null) { throw new ArgumentException("RSA parameters does not define an exponent."); } Modulus = CopyReversed(parameters.Modulus); uint num = 0u; for (int i = 0; i < Math.Min(4, parameters.Exponent.Length); i++) { num |= (uint)(parameters.Exponent[i] << 8 * i); } PublicExponent = num; } public byte[] CreatePublicKeyBlob(AssemblyHashAlgorithm hashAlgorithm) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) using MemoryStream memoryStream = new MemoryStream(); BinaryStreamWriter val = new BinaryStreamWriter((Stream)memoryStream); val.WriteUInt32((uint)SignatureAlgorithm); val.WriteUInt32((uint)hashAlgorithm); val.WriteUInt32((uint)(20 + Modulus.Length)); val.WriteByte((byte)6); val.WriteByte((byte)2); val.WriteUInt16((ushort)0); val.WriteUInt32((uint)SignatureAlgorithm); val.WriteUInt32(826364754u); val.WriteUInt32((uint)BitLength); val.WriteUInt32(PublicExponent); val.WriteBytes(CopyReversed(Modulus)); return memoryStream.ToArray(); } public virtual RSAParameters ToRsaParameters() { RSAParameters result = default(RSAParameters); result.Modulus = Modulus; result.Exponent = BitConverter.GetBytes(PublicExponent); return result; } public override uint GetPhysicalSize() { return base.GetPhysicalSize() + 4 + 4 + 4 + (uint)Modulus.Length / 8u; } public override void Write(BinaryStreamWriter writer) { base.Write(writer); writer.WriteUInt32((uint)Magic); writer.WriteUInt32((uint)BitLength); writer.WriteUInt32(PublicExponent); writer.WriteBytes(Modulus); } } public class StrongNameSigner { public StrongNamePrivateKey PrivateKey { get; } public StrongNameSigner(StrongNamePrivateKey privateKey) { PrivateKey = privateKey ?? throw new ArgumentNullException("privateKey"); } public void SignImage(Stream imageStream, AssemblyHashAlgorithm hashAlgorithm) { imageStream.Position = 0L; using MemoryStream memoryStream = new MemoryStream(); imageStream.CopyTo(memoryStream); memoryStream.Position = 0L; PEFile val = PEFile.FromBytes(memoryStream.ToArray()); PEImage pEImage = PEImage.FromFile(val); if (pEImage.DotNetDirectory == null) { throw new BadImageFormatException("Input image is not a .NET assembly."); } IReadableSegment strongName = pEImage.DotNetDirectory.StrongName; if (strongName == null) { throw new ArgumentException("Cannot sign an image without a strong name directory."); } if (PrivateKey.Modulus.Length != ((IWritable)strongName).GetPhysicalSize()) { throw new ArgumentException("The strong name signature directory size does not match the size of the strong signature."); } byte[] hashToSign = GetHashToSign(memoryStream, val, pEImage, hashAlgorithm); byte[] array = ComputeSignature(hashAlgorithm, hashToSign); imageStream.Position = (long)((IOffsetProvider)strongName).Offset; imageStream.Write(array, 0, array.Length); } private byte[] GetHashToSign(Stream imageStream, PEFile file, PEImage image, AssemblyHashAlgorithm hashAlgorithm) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Invalid comparison between Unknown and I4 //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) StrongNameDataHashBuilder strongNameDataHashBuilder = new StrongNameDataHashBuilder(imageStream, hashAlgorithm); strongNameDataHashBuilder.IncludeRange(new OffsetRange(0uL, (ulong)(uint)(((SegmentBase)file.DosHeader).GetPhysicalSize() + 4 + ((SegmentBase)file.FileHeader).GetPhysicalSize() + ((SegmentBase)file.OptionalHeader).GetPhysicalSize() + (long)file.Sections.Count * 40L))); foreach (PESection section in file.Sections) { strongNameDataHashBuilder.IncludeRange(new OffsetRange(section.Offset, section.Offset + section.GetPhysicalSize())); } ulong num = ((SegmentBase)file.OptionalHeader).Offset + 64; strongNameDataHashBuilder.ZeroRange(new OffsetRange(num, num + 4)); uint num2 = (((int)file.OptionalHeader.Magic == 267) ? 96u : 112u); ulong num3 = ((SegmentBase)file.OptionalHeader).Offset + num2 + 32; strongNameDataHashBuilder.ZeroRange(new OffsetRange(num3, num3 + 8)); DataDirectory dataDirectory = file.OptionalHeader.GetDataDirectory((DataDirectoryIndex)4); if (((DataDirectory)(ref dataDirectory)).IsPresentInPE) { ulong num4 = file.RvaToFileOffset(((DataDirectory)(ref dataDirectory)).VirtualAddress); strongNameDataHashBuilder.ExcludeRange(new OffsetRange(num4, num4 + ((DataDirectory)(ref dataDirectory)).Size)); } IReadableSegment val = image.DotNetDirectory?.StrongName; if (val == null) { throw new ArgumentException("PE image does not contain a strong name directory."); } strongNameDataHashBuilder.ExcludeRange(new OffsetRange(((IOffsetProvider)val).Offset, ((IOffsetProvider)val).Offset + ((IWritable)val).GetPhysicalSize())); return strongNameDataHashBuilder.ComputeHash(); } private byte[] ComputeSignature(AssemblyHashAlgorithm hashAlgorithm, byte[] hash) { using RSA rSA = RSA.Create(); RSAParameters parameters = PrivateKey.ToRsaParameters(); rSA.ImportParameters(parameters); RSAPKCS1SignatureFormatter rSAPKCS1SignatureFormatter = new RSAPKCS1SignatureFormatter(rSA); rSAPKCS1SignatureFormatter.SetHashAlgorithm(hashAlgorithm.ToString().ToUpperInvariant()); byte[] array = rSAPKCS1SignatureFormatter.CreateSignature(hash); Array.Reverse(array); return array; } } } namespace AsmResolver.PE.DotNet.Resources { public abstract class DotNetResourcesDirectory : SegmentBase { public abstract byte[]? GetManifestResourceData(uint offset); public abstract bool TryCreateManifestResourceReader(uint offset, out BinaryStreamReader reader); } public class SerializedDotNetResourcesDirectory : DotNetResourcesDirectory { private readonly BinaryStreamReader _reader; public SerializedDotNetResourcesDirectory(in BinaryStreamReader reader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = reader; if (!((BinaryStreamReader)(ref val)).IsValid) { throw new ArgumentNullException("reader"); } _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public SerializedDotNetResourcesDirectory(IReadableSegment contents) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = Extensions.CreateReader(contents); this..ctor(in reader); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(BinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override byte[]? GetManifestResourceData(uint offset) { if (!TryCreateManifestResourceReader(offset, out var reader)) { return null; } byte[] array = new byte[((BinaryStreamReader)(ref reader)).Length]; ((BinaryStreamReader)(ref reader)).ReadBytes(array, 0, array.Length); return array; } public override bool TryCreateManifestResourceReader(uint offset, out BinaryStreamReader reader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (offset >= ((BinaryStreamReader)(ref _reader)).Length - 4) { reader = default(BinaryStreamReader); return false; } reader = ((BinaryStreamReader)(ref _reader)).ForkRelative(offset); uint num = ((BinaryStreamReader)(ref reader)).ReadUInt32(); if (!((BinaryStreamReader)(ref reader)).CanRead(num)) { reader = default(BinaryStreamReader); return false; } reader = ((BinaryStreamReader)(ref reader)).ForkAbsolute(((BinaryStreamReader)(ref reader)).Offset, num); return true; } } } namespace AsmResolver.PE.DotNet.ReadyToRun { [DebuggerDisplay("CompilerIdentifier ({Identifier})")] public class CompilerIdentifierSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { public ReadyToRunSectionType Type => ReadyToRunSectionType.CompilerIdentifier; public bool CanRead => true; public string Identifier { get; set; } public CompilerIdentifierSection(string identifier) { Identifier = identifier; } public BinaryStreamReader CreateReader() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) return new BinaryStreamReader(Encoding.ASCII.GetBytes(Identifier + "\0")); } public override uint GetPhysicalSize() { return (uint)(Encoding.ASCII.GetByteCount(Identifier) + 1); } public override void Write(BinaryStreamWriter writer) { writer.WriteAsciiString(Identifier); writer.WriteByte((byte)0); } } [DebuggerDisplay("CustomReadyToRunSection ({Type})")] public sealed class CustomReadyToRunSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { public ReadyToRunSectionType Type { get; } [MemberNotNullWhen(true, "Contents")] public bool CanRead { [MemberNotNullWhen(true, "Contents")] get { return Contents is IReadableSegment; } } public ISegment Contents { get; } public CustomReadyToRunSection(ReadyToRunSectionType type, ISegment contents) { Type = type; Contents = contents; } public override uint GetPhysicalSize() { return ((IWritable)Contents).GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { ((IWritable)Contents).Write(writer); } public BinaryStreamReader CreateReader() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!CanRead) { throw new InvalidOperationException("Contents of the ReadyToRun section is not readable."); } return Extensions.CreateReader((IReadableSegment)Contents); } } public class DebugInfo : SegmentBase { private IList? _bounds; private IList? _variables; private byte[]? _serialized; private bool _is32Bit; public IList Bounds { get { if (_bounds == null) { Interlocked.CompareExchange(ref _bounds, GetBounds(), null); } return _bounds; } } public IList Variables { get { if (_variables == null) { Interlocked.CompareExchange(ref _variables, GetVariables(), null); } return _variables; } } protected virtual IList GetBounds() { return new List(); } protected virtual IList GetVariables() { return new List(); } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); _serialized = Serialize(); _is32Bit = ((RelocationParameters)(ref parameters)).Is32Bit; } public override uint GetPhysicalSize() { if (_serialized == null) { _serialized = Serialize(); } return (uint)_serialized.Length; } public override void Write(BinaryStreamWriter writer) { if (_serialized == null) { _serialized = Serialize(); } writer.WriteBytes(_serialized); } private byte[] Serialize() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown byte[] array = SerializeBounds(); byte[] array2 = SerializeVariables(); using MemoryStream memoryStream = new MemoryStream(); BinaryStreamWriter val = new BinaryStreamWriter((Stream)memoryStream); NativeFormat.EncodeUnsigned(val, 0u); NibbleWriter nibbleWriter = new NibbleWriter(val); nibbleWriter.Write3BitEncodedUInt((uint)array.Length); nibbleWriter.Write3BitEncodedUInt((uint)array2.Length); nibbleWriter.Flush(); val.WriteBytes(array); val.WriteBytes(array2); return memoryStream.ToArray(); } private byte[] SerializeBounds() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (Bounds.Count == 0) { return ArrayShim.Empty(); } using MemoryStream memoryStream = new MemoryStream(); NibbleWriter nibbleWriter = new NibbleWriter(new BinaryStreamWriter((Stream)memoryStream)); nibbleWriter.Write3BitEncodedUInt((uint)Bounds.Count); uint num = 0u; for (int i = 0; i < Bounds.Count; i++) { DebugInfoBounds debugInfoBounds = Bounds[i]; nibbleWriter.Write3BitEncodedUInt(debugInfoBounds.NativeOffset - num); nibbleWriter.Write3BitEncodedUInt(debugInfoBounds.ILOffset - 4294967293u); nibbleWriter.Write3BitEncodedUInt((uint)debugInfoBounds.Attributes); num = debugInfoBounds.NativeOffset; } nibbleWriter.Flush(); return memoryStream.ToArray(); } private byte[] SerializeVariables() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (Variables.Count == 0) { return ArrayShim.Empty(); } using MemoryStream memoryStream = new MemoryStream(); NibbleWriter writer = new NibbleWriter(new BinaryStreamWriter((Stream)memoryStream)); writer.Write3BitEncodedUInt((uint)Variables.Count); for (int i = 0; i < Variables.Count; i++) { Variables[i].Write((MachineType)(_is32Bit ? 332 : 34404), ref writer); } writer.Flush(); return memoryStream.ToArray(); } } [Flags] public enum DebugInfoAttributes { SourceTypeInvalid = 0, SequencePoint = 1, StackEmpty = 2, CallSite = 4, NativeEndOffsetUnknown = 8, CallInstruction = 0x10 } [DebuggerDisplay("NativeOffset = {NativeOffset}, ILOffset = {ILOffset} ({Attributes})")] public readonly struct DebugInfoBounds : IEquatable { public const uint NoMappingOffset = uint.MaxValue; public const uint PrologOffset = 4294967294u; public const uint EpilogOffset = 4294967293u; public uint NativeOffset { get; } public uint ILOffset { get; } public DebugInfoAttributes Attributes { get; } public DebugInfoBounds(uint nativeOffset, uint ilOffset, DebugInfoAttributes attributes) { NativeOffset = nativeOffset; ILOffset = ilOffset; Attributes = attributes; } public bool Equals(DebugInfoBounds other) { if (NativeOffset == other.NativeOffset && ILOffset == other.ILOffset) { return Attributes == other.Attributes; } return false; } public override bool Equals(object? obj) { if (obj is DebugInfoBounds other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)(((NativeOffset * 397) ^ ILOffset) * 397) ^ (int)Attributes; } public override string ToString() { return $"{"NativeOffset"}: {NativeOffset:X4}, {"ILOffset"}: IL_{ILOffset:X4} ({Attributes})"; } } public class DebugInfoSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { private NativeArray? _entries; public ReadyToRunSectionType Type => ReadyToRunSectionType.DebugInfo; public virtual bool CanRead => false; public NativeArray Entries { get { if (_entries == null) { Interlocked.CompareExchange(ref _entries, GetEntries(), null); } return _entries; } } protected virtual NativeArray GetEntries() { return new NativeArray(); } public virtual BinaryStreamReader CreateReader() { throw new InvalidOperationException(); } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); Entries.UpdateOffsets(in parameters); } public override uint GetPhysicalSize() { return Entries.GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { Entries.Write(writer); } } public readonly struct DebugInfoVariable : IEquatable { public const uint VarArgsHandle = uint.MaxValue; public const uint ReturnBuffer = 4294967294u; public const uint TypeContext = 4294967293u; internal const uint Unknown = 4294967292u; public uint StartOffset { get; } public uint EndOffset { get; } public uint Index { get; } public DebugInfoVariableLocation Location { get; } public DebugInfoVariable(uint startOffset, uint endOffset, uint index, DebugInfoVariableLocation location) { StartOffset = startOffset; EndOffset = endOffset; Index = index; Location = location; } internal static DebugInfoVariable FromReader(PEReaderContext context, ref NibbleReader reader) { uint num = reader.Read3BitEncodedUInt(); uint endOffset = num + reader.Read3BitEncodedUInt(); uint index = reader.Read3BitEncodedUInt() + 4294967292u; DebugInfoVariableLocation location = DebugInfoVariableLocation.FromReader(context, ref reader); return new DebugInfoVariable(num, endOffset, index, location); } internal void Write(MachineType machineType, ref NibbleWriter writer) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) writer.Write3BitEncodedUInt(StartOffset); writer.Write3BitEncodedUInt(EndOffset - StartOffset); writer.Write3BitEncodedUInt(Index - 4294967292u); Location.Write(machineType, ref writer); } public bool Equals(DebugInfoVariable other) { if (StartOffset == other.StartOffset && EndOffset == other.EndOffset && Index == other.Index) { return Location.Equals(other.Location); } return false; } public override bool Equals(object? obj) { if (obj is DebugInfoVariable other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)(((((StartOffset * 397) ^ EndOffset) * 397) ^ Index) * 397) ^ Location.GetHashCode(); } public override string ToString() { return $"[{StartOffset:X4}, {EndOffset:X4}), {"Index"}: {Index}, {"Location"}: {Location}"; } } public readonly struct DebugInfoVariableLocation : IEquatable { public DebugInfoVariableLocationType Type { get; } public uint Data1 { get; } public uint Data2 { get; } public uint Data3 { get; } public DebugInfoVariableLocation(DebugInfoVariableLocationType type, uint data1) { Type = type; Data1 = data1; Data2 = 0u; Data3 = 0u; } public DebugInfoVariableLocation(DebugInfoVariableLocationType type, uint data1, uint data2) { Type = type; Data1 = data1; Data2 = data2; Data3 = 0u; } public DebugInfoVariableLocation(DebugInfoVariableLocationType type, uint data1, uint data2, uint data3) { Type = type; Data1 = data1; Data2 = data2; Data3 = data3; } internal static DebugInfoVariableLocation FromReader(PEReaderContext context, ref NibbleReader reader) { PEReaderContext context2 = context; DebugInfoVariableLocationType debugInfoVariableLocationType = (DebugInfoVariableLocationType)reader.Read3BitEncodedUInt(); uint num = 0u; uint data = 0u; uint data2 = 0u; switch (debugInfoVariableLocationType) { case DebugInfoVariableLocationType.Register: case DebugInfoVariableLocationType.RegisterByReference: case DebugInfoVariableLocationType.RegisterFP: case DebugInfoVariableLocationType.FPStack: case DebugInfoVariableLocationType.FixedVA: num = reader.Read3BitEncodedUInt(); break; case DebugInfoVariableLocationType.Stack: case DebugInfoVariableLocationType.StackByReference: num = reader.Read3BitEncodedUInt(); data = ToStackOffset(reader.Read3BitEncodedUInt()); break; case DebugInfoVariableLocationType.RegisterRegister: num = reader.Read3BitEncodedUInt(); data = reader.Read3BitEncodedUInt(); break; case DebugInfoVariableLocationType.RegisterStack: num = reader.Read3BitEncodedUInt(); data = reader.Read3BitEncodedUInt(); data2 = ToStackOffset(reader.Read3BitEncodedUInt()); break; case DebugInfoVariableLocationType.StackRegister: num = ToStackOffset(reader.Read3BitEncodedUInt()); data = reader.Read3BitEncodedUInt(); data2 = reader.Read3BitEncodedUInt(); break; case DebugInfoVariableLocationType.Stack2: num = reader.Read3BitEncodedUInt(); data = ToStackOffset(reader.Read3BitEncodedUInt()); break; default: throw new ArgumentOutOfRangeException(); } return new DebugInfoVariableLocation(debugInfoVariableLocationType, num, data, data2); uint ToStackOffset(uint value) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((int)context2.File.FileHeader.Machine == 332) { return value * 4; } return value; } } internal void Write(MachineType machineType, ref NibbleWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) writer.Write3BitEncodedUInt((uint)Type); switch (Type) { case DebugInfoVariableLocationType.Register: case DebugInfoVariableLocationType.RegisterByReference: case DebugInfoVariableLocationType.RegisterFP: case DebugInfoVariableLocationType.FPStack: case DebugInfoVariableLocationType.FixedVA: writer.Write3BitEncodedUInt(Data1); break; case DebugInfoVariableLocationType.Stack: case DebugInfoVariableLocationType.StackByReference: writer.Write3BitEncodedUInt(Data1); writer.Write3BitEncodedUInt(EncodeStackOffset(Data2)); break; case DebugInfoVariableLocationType.RegisterRegister: writer.Write3BitEncodedUInt(Data1); writer.Write3BitEncodedUInt(Data2); break; case DebugInfoVariableLocationType.RegisterStack: writer.Write3BitEncodedUInt(Data1); writer.Write3BitEncodedUInt(Data2); writer.Write3BitEncodedUInt(EncodeStackOffset(Data3)); break; case DebugInfoVariableLocationType.StackRegister: writer.Write3BitEncodedUInt(EncodeStackOffset(Data1)); writer.Write3BitEncodedUInt(Data2); writer.Write3BitEncodedUInt(Data3); break; case DebugInfoVariableLocationType.Stack2: writer.Write3BitEncodedUInt(Data1); writer.Write3BitEncodedUInt(EncodeStackOffset(Data2)); break; default: throw new ArgumentOutOfRangeException(); } uint EncodeStackOffset(uint value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)machineType == 332) { return value / 4; } return value; } } public bool Equals(DebugInfoVariableLocation other) { if (Type == other.Type && Data1 == other.Data1 && Data2 == other.Data2) { return Data3 == other.Data3; } return false; } public override bool Equals(object? obj) { if (obj is DebugInfoVariableLocation other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((uint)((int)Type * 397) ^ Data1) * 397) ^ Data2) * 397) ^ Data3); } public override string ToString() { switch (Type) { case DebugInfoVariableLocationType.Register: case DebugInfoVariableLocationType.RegisterByReference: case DebugInfoVariableLocationType.RegisterFP: case DebugInfoVariableLocationType.FPStack: case DebugInfoVariableLocationType.FixedVA: return $"{Type} {Data1:X}"; case DebugInfoVariableLocationType.Stack: case DebugInfoVariableLocationType.StackByReference: case DebugInfoVariableLocationType.RegisterRegister: case DebugInfoVariableLocationType.Stack2: return $"{Type} {Data1:X}, {Data2:X}"; case DebugInfoVariableLocationType.RegisterStack: case DebugInfoVariableLocationType.StackRegister: return $"{Type} {Data1:X}, {Data2:X}, {Data3:X}"; default: throw new ArgumentOutOfRangeException(); } } } public enum DebugInfoVariableLocationType { Register, RegisterByReference, RegisterFP, Stack, StackByReference, RegisterRegister, RegisterStack, StackRegister, Stack2, FPStack, FixedVA } public class DefaultReadyToRunSectionReader : IReadyToRunSectionReader { public static DefaultReadyToRunSectionReader Instance { get; } = new DefaultReadyToRunSectionReader(); public IReadyToRunSection ReadSection(PEReaderContext context, ReadyToRunSectionType type, ref BinaryStreamReader reader) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) switch (type) { case ReadyToRunSectionType.CompilerIdentifier: return new CompilerIdentifierSection(((BinaryStreamReader)(ref reader)).ReadAsciiString()); case ReadyToRunSectionType.ImportSections: return new SerializedImportSectionsSection(context, ref reader); case ReadyToRunSectionType.RuntimeFunctions: if ((int)context.File.FileHeader.Machine == 34404) { return new SerializedX64RuntimeFunctionsSection(context, ref reader); } break; case ReadyToRunSectionType.MethodDefEntryPoints: return new SerializedMethodEntryPointsSection(ref reader); case ReadyToRunSectionType.DebugInfo: return new SerializedDebugInfoSection(context, reader); } return new CustomReadyToRunSection(type, (ISegment)(object)((BinaryStreamReader)(ref reader)).ReadSegment(((BinaryStreamReader)(ref reader)).Length)); } } [DebuggerDisplay("{Type}, Slots = {Slots.Count} ({Attributes})")] public class ImportSection : IWritable { internal const uint ImportSectionSize = 19u; private ReferenceTable? _slots; private ReferenceTable? _signatures; public ReferenceTable Slots { get { if (_slots == null) { Interlocked.CompareExchange(ref _slots, GetSlots(), null); } return _slots; } } public ImportSectionAttributes Attributes { get; set; } public ImportSectionType Type { get; set; } public byte EntrySize { get; set; } public ReferenceTable Signatures { get { if (_signatures == null) { Interlocked.CompareExchange(ref _signatures, GetSignatures(), null); } return _signatures; } } public ISegmentReference AuxiliaryData { get; set; } = SegmentReference.Null; protected virtual ReferenceTable GetSlots() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new ReferenceTable((ReferenceTableAttributes)2); } protected virtual ReferenceTable GetSignatures() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown return new ReferenceTable((ReferenceTableAttributes)5); } public uint GetPhysicalSize() { return 19u; } public void Write(BinaryStreamWriter writer) { writer.WriteUInt32(Slots.Rva); writer.WriteUInt32(Slots.GetPhysicalSize()); writer.WriteUInt16((ushort)Attributes); writer.WriteByte((byte)Type); writer.WriteByte(EntrySize); writer.WriteUInt32((((Collection)(object)Signatures).Count != 0) ? Signatures.Rva : 0u); writer.WriteUInt32(((IOffsetProvider)AuxiliaryData).Rva); } } [Flags] public enum ImportSectionAttributes : ushort { None = 0, Eager = 1, PCode = 4 } public class ImportSectionsSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { private IList? _sections; public ReadyToRunSectionType Type => ReadyToRunSectionType.ImportSections; public IList Sections { get { if (_sections == null) { Interlocked.CompareExchange(ref _sections, GetSections(), null); } return _sections; } } public virtual bool CanRead => false; protected virtual IList GetSections() { return new List(); } public virtual BinaryStreamReader CreateReader() { throw new InvalidOperationException(); } public override uint GetPhysicalSize() { return (uint)(Sections.Count * 19); } public override void Write(BinaryStreamWriter writer) { for (int i = 0; i < Sections.Count; i++) { Sections[i].Write(writer); } } } public enum ImportSectionType : byte { Unknown = 0, StubDispatch = 2, StringHandle = 3, ILBodyFixups = 7 } public interface IReadyToRunSection : ISegment, IOffsetProvider, IWritable { ReadyToRunSectionType Type { get; } bool CanRead { get; } BinaryStreamReader CreateReader(); } public interface IReadyToRunSectionReader { IReadyToRunSection ReadSection(PEReaderContext context, ReadyToRunSectionType type, ref BinaryStreamReader reader); } public class MethodEntryPoint : SegmentBase { private byte[]? _serialized; public uint RuntimeFunctionIndex { get; set; } public IList Fixups { get; } = new List(); public MethodEntryPoint(uint functionIndex) { RuntimeFunctionIndex = functionIndex; } public static MethodEntryPoint FromReader(ref BinaryStreamReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; uint num = NativeFormat.DecodeUnsigned(ref reader); MethodEntryPoint methodEntryPoint; if ((num & 1) == 0) { methodEntryPoint = new MethodEntryPoint(num >> 1); } else { methodEntryPoint = new MethodEntryPoint(num >> 2); ReadFixups(methodEntryPoint, reader); } ((SegmentBase)methodEntryPoint).Offset = offset; ((SegmentBase)methodEntryPoint).Rva = rva; return methodEntryPoint; } private static void ReadFixups(MethodEntryPoint entryPoint, BinaryStreamReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) NibbleReader nibbleReader = new NibbleReader(reader); uint num = nibbleReader.Read3BitEncodedUInt(); while (true) { uint num2 = nibbleReader.Read3BitEncodedUInt(); while (true) { entryPoint.Fixups.Add(new MethodFixup(num, num2)); uint num3 = nibbleReader.Read3BitEncodedUInt(); if (num3 == 0) { break; } num2 += num3; } uint num4 = nibbleReader.Read3BitEncodedUInt(); if (num4 != 0) { num += num4; continue; } break; } } private uint GetHeader() { if (Fixups.Count <= 0) { return RuntimeFunctionIndex << 1; } return (RuntimeFunctionIndex << 2) | 1u; } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); _serialized = Serialize(); } public override uint GetPhysicalSize() { if (_serialized == null) { _serialized = Serialize(); } return (uint)_serialized.Length; } public override void Write(BinaryStreamWriter writer) { if (_serialized == null) { _serialized = Serialize(); } writer.WriteBytes(_serialized); } private byte[] Serialize() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown using MemoryStream memoryStream = new MemoryStream(); BinaryStreamWriter writer = new BinaryStreamWriter((Stream)memoryStream); NativeFormat.EncodeUnsigned(writer, GetHeader()); if (Fixups.Count == 0) { return memoryStream.ToArray(); } NibbleWriter nibbleWriter = new NibbleWriter(writer); uint num = 0u; uint num2 = 0u; for (int i = 0; i < Fixups.Count; i++) { MethodFixup methodFixup = Fixups[i]; uint num3 = methodFixup.ImportIndex - num; if (num3 != 0 || i == 0) { if (i > 0) { nibbleWriter.Write3BitEncodedUInt(0u); } nibbleWriter.Write3BitEncodedUInt(num3); num2 = 0u; } uint value = methodFixup.SlotIndex - num2; nibbleWriter.Write3BitEncodedUInt(value); num = methodFixup.ImportIndex; num2 = methodFixup.SlotIndex; } nibbleWriter.Write3BitEncodedUInt(0u); nibbleWriter.Write3BitEncodedUInt(0u); nibbleWriter.Flush(); return memoryStream.ToArray(); } } public class MethodEntryPointsSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { private NativeArray? _entryPoints; public ReadyToRunSectionType Type => ReadyToRunSectionType.MethodDefEntryPoints; public virtual bool CanRead => false; public NativeArray EntryPoints { get { if (_entryPoints == null) { Interlocked.CompareExchange(ref _entryPoints, GetEntryPoints(), null); } return _entryPoints; } } protected virtual NativeArray GetEntryPoints() { return new NativeArray(); } public virtual BinaryStreamReader CreateReader() { throw new InvalidOperationException(); } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); EntryPoints.UpdateOffsets(in parameters); } public override uint GetPhysicalSize() { return EntryPoints.GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { EntryPoints.Write(writer); } } [DebuggerDisplay("ImportIndex = {ImportIndex}, SlotIndex = {SlotIndex}")] public readonly struct MethodFixup : IEquatable { public uint ImportIndex { get; } public uint SlotIndex { get; } public MethodFixup(uint importIndex, uint slotIndex) { ImportIndex = importIndex; SlotIndex = slotIndex; } public bool Equals(MethodFixup other) { if (ImportIndex == other.ImportIndex) { return SlotIndex == other.SlotIndex; } return false; } public override bool Equals(object? obj) { if (obj is MethodFixup other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((ImportIndex * 397) ^ SlotIndex); } public override string ToString() { return $"ImportIndex = {ImportIndex}, SlotIndex = {SlotIndex}"; } } public class NativeArray : Collection, ISegment, IOffsetProvider, IWritable where T : IWritable { private sealed class Node : SegmentBase { public uint Index; public T? Value; public Node? Left; public Node? Right; public readonly int Depth; private uint _size; public uint Header { get { uint num = 0u; if (Left != null) { num |= 1u; } if (Right != null) { num |= 2u; } uint num2 = (uint)((Right != null) ? (((SegmentBase)Right).Offset - ((SegmentBase)this).Offset) : ((Left == null) ? Index : 0u)); return num | (num2 << 2); } } [MemberNotNullWhen(true, "Value")] public bool IsLeaf { [MemberNotNullWhen(true, "Value")] get { if (Left == null) { return Right == null; } return false; } } public Node(int depth, uint index = 0u, T? value = default(T?)) { Depth = depth; Index = index; Value = value; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = parameters; if (Depth > 0) { ((RelocationParameters)(ref val)).Advance(5u); } if (IsLeaf) { object obj = Value; ISegment val2 = (ISegment)((obj is ISegment) ? obj : null); if (val2 != null) { val2.UpdateOffsets(ref val); } ((RelocationParameters)(ref val)).Advance(((IWritable)Value).GetPhysicalSize()); } else { if (Left != null) { ((SegmentBase)Left).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(((SegmentBase)Left).GetPhysicalSize()); } if (Right != null) { ((SegmentBase)Right).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(((SegmentBase)Right).GetPhysicalSize()); } } _size = (uint)(((RelocationParameters)(ref val)).Offset - ((RelocationParameters)(ref parameters)).Offset); } public override uint GetPhysicalSize() { return _size; } public override void Write(BinaryStreamWriter writer) { if (Depth > 0) { writer.WriteByte((byte)15); writer.WriteUInt32(Header); } if (IsLeaf) { ((IWritable)Value).Write(writer); return; } Node? left = Left; if (left != null) { ((SegmentBase)left).Write(writer); } Node? right = Right; if (right != null) { ((SegmentBase)right).Write(writer); } } } private readonly List _roots = new List(); private uint _entryIndexSize = 2u; private uint _totalSize; public bool CanUpdateOffsets => true; public ulong Offset { get; private set; } public uint Rva { get; private set; } private uint Header => (uint)(base.Items.Count << 2) | _entryIndexSize; public static NativeArray FromReader(BinaryStreamReader reader, Func readElement) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) NativeArray nativeArray = new NativeArray(); uint num = NativeFormat.DecodeUnsigned(ref reader); int num2 = (int)(num >> 2); nativeArray._entryIndexSize = (byte)(num & 3u); reader = ((BinaryStreamReader)(ref reader)).ForkAbsolute(((BinaryStreamReader)(ref reader)).Offset); for (int i = 0; i < num2; i++) { nativeArray.Add(NativeFormat.TryGetArrayElement(reader, nativeArray._entryIndexSize, i, out var contents) ? readElement(contents) : default(T)); } return nativeArray; } private void RebuildTree() { _roots.Clear(); for (int i = 0; i < base.Items.Count; i++) { T val = base.Items[i]; if (val != null) { InsertNode(i, val); } } _entryIndexSize = 2u; } private void UpdateTreeOffsets(in RelocationParameters parameters) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; RelocationParameters val = parameters; ((RelocationParameters)(ref val)).Advance(NativeFormat.GetEncodedUnsignedSize(Header)); ((RelocationParameters)(ref val)).Advance((uint)(_roots.Count * (1 << (int)_entryIndexSize))); foreach (Node root in _roots) { ((SegmentBase)root).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(((SegmentBase)root).GetPhysicalSize()); } _totalSize = (uint)(((RelocationParameters)(ref val)).Offset - ((RelocationParameters)(ref parameters)).Offset); } private void InsertNode(int index, T? value) { int num = index / 16; while (num >= _roots.Count) { _roots.Add(new Node(8)); } Node node = _roots[num]; for (uint num2 = 8u; num2 != 0; num2 >>= 1) { if ((index & num2) != 0L) { Node node2 = node; if (node2.Right == null) { node2.Right = new Node(node.Depth >> 1); } node = node.Right; } else { Node node2 = node; if (node2.Left == null) { node2.Left = new Node(node.Depth >> 1); } node = node.Left; } } node.Index = (uint)index; node.Value = value; } public void UpdateOffsets(in RelocationParameters parameters) { RebuildTree(); UpdateTreeOffsets(in parameters); } public uint GetPhysicalSize() { return _totalSize; } public uint GetVirtualSize() { return GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { uint header = Header; uint encodedUnsignedSize = NativeFormat.GetEncodedUnsignedSize(header); NativeFormat.EncodeUnsigned(writer, header); foreach (Node root in _roots) { WriteRootNodeHeader(writer, root, encodedUnsignedSize); } foreach (Node root2 in _roots) { ((SegmentBase)root2).Write(writer); } } private void WriteRootNodeHeader(BinaryStreamWriter writer, Node root, uint headerSize) { uint num = (uint)(((SegmentBase)root).Offset - headerSize - Offset); switch (_entryIndexSize) { case 0u: writer.WriteByte((byte)num); break; case 1u: writer.WriteUInt16((ushort)num); break; case 2u: writer.WriteUInt32(num); break; default: throw new ArgumentOutOfRangeException("_entryIndexSize"); } } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } internal static class NativeFormat { internal const int ArrayBlockSize = 16; public static uint GetEncodedUnsignedSize(uint value) { if (value < 4194303) { if (value >= 127) { if (value < 32767) { return 2u; } return 3u; } return 1u; } if (value < 536870911) { return 4u; } return 5u; } public static uint DecodeUnsigned(ref BinaryStreamReader reader) { uint num = 0u; uint num2 = ((BinaryStreamReader)(ref reader)).ReadByte(); if ((num2 & 1) == 0) { return num2 >> 1; } if ((num2 & 2) == 0) { return (num2 >> 2) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 6); } if ((num2 & 4) == 0) { return (num2 >> 3) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 5) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 13); } if ((num2 & 8) == 0) { return (num2 >> 4) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 4) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 12) | (uint)(((BinaryStreamReader)(ref reader)).ReadByte() << 20); } if ((num2 & 0x10) == 0) { return ((BinaryStreamReader)(ref reader)).ReadUInt32(); } throw new BadImageFormatException("Invalid encoding of unsigned integer."); } public static void EncodeUnsigned(BinaryStreamWriter writer, uint value) { switch (GetEncodedUnsignedSize(value)) { case 1u: writer.WriteByte((byte)((value & 0x7F) << 1)); break; case 2u: writer.WriteByte((byte)(((value & 0x3F) << 2) | 1u)); writer.WriteByte((byte)(value >> 6)); break; case 3u: writer.WriteByte((byte)(((value & 0x1F) << 3) | 3u)); writer.WriteByte((byte)((value >> 5) & 0xFFu)); writer.WriteByte((byte)((value >> 13) & 0xFFu)); break; case 4u: writer.WriteByte((byte)(((value & 0xF) << 4) | 3u)); writer.WriteByte((byte)((value >> 4) & 0xFFu)); writer.WriteByte((byte)((value >> 12) & 0xFFu)); writer.WriteByte((byte)((value >> 20) & 0xFFu)); break; case 5u: writer.WriteByte((byte)15); writer.WriteUInt32(value); break; default: throw new ArgumentOutOfRangeException("value"); } } public static bool TryGetArrayElement(BinaryStreamReader reader, uint entryIndexSize, int index, out BinaryStreamReader contents) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) switch (entryIndexSize) { case 0u: ((BinaryStreamReader)(ref reader)).RelativeOffset = (uint)index / 16u; ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader)).ReadByte(); break; case 1u: ((BinaryStreamReader)(ref reader)).RelativeOffset = 2 * ((uint)index / 16u); ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader)).ReadUInt16(); break; default: ((BinaryStreamReader)(ref reader)).RelativeOffset = 4 * ((uint)index / 16u); ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); break; } for (uint num = 8u; num != 0; num >>= 1) { BinaryStreamReader reader2 = ((BinaryStreamReader)(ref reader)).Fork(); uint num2 = DecodeUnsigned(ref reader2); if ((index & num) != 0L) { if ((num2 & 2u) != 0) { ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader)).RelativeOffset + (num2 >> 2); continue; } } else if ((num2 & (true ? 1u : 0u)) != 0) { ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader2)).RelativeOffset; continue; } if ((num2 & 3) == 0 && num2 >> 2 == (index & 0xF)) { ((BinaryStreamReader)(ref reader)).RelativeOffset = ((BinaryStreamReader)(ref reader2)).RelativeOffset; break; } contents = default(BinaryStreamReader); return false; } contents = reader; return true; } } internal struct NibbleReader { private BinaryStreamReader _reader; private byte? _buffer; public BinaryStreamReader BaseReader => _reader; public NibbleReader(BinaryStreamReader reader) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _buffer = null; } public byte ReadNibble() { if (!_buffer.HasValue) { _buffer = ((BinaryStreamReader)(ref _reader)).ReadByte(); return (byte)(_buffer & 0xF).Value; } byte result = (byte)((_buffer >> 4) & 0xF).Value; _buffer = null; return result; } public uint Read3BitEncodedUInt() { uint num = 0u; byte b; do { b = ReadNibble(); num <<= 3; num |= b & 7u; } while ((b & 8u) != 0); return num; } } internal struct NibbleWriter { private readonly BinaryStreamWriter _writer; private byte? _buffer; public NibbleWriter(BinaryStreamWriter writer) { _writer = writer; _buffer = null; } public void WriteNibble(byte nibble) { nibble = (byte)(nibble & 0xFu); if (_buffer.HasValue) { _writer.WriteByte((byte)(_buffer.Value | (nibble << 4))); _buffer = null; } else { _buffer = nibble; } } public void Write3BitEncodedUInt(uint value) { int i; for (i = 0; value >> i > 7; i += 3) { } while (i > 0) { WriteNibble((byte)(((value >> i) & 7u) | 8u)); i -= 3; } WriteNibble((byte)(value & 7u)); } public void Flush() { byte? buffer = _buffer; if (buffer.HasValue) { _writer.WriteByte(_buffer.Value); _buffer = null; } } } [Flags] public enum ReadyToRunAttributes { PlatformNeutralSource = 1, Composite = 2, Partial = 4, NonSharedPInvokeStubs = 8, EmbeddedMsil = 0x10, Component = 0x20, MultiModuleVersionBubble = 0x40, UnrelatedR2RCode = 0x80 } public class ReadyToRunDirectory : SegmentBase, IManagedNativeHeader, ISegment, IOffsetProvider, IWritable { private IList? _sections; public ManagedNativeHeaderSignature Signature => ManagedNativeHeaderSignature.Rtr; public ushort MajorVersion { get; set; } = 5; public ushort MinorVersion { get; set; } = 4; public ReadyToRunAttributes Attributes { get; set; } public IList Sections { get { if (_sections == null) { Interlocked.CompareExchange(ref _sections, GetSections(), null); } return _sections; } } protected virtual IList GetSections() { return new List(); } public IReadyToRunSection GetSection(ReadyToRunSectionType type) { if (!TryGetSection(type, out IReadyToRunSection section)) { throw new ArgumentException($"Directory does not contain a section of type {type}."); } return section; } public TSection GetSection() where TSection : class, IReadyToRunSection { if (!TryGetSection(out TSection section)) { throw new ArgumentException("Directory does not contain a section of type " + typeof(TSection).Name + "."); } return section; } public bool TryGetSection(ReadyToRunSectionType type, [NotNullWhen(true)] out IReadyToRunSection? section) { for (int i = 0; i < Sections.Count; i++) { if (Sections[i].Type == type) { section = Sections[i]; return true; } } section = null; return false; } public bool TryGetSection([NotNullWhen(true)] out TSection? section) where TSection : class, IReadyToRunSection { for (int i = 0; i < Sections.Count; i++) { if (Sections[i] is TSection val) { section = val; return true; } } section = null; return false; } public override uint GetPhysicalSize() { return (uint)(16 + Sections.Count * 12); } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32((uint)Signature); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt32((uint)Attributes); writer.WriteInt32(Sections.Count); foreach (IReadyToRunSection section in Sections) { writer.WriteUInt32((uint)section.Type); writer.WriteUInt32(((IOffsetProvider)section).Rva); writer.WriteUInt32(((IWritable)section).GetPhysicalSize()); } } } public enum ReadyToRunFixupKind : byte { ThisObjDictionaryLookup = 7, TypeDictionaryLookup = 8, MethodDictionaryLookup = 9, TypeHandle = 16, MethodHandle = 17, FieldHandle = 18, MethodEntry = 19, MethodEntryDefToken = 20, MethodEntryRefToken = 21, VirtualEntry = 22, VirtualEntryDefToken = 23, VirtualEntryRefToken = 24, VirtualEntrySlot = 25, Helper = 26, StringHandle = 27, NewObject = 28, NewArray = 29, IsInstanceOf = 30, ChkCast = 31, FieldAddress = 32, CctorTrigger = 33, StaticBaseNonGC = 34, StaticBaseGC = 35, ThreadStaticBaseNonGC = 36, ThreadStaticBaseGC = 37, FieldBaseOffset = 38, FieldOffset = 39, TypeDictionary = 40, MethodDictionary = 41, CheckTypeLayout = 42, CheckFieldOffset = 43, DelegateCtor = 44, DeclaringTypeHandle = 45, IndirectPInvokeTarget = 46, PInvokeTarget = 47, CheckInstructionSetSupport = 48, VerifyFieldOffset = 49, VerifyTypeLayout = 50, CheckVirtualFunctionOverride = 51, VerifyVirtualFunctionOverride = 52, CheckILBody = 53, VerifyILBody = 54, ModuleOverride = 128 } public enum ReadyToRunHelper : uint { Invalid = 0u, Module = 1u, GSCookie = 2u, IndirectTrapThreads = 3u, DelayLoadMethodCall = 8u, DelayLoadHelper = 16u, DelayLoadHelperObj = 17u, DelayLoadHelperObjObj = 18u, Throw = 32u, Rethrow = 33u, Overflow = 34u, RngChkFail = 35u, FailFast = 36u, ThrowNullRef = 37u, ThrowDivZero = 38u, WriteBarrier = 48u, CheckedWriteBarrier = 49u, ByRefWriteBarrier = 50u, StelemRef = 56u, LdelemaRef = 57u, MemSet = 64u, MemCpy = 65u, PInvokeBegin = 66u, PInvokeEnd = 67u, GCPoll = 68u, ReversePInvokeEnter = 69u, ReversePInvokeExit = 70u, GetString = 80u, LogMethodEnter = 81u, GetRuntimeTypeHandle = 84u, GetRuntimeMethodHandle = 85u, GetRuntimeFieldHandle = 86u, Box = 88u, BoxNullable = 89u, Unbox = 90u, UnboxNullable = 91u, NewMultiDimArr = 92u, NewObject = 96u, NewArray = 97u, CheckCastAny = 98u, CheckInstanceAny = 99u, GenericGcStaticBase = 100u, GenericNonGcStaticBase = 101u, GenericGcTlsBase = 102u, GenericNonGcTlsBase = 103u, VirtualFuncPtr = 104u, IsInstanceOfException = 105u, NewMaybeFrozenArray = 106u, NewMaybeFrozenObject = 107u, LMul = 192u, LMulOfv = 193u, ULMulOvf = 194u, LDiv = 195u, LMod = 196u, ULDiv = 197u, ULMod = 198u, LLsh = 199u, LRsh = 200u, LRsz = 201u, Lng2Dbl = 202u, ULng2Dbl = 203u, Div = 204u, Mod = 205u, UDiv = 206u, UMod = 207u, Dbl2Int = 208u, Dbl2IntOvf = 209u, Dbl2Lng = 210u, Dbl2LngOvf = 211u, Dbl2UInt = 212u, Dbl2UIntOvf = 213u, Dbl2ULng = 214u, Dbl2ULngOvf = 215u, DblRem = 224u, FltRem = 225u, DblRound = 226u, FltRound = 227u, PersonalityRoutine = 240u, PersonalityRoutineFilterFunclet = 241u, MonitorEnter = 248u, MonitorExit = 249u, WriteBarrierEax = 256u, WriteBarrierEbx = 257u, WriteBarrierEcx = 258u, WriteBarrierEsi = 259u, WriteBarrierEdi = 260u, WriteBarrierEbp = 261u, CheckedWriteBarrierEax = 262u, CheckedWriteBarrierEbx = 263u, CheckedWriteBarrierEcx = 264u, CheckedWriteBarrierEsi = 265u, CheckedWriteBarrierEdi = 266u, CheckedWriteBarrierEbp = 267u, EndCatch = 272u, StackProbe = 273u, GetCurrentManagedThreadId = 274u, StelemRefI = 275u, LdelemaRefI = 276u } public enum ReadyToRunSectionType { CompilerIdentifier = 100, ImportSections, RuntimeFunctions, MethodDefEntryPoints, ExceptionInfo, DebugInfo, DelayLoadMethodCallThunks, AvailableTypesOld, AvailableTypes, InstanceMethodEntryPoints, InliningInfo, ProfileDataInfo, ManifestMetadata, AttributePresence, InliningInfo2, ComponentAssemblies, OwnerCompositeExecutable, PgoInstrumentationData, ManifestAssemblyMvids, CrossModuleInlineInfo, HotColdMap, MethodIsGenericMap, EnclosingTypeMap, TypeGenericInfoMap } public abstract class RuntimeFunctionsSection : SegmentBase, IReadyToRunSection, ISegment, IOffsetProvider, IWritable { public ReadyToRunSectionType Type => ReadyToRunSectionType.RuntimeFunctions; public virtual bool CanRead => false; public virtual BinaryStreamReader CreateReader() { throw new InvalidOperationException(); } public abstract IEnumerable GetFunctions(); } public abstract class RuntimeFunctionsSection : RuntimeFunctionsSection where TFunction : IRuntimeFunction, IWritable { private IList? _functions; public IList Functions { get { if (_functions == null) { Interlocked.CompareExchange(ref _functions, GetEntries(), null); } return _functions; } } protected virtual IList GetEntries() { return new List(); } public sealed override IEnumerable GetFunctions() { return (IEnumerable)Functions; } public override uint GetPhysicalSize() { if (Functions.Count <= 0) { return 0u; } return (uint)Functions.Count * ((IWritable)Functions[0]).GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { for (int i = 0; i < Functions.Count; i++) { ((IWritable)Functions[i]).Write(writer); } } } public class SerializedDebugInfo : DebugInfo { private readonly PEReaderContext _context; private readonly BinaryStreamReader _boundsReader; private readonly BinaryStreamReader _variablesReader; public SerializedDebugInfo(PEReaderContext context, BinaryStreamReader reader) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) _context = context; BinaryStreamReader val = reader; uint num = NativeFormat.DecodeUnsigned(ref reader); if (num != 0) { ((BinaryStreamReader)(ref reader)).Offset = ((BinaryStreamReader)(ref val)).Offset - num; } NibbleReader nibbleReader = new NibbleReader(reader); uint num2 = nibbleReader.Read3BitEncodedUInt(); uint num3 = nibbleReader.Read3BitEncodedUInt(); BinaryStreamReader baseReader = nibbleReader.BaseReader; _boundsReader = ((BinaryStreamReader)(ref reader)).ForkRelative(((BinaryStreamReader)(ref baseReader)).RelativeOffset, num2); baseReader = nibbleReader.BaseReader; _variablesReader = ((BinaryStreamReader)(ref reader)).ForkRelative(((BinaryStreamReader)(ref baseReader)).RelativeOffset + num2, num3); } protected override IList GetBounds() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) IList bounds = base.GetBounds(); if (((BinaryStreamReader)(ref _boundsReader)).Length == 0) { return bounds; } NibbleReader nibbleReader = new NibbleReader(_boundsReader); uint num = nibbleReader.Read3BitEncodedUInt(); uint num2 = 0u; for (int i = 0; i < num; i++) { num2 += nibbleReader.Read3BitEncodedUInt(); bounds.Add(new DebugInfoBounds(num2, nibbleReader.Read3BitEncodedUInt() + 4294967293u, (DebugInfoAttributes)nibbleReader.Read3BitEncodedUInt())); } return bounds; } protected override IList GetVariables() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) IList variables = base.GetVariables(); if (((BinaryStreamReader)(ref _variablesReader)).Length == 0) { return variables; } NibbleReader reader = new NibbleReader(_variablesReader); uint num = reader.Read3BitEncodedUInt(); for (int i = 0; i < num; i++) { variables.Add(DebugInfoVariable.FromReader(_context, ref reader)); } return variables; } } public class SerializedDebugInfoSection : DebugInfoSection { private readonly PEReaderContext _context; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedDebugInfoSection(PEReaderContext context, BinaryStreamReader reader) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) _context = context; _reader = reader; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } protected override NativeArray GetEntries() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return NativeArray.FromReader(_reader, (BinaryStreamReader r) => new SerializedDebugInfo(_context, r)); } } public class SerializedImportSection : ImportSection { private readonly PEReaderContext _context; private readonly DataDirectory _section; private readonly byte _originalEntrySize; private readonly uint _signatures; public SerializedImportSection(PEReaderContext context, ref BinaryStreamReader reader) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _context = context; _section = DataDirectory.FromReader(ref reader); base.Attributes = (ImportSectionAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(); base.Type = (ImportSectionType)((BinaryStreamReader)(ref reader)).ReadByte(); base.EntrySize = (_originalEntrySize = ((BinaryStreamReader)(ref reader)).ReadByte()); _signatures = ((BinaryStreamReader)(ref reader)).ReadUInt32(); base.AuxiliaryData = context.File.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()); } protected override ReferenceTable GetSlots() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) ReferenceTable slots = base.GetSlots(); if (!((DataDirectory)(ref _section)).IsPresentInPE) { return slots; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateDataDirectoryReader(_section, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid RVA and/or size for import section."); return slots; } byte originalEntrySize = _originalEntrySize; if ((originalEntrySize != 4 && originalEntrySize != 8) || 1 == 0) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid entry size of {_originalEntrySize} for import section."); return slots; } while (((BinaryStreamReader)(ref val)).CanRead((uint)_originalEntrySize)) { ulong num = ((BinaryStreamReader)(ref val)).ReadNativeInt(_originalEntrySize == 4); ISegmentReference item = ((num != 0L) ? _context.File.GetReferenceToRva((uint)(num - _context.File.OptionalHeader.ImageBase)) : SegmentReference.Null); ((Collection)(object)slots).Add(item); } return slots; } protected override ReferenceTable GetSignatures() { ReferenceTable signatures = base.GetSignatures(); if (_signatures == 0) { return signatures; } BinaryStreamReader val = default(BinaryStreamReader); if (!_context.File.TryCreateReaderAtRva(_signatures, ref val)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid signatures RVA {_signatures:X8} for import section."); return signatures; } for (int i = 0; i < ((DataDirectory)(ref _section)).Size / _originalEntrySize; i++) { ((Collection)(object)signatures).Add(_context.File.GetReferenceToRva(((BinaryStreamReader)(ref val)).ReadUInt32())); } return signatures; } } public sealed class SerializedImportSectionsSection : ImportSectionsSection { private readonly PEReaderContext _context; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedImportSectionsSection(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; _context = context; _reader = reader; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } protected override IList GetSections() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) List list = new List(); BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref reader)).CanRead(19u)) { list.Add(new SerializedImportSection(_context, ref reader)); } return list; } } public class SerializedMethodEntryPointsSection : MethodEntryPointsSection { private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedMethodEntryPointsSection(ref BinaryStreamReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; _reader = reader; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } protected override NativeArray GetEntryPoints() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return NativeArray.FromReader(_reader, (BinaryStreamReader reader) => MethodEntryPoint.FromReader(ref reader)); } } public class SerializedReadyToRunDirectory : ReadyToRunDirectory { private readonly PEReaderContext _context; private readonly uint _numberOfSections; private readonly BinaryStreamReader _sectionReader; public SerializedReadyToRunDirectory(PEReaderContext context, ref BinaryStreamReader reader) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (((BinaryStreamReader)(ref reader)).ReadUInt32() != 5395538) { throw new BadImageFormatException("Input stream does not point to a valid R2R header."); } ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; _context = context; base.MajorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref reader)).ReadUInt16(); base.Attributes = (ReadyToRunAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(); _numberOfSections = ((BinaryStreamReader)(ref reader)).ReadUInt32(); _sectionReader = ((BinaryStreamReader)(ref reader)).Fork(); } protected override IList GetSections() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) List list = new List(); BinaryStreamReader val = ((BinaryStreamReader)(ref _sectionReader)).Fork(); BinaryStreamReader reader = default(BinaryStreamReader); for (int i = 0; i < _numberOfSections; i++) { if (!((BinaryStreamReader)(ref val)).CanRead(12u)) { break; } ReadyToRunSectionType type = (ReadyToRunSectionType)((BinaryStreamReader)(ref val)).ReadUInt32(); DataDirectory val2 = DataDirectory.FromReader(ref val); if (!_context.File.TryCreateDataDirectoryReader(val2, ref reader)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid RVA and/or size for ReadyToRun section {i}."); } else { list.Add(_context.Parameters.ReadyToRunSectionReader.ReadSection(_context, type, ref reader)); } } return list; } } public class SerializedX64RuntimeFunctionsSection : RuntimeFunctionsSection { private readonly PEReaderContext _context; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedX64RuntimeFunctionsSection(PEReaderContext context, ref BinaryStreamReader reader) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; _context = context; _reader = reader; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } protected override IList GetEntries() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) IList entries = base.GetEntries(); BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref reader)).CanRead(12u)) { entries.Add(X64RuntimeFunction.FromReader(_context, ref reader)); } return entries; } } } namespace AsmResolver.PE.DotNet.Metadata { public abstract class BlobStream : MetadataHeap { public const string DefaultName = "#Blob"; protected BlobStream() : base("#Blob") { } protected BlobStream(string name) : base(name) { } public abstract byte[]? GetBlobByIndex(uint index); public abstract bool TryGetBlobReaderByIndex(uint index, out BinaryStreamReader reader); public abstract bool TryFindBlobIndex(byte[]? blob, out uint index); } public class CustomMetadataStream : IMetadataStream, ISegment, IOffsetProvider, IWritable { public ulong Offset => ((IOffsetProvider)Contents).Offset; public uint Rva => ((IOffsetProvider)Contents).Rva; public bool CanUpdateOffsets => true; public string Name { get; set; } [MemberNotNullWhen(true, "Contents")] public bool CanRead { [MemberNotNullWhen(true, "Contents")] get { return Contents is IReadableSegment; } } public ISegment Contents { get; set; } public CustomMetadataStream(string name, byte[] data) : this(name, (ISegment)new DataSegment(data)) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown public CustomMetadataStream(string name, ISegment contents) { Name = name; Contents = contents; } public BinaryStreamReader CreateReader() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!CanRead) { throw new InvalidOperationException("Contents of the metadata stream is not readable."); } return Extensions.CreateReader((IReadableSegment)Contents); } public void UpdateOffsets(in RelocationParameters parameters) { Contents.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return ((IWritable)Contents).GetPhysicalSize(); } public uint GetVirtualSize() { return GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { ((IWritable)Contents).Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class DefaultMetadataStreamReader : IMetadataStreamReader { public static DefaultMetadataStreamReader Instance { get; } = new DefaultMetadataStreamReader(); public IMetadataStream ReadStream(MetadataReaderContext context, MetadataStreamReaderFlags flags, MetadataStreamHeader header, ref BinaryStreamReader reader) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) StringComparison comparisonType = (((flags & MetadataStreamReaderFlags.IsEnc) != 0) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); if (string.Equals(header.Name, "#~", comparisonType) || string.Equals(header.Name, "#-", comparisonType)) { bool forceLargeColumns = (flags & MetadataStreamReaderFlags.IsEnc) != 0 && (flags & MetadataStreamReaderFlags.HasJtdStream) != 0; return new SerializedTableStream(context, header.Name, in reader) { ForceLargeColumns = forceLargeColumns }; } if (string.Equals(header.Name, "#Strings", comparisonType)) { return new SerializedStringsStream(header.Name, in reader); } if (string.Equals(header.Name, "#US", comparisonType)) { return new SerializedUserStringsStream(header.Name, reader); } if (string.Equals(header.Name, "#Blob", comparisonType)) { return new SerializedBlobStream(header.Name, in reader); } if (string.Equals(header.Name, "#GUID", comparisonType)) { return new SerializedGuidStream(header.Name, in reader); } if (header.Name == "#Pdb") { return new SerializedPdbStream(header.Name, in reader); } return new CustomMetadataStream(header.Name, (ISegment)(object)DataSegment.FromReader(ref reader)); } } public class FieldRvaDataReader : IFieldRvaDataReader { public static FieldRvaDataReader Instance { get; } = new FieldRvaDataReader(); public ISegment? ResolveFieldData(IErrorListener listener, Platform platform, DotNetDirectory directory, in FieldRvaRow fieldRvaRow) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown if (fieldRvaRow.Data.IsBounded) { return fieldRvaRow.Data.GetSegment(); } MetadataDirectory metadata = directory.Metadata; if (metadata == null) { ErrorListenerExtensions.BadImage(listener, ".NET directory does not contain a metadata directory."); return null; } if (!metadata.TryGetStream(out TablesStream stream)) { ErrorListenerExtensions.BadImage(listener, "Metadata does not contain a tables stream."); return null; } MetadataTable table = stream.GetTable(TableIndex.Field); if (fieldRvaRow.Field > table.Count) { ErrorListenerExtensions.BadImage(listener, "FieldRva row has an invalid Field column value."); return null; } FieldDefinitionRow field = table.GetByRid(fieldRvaRow.Field); int num = DetermineFieldSize(listener, platform, directory, in field); if (fieldRvaRow.Data.CanRead) { BinaryStreamReader val = fieldRvaRow.Data.CreateReader(); return (ISegment?)(object)DataSegment.FromReader(ref val, num); } ISegmentReference data = fieldRvaRow.Data; PESegmentReference val2 = (PESegmentReference)(object)((data is PESegmentReference) ? data : null); if (val2 != null && val2.IsValidAddress) { ZeroesSegment val3 = new ZeroesSegment((uint)num); RelocationParameters val4 = new RelocationParameters(((IOffsetProvider)fieldRvaRow.Data).Offset, ((IOffsetProvider)fieldRvaRow.Data).Rva); ((SegmentBase)val3).UpdateOffsets(ref val4); return (ISegment?)val3; } ErrorListenerExtensions.NotSupported(listener, "FieldRva row has an invalid or unsupported data column."); return null; } private int DetermineFieldSize(IErrorListener listener, Platform platform, DotNetDirectory directory, in FieldDefinitionRow field) { if (!directory.Metadata.TryGetStream(out BlobStream stream) || !stream.TryGetBlobReaderByIndex(field.Signature, out var reader)) { return 0; } ((BinaryStreamReader)(ref reader)).ReadByte(); uint num = default(uint); do { IL_002a: switch ((ElementType)((BinaryStreamReader)(ref reader)).ReadByte()) { case ElementType.Boolean: return 1; case ElementType.Char: return 2; case ElementType.I1: return 1; case ElementType.U1: return 1; case ElementType.I2: return 2; case ElementType.U2: return 2; case ElementType.I4: return 4; case ElementType.U4: return 4; case ElementType.I8: return 8; case ElementType.U8: return 8; case ElementType.R4: return 4; case ElementType.R8: return 8; case ElementType.ValueType: return GetCustomTypeSize(directory.Metadata, ref reader); case ElementType.Ptr: case ElementType.I: case ElementType.U: case ElementType.FnPtr: if (!directory.Flags.IsLoadedAs32Bit(platform)) { return 8; } return 4; case ElementType.CModReqD: case ElementType.CModOpt: continue; } goto IL_002a; } while (((BinaryStreamReader)(ref reader)).TryReadCompressedUInt32(ref num)); return ErrorListenerExtensions.BadImageAndReturn(listener, "Invalid field signature."); } private int GetCustomTypeSize(MetadataDirectory metadataDirectory, ref BinaryStreamReader reader) { uint codedIndex = default(uint); if (!((BinaryStreamReader)(ref reader)).TryReadCompressedUInt32(ref codedIndex) || !metadataDirectory.TryGetStream(out TablesStream stream)) { return 0; } MetadataToken metadataToken = stream.GetIndexEncoder(CodedIndex.TypeDefOrRef).DecodeIndex(codedIndex); if (metadataToken.Table == TableIndex.TypeDef && stream.GetTable(TableIndex.ClassLayout).TryGetRowByKey(2, metadataToken.Rid, out var row)) { return (int)row.ClassSize; } return 0; } ISegment? IFieldRvaDataReader.ResolveFieldData(IErrorListener listener, Platform platform, DotNetDirectory directory, in FieldRvaRow fieldRvaRow) { return ResolveFieldData(listener, platform, directory, in fieldRvaRow); } } public abstract class GuidStream : MetadataHeap { public const int GuidSize = 16; public const string DefaultName = "#GUID"; protected GuidStream() : base("#GUID") { } protected GuidStream(string name) : base(name) { } public abstract Guid GetGuidByIndex(uint index); public abstract bool TryFindGuidIndex(Guid guid, out uint index); } public interface IFieldRvaDataReader { ISegment? ResolveFieldData(IErrorListener listener, Platform platform, DotNetDirectory directory, in FieldRvaRow fieldRvaRow); } public interface ILazyMetadataStream : IMetadataStream, ISegment, IOffsetProvider, IWritable { void Initialize(MetadataDirectory parentMetadata); } public interface IMetadataStream : ISegment, IOffsetProvider, IWritable { string Name { get; set; } bool CanRead { get; } BinaryStreamReader CreateReader(); } public interface IMetadataStreamReader { IMetadataStream ReadStream(MetadataReaderContext context, MetadataStreamReaderFlags flags, MetadataStreamHeader header, ref BinaryStreamReader reader); } public class MetadataDirectory : SegmentBase { private IList? _streams; public ushort MajorVersion { get; set; } = 1; public ushort MinorVersion { get; set; } = 1; public uint Reserved { get; set; } public string VersionString { get; set; } = "v4.0.30319"; public ushort Flags { get; set; } public bool IsEncMetadata { get; set; } public IList Streams { get { if (_streams == null) { Interlocked.CompareExchange(ref _streams, GetStreams(), null); } return _streams; } } public static MetadataDirectory FromFile(string path) { return FromBytes(File.ReadAllBytes(path)); } public static MetadataDirectory FromBytes(byte[] data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromReader(new BinaryStreamReader(data)); } public static MetadataDirectory FromFile(IInputFile file) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromReader(IOExtensions.CreateReader(file)); } public static MetadataDirectory FromReader(BinaryStreamReader reader) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FromReader(reader, new MetadataReaderContext((ISegmentReferenceFactory)(object)VirtualAddressFactory.Instance)); } public static MetadataDirectory FromReader(BinaryStreamReader reader, MetadataReaderContext context) { return new SerializedMetadataDirectory(context, ref reader); } public override uint GetPhysicalSize() { return (uint)(16 + Extensions.Align((uint)VersionString.Length, 4u) + 2 + 2 + GetSizeOfStreamHeaders() + Streams.Sum((IMetadataStream s) => ((IWritable)s).GetPhysicalSize())); } public override void Write(BinaryStreamWriter writer) { ulong offset = writer.Offset; writer.WriteUInt32(1112167234u); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt32(Reserved); byte[] array = new byte[Extensions.Align((uint)VersionString.Length, 4u)]; Encoding.UTF8.GetBytes(VersionString, 0, VersionString.Length, array, 0); writer.WriteInt32(array.Length); writer.WriteBytes(array); writer.WriteUInt16(Flags); writer.WriteUInt16((ushort)Streams.Count); ulong offset2 = writer.Offset; WriteStreamHeaders(writer, GetStreamHeaders((uint)(offset2 - offset))); WriteStreams(writer); } protected virtual MetadataStreamHeader[] GetStreamHeaders(uint offset) { uint sizeOfStreamHeaders = GetSizeOfStreamHeaders(); offset += sizeOfStreamHeaders; MetadataStreamHeader[] array = new MetadataStreamHeader[Streams.Count]; for (int i = 0; i < array.Length; i++) { uint physicalSize = ((IWritable)Streams[i]).GetPhysicalSize(); array[i] = new MetadataStreamHeader(offset, physicalSize, Streams[i].Name); offset += physicalSize; } return array; } private uint GetSizeOfStreamHeaders() { return (uint)(Streams.Count * 2 * 4 + Streams.Sum((IMetadataStream s) => Extensions.Align((uint)(s.Name.Length + 1), 4u))); } protected virtual void WriteStreamHeaders(BinaryStreamWriter writer, MetadataStreamHeader[] headers) { for (int i = 0; i < headers.Length; i++) { MetadataStreamHeader metadataStreamHeader = headers[i]; writer.WriteUInt32(metadataStreamHeader.Offset); writer.WriteUInt32(metadataStreamHeader.Size); ulong offset = writer.Offset; writer.WriteAsciiString(metadataStreamHeader.Name); writer.WriteByte((byte)0); writer.AlignRelative(4u, offset); } } protected virtual void WriteStreams(BinaryStreamWriter writer) { for (int i = 0; i < Streams.Count; i++) { ((IWritable)Streams[i]).Write(writer); } } public virtual IMetadataStream GetStream(string name) { if (!TryGetStream(name, out IMetadataStream stream)) { throw new KeyNotFoundException("Metadata directory does not contain a stream called " + name + "."); } return stream; } public TStream GetStream() where TStream : class, IMetadataStream { if (!TryGetStream(out TStream stream)) { throw new KeyNotFoundException("Metadata directory does not contain a stream of type " + typeof(TStream).FullName + "."); } return stream; } public bool TryGetStream(string name, [NotNullWhen(true)] out IMetadataStream? stream) { bool flag; switch (name) { case "#~": case "#-": case "#Schema": flag = true; break; default: flag = false; break; } bool heapRequested = !flag; return TryFindStream((IMetadataStream c, object? s) => c.Name == s as string, name, heapRequested, out stream); } public bool TryGetStream([NotNullWhen(true)] out TStream? stream) where TStream : class, IMetadataStream { bool heapRequested = !typeof(TablesStream).IsAssignableFrom(typeof(TStream)); if (TryFindStream((IMetadataStream c, object? _) => c is TStream, null, heapRequested, out IMetadataStream stream2)) { stream = (TStream)stream2; return true; } stream = null; return false; } private bool TryFindStream(Func condition, object? state, bool heapRequested, [NotNullWhen(true)] out IMetadataStream? stream) { IList streams = Streams; if (heapRequested && !IsEncMetadata) { for (int num = streams.Count - 1; num >= 0; num--) { if (condition(streams[num], state)) { stream = streams[num]; return true; } } } else { for (int i = 0; i < streams.Count; i++) { if (condition(streams[i], state)) { stream = streams[i]; return true; } } } stream = null; return false; } protected virtual IList GetStreams() { return new List(); } } public abstract class MetadataHeap : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public string Name { get; set; } public virtual bool CanRead => false; public IndexSize IndexSize { get { if (((SegmentBase)this).GetPhysicalSize() > 65535) { return (IndexSize)4; } return (IndexSize)2; } } protected MetadataHeap(string name) { Name = name ?? throw new ArgumentNullException("name"); } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } } public class MetadataReaderContext : IErrorListener { public ISegmentReferenceFactory ReferenceFactory { get; } public IErrorListener ErrorListener { get; } public IMetadataStreamReader MetadataStreamReader { get; } public MetadataReaderContext(ISegmentReferenceFactory factory) : this(factory, (IErrorListener)(object)ThrowErrorListener.Instance, DefaultMetadataStreamReader.Instance) { } public MetadataReaderContext(ISegmentReferenceFactory referenceFactory, IErrorListener errorListener, IMetadataStreamReader metadataStreamReader) { ReferenceFactory = referenceFactory; ErrorListener = errorListener; MetadataStreamReader = metadataStreamReader; } public static MetadataReaderContext FromReaderContext(PEReaderContext context) { return new MetadataReaderContext((ISegmentReferenceFactory)(object)context.File, context.Parameters.ErrorListener, context.Parameters.MetadataStreamReader); } public void MarkAsFatal() { ErrorListener.MarkAsFatal(); } public void RegisterException(Exception exception) { ErrorListener.RegisterException(exception); } } public enum MetadataSignature { Bsjb = 1112167234, ComPlus = 726486851 } public readonly struct MetadataStreamHeader { public uint Offset { get; } public uint Size { get; } public string Name { get; } public MetadataStreamHeader(uint offset, uint size, string name) { Offset = offset; Size = size; Name = name ?? throw new ArgumentNullException("name"); if (name.Length > 32) { throw new ArgumentOutOfRangeException("name", "Name can be no longer than 32 bytes."); } } public static MetadataStreamHeader FromReader(ref BinaryStreamReader reader) { uint offset = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint size = ((BinaryStreamReader)(ref reader)).ReadUInt32(); string name = ((BinaryStreamReader)(ref reader)).ReadAsciiString(); ((BinaryStreamReader)(ref reader)).AlignRelative(4u); return new MetadataStreamHeader(offset, size, name); } public override string ToString() { return $"{"Offset"}: {Offset:X8}, {"Size"}: {Size:X8}, {"Name"}: {Name}"; } } public class MetadataStreamList : LazyList { private readonly MetadataReaderContext _context; private readonly MetadataStreamHeader[] _streamHeaders; private readonly MetadataDirectory _owner; private readonly BinaryStreamReader _directoryReader; private readonly MetadataStreamReaderFlags _streamReaderFlags; public override int Count { get { if (!base.IsInitialized) { return _streamHeaders.Length; } return base.Items.Count; } } public MetadataStreamList(MetadataDirectory owner, MetadataReaderContext context, MetadataStreamReaderFlags streamReaderFlags, MetadataStreamHeader[] streamHeaders, in BinaryStreamReader directoryReader) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) _context = context ?? throw new ArgumentNullException("context"); _streamHeaders = streamHeaders; _owner = owner; _directoryReader = directoryReader; _streamReaderFlags = streamReaderFlags; } protected override void Initialize() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) MetadataStreamHeader[] streamHeaders = _streamHeaders; for (int i = 0; i < streamHeaders.Length; i++) { MetadataStreamHeader header = streamHeaders[i]; BinaryStreamReader reader = ((BinaryStreamReader)(ref _directoryReader)).ForkAbsolute(((BinaryStreamReader)(ref _directoryReader)).Offset + header.Offset, header.Size); IMetadataStream item = _context.MetadataStreamReader.ReadStream(_context, _streamReaderFlags, header, ref reader); base.Items.Add(item); } } protected override void PostInitialize() { for (int i = 0; i < base.Items.Count; i++) { if (base.Items[i] is ILazyMetadataStream lazyMetadataStream) { lazyMetadataStream.Initialize(_owner); } } } } [Flags] public enum MetadataStreamReaderFlags { None = 0, IsEnc = 1, HasJtdStream = 2 } public class PdbStream : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public const string DefaultName = "#Pdb"; public string Name { get; set; } = "#Pdb"; public virtual bool CanRead => false; public byte[] Id { get; } = new byte[20]; public MetadataToken EntryPoint { get; set; } public uint[] TypeSystemRowCounts { get; } = new uint[56]; public void UpdateRowCounts(TablesStream stream) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 44) { if (tableIndex.IsValidTableIndex()) { TypeSystemRowCounts[(uint)tableIndex] = (uint)stream.GetTable(tableIndex).Count; } tableIndex++; } } public void UpdateRowCounts(uint[] rowCounts) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 44 && (int)tableIndex < rowCounts.Length) { if (tableIndex.IsValidTableIndex()) { TypeSystemRowCounts[(uint)tableIndex] = rowCounts[(uint)tableIndex]; } tableIndex++; } } public ulong ComputeReferencedTypeSystemTables() { ulong num = 0uL; for (int i = 0; i < TypeSystemRowCounts.Length; i++) { if (TypeSystemRowCounts[i] != 0) { num |= (ulong)(1L << i); } } return num; } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } public override uint GetPhysicalSize() { return (uint)(32 + 4 * TypeSystemRowCounts.Count((uint c) => c != 0)); } public override void Write(BinaryStreamWriter writer) { writer.WriteBytes(Id); writer.WriteUInt32(EntryPoint.ToUInt32()); writer.WriteUInt64(ComputeReferencedTypeSystemTables()); uint[] typeSystemRowCounts = TypeSystemRowCounts; foreach (uint num in typeSystemRowCounts) { if (num != 0) { writer.WriteUInt32(num); } } } } public class SerializedBlobStream : BlobStream { private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedBlobStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Blob", in reader); } public SerializedBlobStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedBlobStream(string name, in BinaryStreamReader reader) : base(name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(BinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override byte[]? GetBlobByIndex(uint index) { if (!TryGetBlobReaderByIndex(index, out var reader)) { return null; } return ((BinaryStreamReader)(ref reader)).ReadToEnd(); } public override bool TryGetBlobReaderByIndex(uint index, out BinaryStreamReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (index == 0 || index >= ((BinaryStreamReader)(ref _reader)).Length) { reader = default(BinaryStreamReader); return false; } reader = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); uint num = default(uint); if (((BinaryStreamReader)(ref reader)).TryReadCompressedUInt32(ref num)) { uint num2 = (uint)(((BinaryStreamReader)(ref reader)).Offset - ((BinaryStreamReader)(ref reader)).StartOffset); ((BinaryStreamReader)(ref reader)).ChangeSize(Math.Min(num + num2, ((BinaryStreamReader)(ref reader)).Length)); return true; } return false; } public override bool TryFindBlobIndex(byte[]? blob, out uint index) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (blob == null) { index = 0u; return true; } uint num = (uint)blob.Length + Extensions.GetCompressedSize((uint)blob.Length); BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); uint num2 = default(uint); while (((BinaryStreamReader)(ref val)).CanRead(num)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num2) && num2 == blob.Length && ((BinaryStreamReader)(ref val)).CanRead(num2)) { int i; for (i = 0; i < blob.Length && blob[i] == ((BinaryStreamReader)(ref val)).ReadByte(); i++) { } if (i == blob.Length) { return true; } } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } public class SerializedGuidStream : GuidStream { [ThreadStatic] private static byte[]? _readBuffer; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedGuidStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#GUID", in reader); } public SerializedGuidStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedGuidStream(string name, in BinaryStreamReader reader) : base(name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(BinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override Guid GetGuidByIndex(uint index) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (index == 0) { return Guid.Empty; } if (_readBuffer == null) { _readBuffer = new byte[16]; } uint num = (index - 1) * 16; if (num < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(num); ((BinaryStreamReader)(ref val)).ReadBytes(_readBuffer, 0, _readBuffer.Length); return new Guid(_readBuffer); } return Guid.Empty; } public override bool TryFindGuidIndex(Guid guid, out uint index) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (_readBuffer == null) { _readBuffer = new byte[16]; } index = 1u; BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref val)).CanRead(16u)) { if (((BinaryStreamReader)(ref val)).ReadBytes(_readBuffer, 0, _readBuffer.Length) == 16 && new Guid(_readBuffer) == guid) { return true; } index++; } index = 0u; return false; } } public class SerializedMetadataDirectory : MetadataDirectory { private readonly MetadataReaderContext _context; private readonly BinaryStreamReader _streamContentsReader; private readonly MetadataStreamHeader[] _streamHeaders; private readonly bool _hasJtdStream; private readonly bool _isEncMetadata; public SerializedMetadataDirectory(MetadataReaderContext context, ref BinaryStreamReader directoryReader) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!((BinaryStreamReader)(ref directoryReader)).IsValid) { throw new ArgumentNullException("directoryReader"); } _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref directoryReader)).Rva; _streamContentsReader = ((BinaryStreamReader)(ref directoryReader)).Fork(); _streamHeaders = ArrayShim.Empty(); MetadataSignature metadataSignature = (MetadataSignature)((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); switch (metadataSignature) { case MetadataSignature.ComPlus: ErrorListenerExtensions.NotSupported((IErrorListener)(object)_context, "Old COM+ metadata header format is not supported."); break; default: ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, $"Invalid metadata header ({metadataSignature:X8})."); break; case MetadataSignature.Bsjb: { base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.Reserved = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); uint num = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); if (!((BinaryStreamReader)(ref directoryReader)).CanRead(num)) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Invalid version length in metadata header (" + num + " characters)."); break; } byte[] array = new byte[num]; ((BinaryStreamReader)(ref directoryReader)).ReadBytes(array, 0, array.Length); base.VersionString = Encoding.ASCII.GetString(array); base.Flags = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); int num2 = ((BinaryStreamReader)(ref directoryReader)).ReadInt16(); _streamHeaders = new MetadataStreamHeader[num2]; bool? flag = null; for (int i = 0; i < num2; i++) { _streamHeaders[i] = MetadataStreamHeader.FromReader(ref directoryReader); string name = _streamHeaders[i].Name; if (!flag.HasValue) { if (name == "#~") { flag = false; } else if (name == "#-") { flag = true; } } if (name == "#Schema") { flag = true; } else if (name == "#JTD") { _hasJtdStream = true; } } base.IsEncMetadata = (_isEncMetadata = flag.GetValueOrDefault()); break; } } } protected override IList GetStreams() { if (_streamHeaders.Length == 0) { return base.GetStreams(); } MetadataStreamReaderFlags metadataStreamReaderFlags = MetadataStreamReaderFlags.None; if (_isEncMetadata) { metadataStreamReaderFlags |= MetadataStreamReaderFlags.IsEnc; } if (_hasJtdStream) { metadataStreamReaderFlags |= MetadataStreamReaderFlags.HasJtdStream; } return (IList)new MetadataStreamList(this, _context, metadataStreamReaderFlags, _streamHeaders, in _streamContentsReader); } } public class SerializedPdbStream : PdbStream { private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedPdbStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Pdb", in reader); } public SerializedPdbStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedPdbStream(string name, in BinaryStreamReader reader) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) _reader = reader; base.Name = name; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; BinaryStreamReader val2 = ((BinaryStreamReader)(ref reader)).Fork(); ((BinaryStreamReader)(ref val2)).ReadBytes(base.Id, 0, base.Id.Length); base.EntryPoint = ((BinaryStreamReader)(ref val2)).ReadUInt32(); ulong num = ((BinaryStreamReader)(ref val2)).ReadUInt64(); for (int i = 0; i < 64; i++) { if (((num >> i) & 1) != 0L) { base.TypeSystemRowCounts[i] = ((BinaryStreamReader)(ref val2)).ReadUInt32(); } } } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } } public class SerializedStringsStream : StringsStream { private readonly ConcurrentDictionary _cachedStrings; private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedStringsStream(byte[] rawData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor("#Strings", in reader); } public SerializedStringsStream(string name, byte[] rawData) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(name, in reader); } public SerializedStringsStream(string name, in BinaryStreamReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) _cachedStrings = new ConcurrentDictionary(); base..ctor(name); _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(BinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override Utf8String? GetStringByIndex(uint index) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (index == 0) { return null; } if (!_cachedStrings.TryGetValue(index, out Utf8String value) && index < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); value = ((BinaryStreamReader)(ref val)).ReadUtf8String(); _cachedStrings.TryAdd(index, value); } return value; } public override bool TryFindStringIndex(Utf8String? value, out uint index) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (value == null) { index = 0u; return true; } byte[] bytesUnsafe = value.GetBytesUnsafe(); BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); while (((BinaryStreamReader)(ref val)).CanRead((uint)value.ByteCount)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; int i; for (i = 0; i < bytesUnsafe.Length && bytesUnsafe[i] == ((BinaryStreamReader)(ref val)).ReadByte(); i++) { } if (i == value.Length && ((BinaryStreamReader)(ref val)).CanRead(1u) && ((BinaryStreamReader)(ref val)).ReadByte() == 0) { return true; } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } public class SerializedTableStream : TablesStream, ILazyMetadataStream, IMetadataStream, ISegment, IOffsetProvider, IWritable { private readonly MetadataReaderContext _context; private readonly BinaryStreamReader _reader; private readonly ulong _validMask; private readonly ulong _sortedMask; private readonly uint[] _rowCounts; private readonly uint _headerSize; private bool _tablesInitialized; private uint[]? _combinedRowCounts; private IndexSize[]? _indexSizes; public override bool CanRead => true; public SerializedTableStream(MetadataReaderContext context, string name, byte[] rawData) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = new BinaryStreamReader(rawData); this..ctor(context, name, in reader); } public SerializedTableStream(MetadataReaderContext context, string name, in BinaryStreamReader reader) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) base.Name = name ?? throw new ArgumentNullException("name"); _context = context ?? throw new ArgumentNullException("context"); _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; BinaryStreamReader val = reader; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref val)).Rva; BinaryStreamReader reader2 = ((BinaryStreamReader)(ref _reader)).Fork(); base.Reserved = ((BinaryStreamReader)(ref reader2)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref reader2)).ReadByte(); base.MinorVersion = ((BinaryStreamReader)(ref reader2)).ReadByte(); base.Flags = (TablesStreamFlags)((BinaryStreamReader)(ref reader2)).ReadByte(); base.Log2LargestRid = ((BinaryStreamReader)(ref reader2)).ReadByte(); _validMask = ((BinaryStreamReader)(ref reader2)).ReadUInt64(); _sortedMask = ((BinaryStreamReader)(ref reader2)).ReadUInt64(); _rowCounts = ReadRowCounts(ref reader2); if (base.HasExtraData) { base.ExtraData = ((BinaryStreamReader)(ref reader2)).ReadUInt32(); } _headerSize = ((BinaryStreamReader)(ref reader2)).RelativeOffset; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } private uint[] ReadRowCounts(ref BinaryStreamReader reader) { uint[] array = new uint[56]; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 56) { array[(uint)tableIndex] = (TablesStream.HasTable(_validMask, tableIndex) ? ((BinaryStreamReader)(ref reader)).ReadUInt32() : 0u); tableIndex++; } return array; } public void Initialize(MetadataDirectory parentMetadata) { if (parentMetadata.TryGetStream(out PdbStream stream)) { _combinedRowCounts = new uint[_rowCounts.Length]; base.ExternalRowCounts = new uint[48]; for (int i = 0; i < 48; i++) { _combinedRowCounts[i] = stream.TypeSystemRowCounts[i]; base.ExternalRowCounts[i] = stream.TypeSystemRowCounts[i]; } for (int j = 48; j < 56; j++) { _combinedRowCounts[j] = _rowCounts[j]; } } else { _combinedRowCounts = _rowCounts; } _indexSizes = InitializeIndexSizes(); } protected override uint GetColumnSize(ColumnType columnType) { if (_tablesInitialized) { return base.GetColumnSize(columnType); } if (_indexSizes == null) { throw new InvalidOperationException("Serialized tables stream is not fully initialized yet."); } if ((int)columnType >= _indexSizes.Length) { return base.GetColumnSize(columnType); } return (uint)_indexSizes[(int)columnType]; } private IndexSize[] InitializeIndexSizes() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected I4, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected I4, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected I4, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected I4, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected I4, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected I4, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected I4, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected I4, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected I4, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected I4, but got Unknown //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Expected I4, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected I4, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected I4, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected I4, but got Unknown List list = new List(70); uint[] rowCounts = _rowCounts; foreach (uint num in rowCounts) { list.Add((IndexSize)((base.ForceLargeColumns || num > 65535) ? 4 : 2)); } list.AddRange((IEnumerable)(object)new IndexSize[14] { (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Param, TableIndex.Property), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Param), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.Method, TableIndex.Assembly), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.Method, TableIndex.TypeSpec), (IndexSize)(int)GetCodedIndexSize(TableIndex.Event, TableIndex.Property), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.MemberRef), (IndexSize)(int)GetCodedIndexSize(TableIndex.Field, TableIndex.Method), (IndexSize)(int)GetCodedIndexSize(TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType), (IndexSize)(int)GetCodedIndexSize(TableIndex.Module, TableIndex.Module, TableIndex.Method, TableIndex.MemberRef, TableIndex.Module), (IndexSize)(int)GetCodedIndexSize(TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef), (IndexSize)(int)GetCodedIndexSize(TableIndex.TypeDef, TableIndex.Method), (IndexSize)(int)GetCodedIndexSize(TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec, TableIndex.Document, TableIndex.LocalScope, TableIndex.LocalVariable, TableIndex.LocalConstant, TableIndex.ImportScope) }); return list.ToArray(); } private IndexSize GetCodedIndexSize(params TableIndex[] tables) { if (_combinedRowCounts == null) { throw new InvalidOperationException("Serialized tables stream is not fully initialized yet."); } if (!base.ForceLargeColumns) { int num = (int)Math.Ceiling(Math.Log(tables.Length, 2.0)); int maxSmallTableMemberCount = 65535 >> num; if (tables.Select((TableIndex t) => _combinedRowCounts[(uint)t]).All((uint c) => c < maxSmallTableMemberCount)) { return (IndexSize)2; } return (IndexSize)4; } return (IndexSize)4; } protected override IList GetTables() { uint offset = _headerSize; IMetadataTable[] result = new IMetadataTable[56] { CreateNextTable(TableIndex.Module, ref offset, ModuleDefinitionRow.FromReader), CreateNextTable(TableIndex.TypeRef, ref offset, TypeReferenceRow.FromReader), CreateNextTable(TableIndex.TypeDef, ref offset, TypeDefinitionRow.FromReader), CreateNextTable(TableIndex.FieldPtr, ref offset, FieldPointerRow.FromReader), CreateNextTable(TableIndex.Field, ref offset, FieldDefinitionRow.FromReader), CreateNextTable(TableIndex.MethodPtr, ref offset, MethodPointerRow.FromReader), CreateNextTable(TableIndex.Method, ref offset, MethodDefinitionRow.FromReader), CreateNextTable(TableIndex.ParamPtr, ref offset, ParameterPointerRow.FromReader), CreateNextTable(TableIndex.Param, ref offset, ParameterDefinitionRow.FromReader), CreateNextTable(TableIndex.InterfaceImpl, ref offset, InterfaceImplementationRow.FromReader), CreateNextTable(TableIndex.MemberRef, ref offset, MemberReferenceRow.FromReader), CreateNextTable(TableIndex.Constant, ref offset, ConstantRow.FromReader), CreateNextTable(TableIndex.CustomAttribute, ref offset, CustomAttributeRow.FromReader), CreateNextTable(TableIndex.FieldMarshal, ref offset, FieldMarshalRow.FromReader), CreateNextTable(TableIndex.DeclSecurity, ref offset, SecurityDeclarationRow.FromReader), CreateNextTable(TableIndex.ClassLayout, ref offset, ClassLayoutRow.FromReader), CreateNextTable(TableIndex.FieldLayout, ref offset, FieldLayoutRow.FromReader), CreateNextTable(TableIndex.StandAloneSig, ref offset, StandAloneSignatureRow.FromReader), CreateNextTable(TableIndex.EventMap, ref offset, EventMapRow.FromReader), CreateNextTable(TableIndex.EventPtr, ref offset, EventPointerRow.FromReader), CreateNextTable(TableIndex.Event, ref offset, EventDefinitionRow.FromReader), CreateNextTable(TableIndex.PropertyMap, ref offset, PropertyMapRow.FromReader), CreateNextTable(TableIndex.PropertyPtr, ref offset, PropertyPointerRow.FromReader), CreateNextTable(TableIndex.Property, ref offset, PropertyDefinitionRow.FromReader), CreateNextTable(TableIndex.MethodSemantics, ref offset, MethodSemanticsRow.FromReader), CreateNextTable(TableIndex.MethodImpl, ref offset, MethodImplementationRow.FromReader), CreateNextTable(TableIndex.ModuleRef, ref offset, ModuleReferenceRow.FromReader), CreateNextTable(TableIndex.TypeSpec, ref offset, TypeSpecificationRow.FromReader), CreateNextTable(TableIndex.ImplMap, ref offset, ImplementationMapRow.FromReader), CreateNextTable(TableIndex.FieldRva, ref offset, FieldRvaRow.FromReader), CreateNextTable(TableIndex.EncLog, ref offset, EncLogRow.FromReader), CreateNextTable(TableIndex.EncMap, ref offset, EncMapRow.FromReader), CreateNextTable(TableIndex.Assembly, ref offset, AssemblyDefinitionRow.FromReader), CreateNextTable(TableIndex.AssemblyProcessor, ref offset, AssemblyProcessorRow.FromReader), CreateNextTable(TableIndex.AssemblyOS, ref offset, AssemblyOSRow.FromReader), CreateNextTable(TableIndex.AssemblyRef, ref offset, AssemblyReferenceRow.FromReader), CreateNextTable(TableIndex.AssemblyRefProcessor, ref offset, AssemblyRefProcessorRow.FromReader), CreateNextTable(TableIndex.AssemblyRefOS, ref offset, AssemblyRefOSRow.FromReader), CreateNextTable(TableIndex.File, ref offset, FileReferenceRow.FromReader), CreateNextTable(TableIndex.ExportedType, ref offset, ExportedTypeRow.FromReader), CreateNextTable(TableIndex.ManifestResource, ref offset, ManifestResourceRow.FromReader), CreateNextTable(TableIndex.NestedClass, ref offset, NestedClassRow.FromReader), CreateNextTable(TableIndex.GenericParam, ref offset, GenericParameterRow.FromReader), CreateNextTable(TableIndex.MethodSpec, ref offset, MethodSpecificationRow.FromReader), CreateNextTable(TableIndex.GenericParamConstraint, ref offset, GenericParameterConstraintRow.FromReader), null, null, null, CreateNextTable(TableIndex.Document, ref offset, DocumentRow.FromReader), CreateNextTable(TableIndex.MethodDebugInformation, ref offset, MethodDebugInformationRow.FromReader), CreateNextTable(TableIndex.LocalScope, ref offset, LocalScopeRow.FromReader), CreateNextTable(TableIndex.LocalVariable, ref offset, LocalVariableRow.FromReader), CreateNextTable(TableIndex.LocalConstant, ref offset, LocalConstantRow.FromReader), CreateNextTable(TableIndex.ImportScope, ref offset, ImportScopeRow.FromReader), CreateNextTable(TableIndex.StateMachineMethod, ref offset, StateMachineMethodRow.FromReader), CreateNextTable(TableIndex.CustomDebugInformation, ref offset, CustomDebugInformationRow.FromReader) }; _tablesInitialized = true; return result; } private BinaryStreamReader CreateNextRawTableReader(TableIndex currentIndex, ref uint currentOffset) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) uint num = base.TableLayouts[(int)currentIndex].RowSize * _rowCounts[(uint)currentIndex]; BinaryStreamReader result = ((BinaryStreamReader)(ref _reader)).ForkRelative(currentOffset, num); currentOffset += num; return result; } private SerializedMetadataTable CreateNextTable(TableIndex index, ref uint offset, SerializedMetadataTable.ReadRowDelegate readRow) where TRow : struct, IMetadataRow { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader reader = CreateNextRawTableReader(index, ref offset); return new SerializedMetadataTable(in reader, index, base.TableLayouts[(int)index], TablesStream.IsSorted(_sortedMask, index), readRow); } private SerializedMetadataTable CreateNextTable(TableIndex index, ref uint offset, SerializedMetadataTable.ReadRowExtendedDelegate readRow) where TRow : struct, IMetadataRow { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) MetadataReaderContext context = _context; BinaryStreamReader reader = CreateNextRawTableReader(index, ref offset); return new SerializedMetadataTable(context, in reader, index, base.TableLayouts[(int)index], TablesStream.IsSorted(_sortedMask, index), readRow); } } public class SerializedUserStringsStream : UserStringsStream { private readonly ConcurrentDictionary _cachedStrings = new ConcurrentDictionary(); private readonly BinaryStreamReader _reader; public override bool CanRead => true; public SerializedUserStringsStream(byte[] rawData) : this("#US", new BinaryStreamReader(rawData)) { }//IL_0007: Unknown result type (might be due to invalid IL or missing references) public SerializedUserStringsStream(string name, byte[] rawData) : this(name, new BinaryStreamReader(rawData)) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public SerializedUserStringsStream(string name, BinaryStreamReader reader) : base(name) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref reader)).Rva; } public override BinaryStreamReader CreateReader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((BinaryStreamReader)(ref _reader)).Fork(); } public override uint GetPhysicalSize() { return ((BinaryStreamReader)(ref _reader)).Length; } public override void Write(BinaryStreamWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); ((BinaryStreamReader)(ref val)).WriteToOutput(writer); } public override string? GetStringByIndex(uint index) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) index &= 0xFFFFFFu; if (!_cachedStrings.TryGetValue(index, out string value) && index < ((BinaryStreamReader)(ref _reader)).Length) { BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).ForkRelative(index); uint num = default(uint); if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num)) { if (num == 0) { return string.Empty; } byte[] array = new byte[num]; int num2 = ((BinaryStreamReader)(ref val)).ReadBytes(array, 0, (int)num); value = Encoding.Unicode.GetString(array, 0, num2 - 1); } _cachedStrings.TryAdd(index, value); } return value; } public override bool TryFindStringIndex(string value, out uint index) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (value == string.Empty) { index = 0u; return true; } uint num = (uint)(value.Length * 2 + 1); uint num2 = Extensions.GetCompressedSize(num) + num; BinaryStreamReader val = ((BinaryStreamReader)(ref _reader)).Fork(); uint num3 = default(uint); while (((BinaryStreamReader)(ref val)).CanRead(num2)) { index = ((BinaryStreamReader)(ref val)).RelativeOffset; if (((BinaryStreamReader)(ref val)).TryReadCompressedUInt32(ref num3) && num3 == num && ((BinaryStreamReader)(ref val)).CanRead(num3)) { int i; for (i = 0; i < value.Length && value[i] == ((BinaryStreamReader)(ref val)).ReadUInt16(); i++) { } bool flag = i == value.Length && ((BinaryStreamReader)(ref val)).CanRead(1u); if (flag) { byte b = ((BinaryStreamReader)(ref val)).ReadByte(); bool flag2 = (uint)b <= 1u; flag = flag2; } if (flag) { return true; } } ((BinaryStreamReader)(ref val)).RelativeOffset = index + 1; } index = 0u; return false; } } public abstract class StringsStream : MetadataHeap { public const string DefaultName = "#Strings"; protected StringsStream() : base("#Strings") { } protected StringsStream(string name) : base(name) { } public abstract Utf8String? GetStringByIndex(uint index); public abstract bool TryFindStringIndex(Utf8String? value, out uint index); } public class TablesStream : SegmentBase, IMetadataStream, ISegment, IOffsetProvider, IWritable { public const string CompressedStreamName = "#~"; public const string EncStreamName = "#-"; public const string MinimalStreamName = "#JTD"; public const string UncompressedStreamName = "#Schema"; private readonly Dictionary _indexEncoders; private readonly LazyVariable> _tables; private readonly LazyVariable> _layouts; public string Name { get; set; } = "#~"; public virtual bool CanRead => false; public uint Reserved { get; set; } public byte MajorVersion { get; set; } = 2; public byte MinorVersion { get; set; } public TablesStreamFlags Flags { get; set; } public IndexSize StringIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(0); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(0, value); } } public IndexSize GuidIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(1); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(1, value); } } public IndexSize BlobIndexSize { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return GetStreamIndexSize(2); } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) SetStreamIndexSize(2, value); } } public bool HasPaddingBit { get { return (Flags & TablesStreamFlags.LongBlobIndices) != 0; } set { Flags = (Flags & ~TablesStreamFlags.LongBlobIndices) | (value ? TablesStreamFlags.LongBlobIndices : ((TablesStreamFlags)0)); } } public bool HasDeltaOnly { get { return (Flags & TablesStreamFlags.DeltaOnly) != 0; } set { Flags = (Flags & ~TablesStreamFlags.DeltaOnly) | (value ? TablesStreamFlags.DeltaOnly : ((TablesStreamFlags)0)); } } public bool HasExtraData { get { return (Flags & TablesStreamFlags.ExtraData) != 0; } set { Flags = (Flags & ~TablesStreamFlags.ExtraData) | (value ? TablesStreamFlags.ExtraData : ((TablesStreamFlags)0)); } } public bool HasDeletedTokens { get { return (Flags & TablesStreamFlags.HasDelete) != 0; } set { Flags = (Flags & ~TablesStreamFlags.HasDelete) | (value ? TablesStreamFlags.HasDelete : ((TablesStreamFlags)0)); } } public byte Log2LargestRid { get; protected set; } = 1; public uint ExtraData { get; set; } [MemberNotNullWhen(true, "ExternalRowCounts")] public bool HasExternalRowCounts { [MemberNotNullWhen(true, "ExternalRowCounts")] get { return ExternalRowCounts != null; } } public uint[]? ExternalRowCounts { get; set; } public bool ForceLargeColumns { get; set; } protected IList Tables => _tables.GetValue(this); protected IList TableLayouts => _layouts.GetValue(this); public TablesStream() { _layouts = new LazyVariable>((Func>)((TablesStream x) => x.GetTableLayouts())); _tables = new LazyVariable>((Func>)((TablesStream x) => x.GetTables())); _indexEncoders = CreateIndexEncoders(); } public virtual BinaryStreamReader CreateReader() { throw new NotSupportedException(); } public uint GetTableRowCount(TableIndex table) { if (!HasExternalRowCounts || (int)table >= ExternalRowCounts.Length) { return (uint)GetTable(table).Count; } return ExternalRowCounts[(uint)table]; } public IndexSize GetTableIndexSize(TableIndex table) { if (!ForceLargeColumns) { if (GetTableRowCount(table) > 65535) { return (IndexSize)4; } return (IndexSize)2; } return (IndexSize)4; } protected void SynchronizeTableLayoutsWithFlags() { TableLayout[] tableLayouts = GetTableLayouts(); for (int i = 0; i < Tables.Count; i++) { Tables[i]?.UpdateTableLayout(tableLayouts[i]); } } public override uint GetPhysicalSize() { SynchronizeTableLayoutsWithFlags(); ulong validBitmask = ComputeValidBitmask(); return (uint)((int)(24 + GetTablesCount(validBitmask) * 4 + (HasExtraData ? 8 : 0) + GetTablesSize(validBitmask)) + 4); } public override void Write(BinaryStreamWriter writer) { SynchronizeTableLayoutsWithFlags(); writer.WriteUInt32(Reserved); writer.WriteByte(MajorVersion); writer.WriteByte(MinorVersion); writer.WriteByte((byte)Flags); writer.WriteByte(Log2LargestRid); ulong num = ComputeValidBitmask(); writer.WriteUInt64(num); writer.WriteUInt64(ComputeSortedBitmask()); WriteRowCounts(writer, num); if (HasExtraData) { writer.WriteUInt32(ExtraData); } WriteTables(writer, num); writer.WriteUInt32(0u); } protected virtual ulong ComputeValidBitmask() { ulong num = 0uL; for (int i = 0; i < Tables.Count; i++) { IMetadataTable? metadataTable = Tables[i]; if (metadataTable != null && metadataTable.Count > 0) { num |= (ulong)(1L << i); } } return num; } protected virtual ulong ComputeSortedBitmask() { ulong num = 0uL; bool flag = false; bool flag2 = false; for (int i = 0; i < Tables.Count; i++) { IMetadataTable metadataTable = Tables[i]; if (metadataTable == null) { continue; } if (metadataTable.IsSorted) { num |= (ulong)(1L << i); } if (metadataTable.Count > 0) { if (i <= 44) { flag = true; } else { flag2 = true; } } } if (!flag) { num &= 0xFFFFE00000000000uL; } if (!flag2) { num &= 0xFF001FFFFFFFFFFFuL; } return num; } protected virtual int GetTablesCount(ulong validBitmask) { int num = 0; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < 56) { if (HasTable(validBitmask, tableIndex)) { num++; } tableIndex++; } return num; } protected virtual uint GetTablesSize(ulong validBitmask) { long num = 0L; TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < (int)(byte)Tables.Count) { if (HasTable(validBitmask, tableIndex)) { IMetadataTable table = GetTable(tableIndex); num += table.Count * table.Layout.RowSize; } tableIndex++; } return (uint)num; } protected virtual void WriteRowCounts(BinaryStreamWriter writer, ulong validBitmask) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex <= 56) { if (HasTable(validBitmask, tableIndex)) { writer.WriteInt32(GetTable(tableIndex).Count); } tableIndex++; } } protected virtual void WriteTables(BinaryStreamWriter writer, ulong validBitmask) { TableIndex tableIndex = TableIndex.Module; while ((int)tableIndex < (int)(byte)Tables.Count) { if (HasTable(validBitmask, tableIndex)) { GetTable(tableIndex).Write(writer); } tableIndex++; } } protected static bool HasTable(ulong validMask, TableIndex table) { return ((validMask >> (int)table) & 1) != 0; } protected static bool IsSorted(ulong sortedMask, TableIndex table) { return ((sortedMask >> (int)table) & 1) != 0; } public virtual IMetadataTable GetTable(TableIndex index) { return Tables[(int)index] ?? throw new ArgumentOutOfRangeException("index"); } public virtual MetadataTable GetTable() where TRow : struct, IMetadataRow { return Tables.OfType>().First(); } public virtual MetadataTable GetTable(TableIndex index) where TRow : struct, IMetadataRow { return (MetadataTable)(Tables[(int)index] ?? throw new ArgumentOutOfRangeException("index")); } private IndexSize GetStreamIndexSize(int bitIndex) { if (!ForceLargeColumns) { return (IndexSize)(((((int)Flags >> bitIndex) & 1) + 1) * 2); } return (IndexSize)4; } private void SetStreamIndexSize(int bitIndex, IndexSize newSize) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 Flags = (TablesStreamFlags)(((uint)Flags & (uint)(~(1 << bitIndex))) | (((int)newSize == 4) ? ((uint)(1 << bitIndex)) : 0u)); } protected virtual uint GetColumnSize(ColumnType columnType) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected I4, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected I4, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected I4, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown if (_layouts.IsInitialized) { if (columnType <= ColumnType.CustomDebugInformation) { return (uint)(int)GetTableIndexSize((TableIndex)columnType); } if (columnType <= ColumnType.HasCustomDebugInformation) { return (uint)(int)GetIndexEncoder((CodedIndex)columnType).IndexSize; } } return columnType switch { ColumnType.Blob => (uint)(int)BlobIndexSize, ColumnType.String => (uint)(int)StringIndexSize, ColumnType.Guid => (uint)(int)GuidIndexSize, ColumnType.Byte => 1u, ColumnType.UInt16 => 2u, ColumnType.UInt32 => 4u, _ => 4u, }; } public IndexEncoder GetIndexEncoder(CodedIndex index) { return _indexEncoders[index]; } public MetadataRange GetFieldRange(uint typeDefRid) { return GetMemberRange(TableIndex.TypeDef, typeDefRid, 4, TableIndex.Field, TableIndex.FieldPtr); } public MetadataRange GetMethodRange(uint typeDefRid) { return GetMemberRange(TableIndex.TypeDef, typeDefRid, 5, TableIndex.Method, TableIndex.MethodPtr); } public MetadataRange GetParameterRange(uint methodDefRid) { return GetMemberRange(TableIndex.Method, methodDefRid, 5, TableIndex.Param, TableIndex.ParamPtr); } public MetadataRange GetPropertyRange(uint propertyMapRid) { return GetMemberRange(TableIndex.PropertyMap, propertyMapRid, 1, TableIndex.Property, TableIndex.PropertyPtr); } public MetadataRange GetEventRange(uint eventMapRid) { return GetMemberRange(TableIndex.EventMap, eventMapRid, 1, TableIndex.Event, TableIndex.EventPtr); } private MetadataRange GetMemberRange(TableIndex ownerTableIndex, uint ownerRid, int ownerColumnIndex, TableIndex memberTableIndex, TableIndex redirectTableIndex) where TOwnerRow : struct, IMetadataRow { int num = (int)(ownerRid - 1); MetadataTable table = GetTable(ownerTableIndex); if (num < 0 || num >= table.Count) { return MetadataRange.Empty; } uint startRid = table[num][ownerColumnIndex]; uint endRid = ((num < table.Count - 1) ? table[num + 1][ownerColumnIndex] : ((uint)(GetTable(memberTableIndex).Count + 1))); IMetadataTable table2 = GetTable(redirectTableIndex); if (table2.Count > 0) { return new MetadataRange(table2, memberTableIndex, startRid, endRid); } return new MetadataRange(memberTableIndex, startRid, endRid); } protected virtual IList GetTables() { IList tableLayouts = TableLayouts; return new IMetadataTable[56] { new MetadataTable(TableIndex.Module, tableLayouts[0]), new MetadataTable(TableIndex.TypeRef, tableLayouts[1]), new MetadataTable(TableIndex.TypeDef, tableLayouts[2]), new MetadataTable(TableIndex.FieldPtr, tableLayouts[3]), new MetadataTable(TableIndex.Field, tableLayouts[4]), new MetadataTable(TableIndex.Method, tableLayouts[5]), new MetadataTable(TableIndex.Method, tableLayouts[6]), new MetadataTable(TableIndex.ParamPtr, tableLayouts[7]), new MetadataTable(TableIndex.Param, tableLayouts[8]), new MetadataTable(TableIndex.InterfaceImpl, tableLayouts[9], isSorted: true), new MetadataTable(TableIndex.MemberRef, tableLayouts[10]), new MetadataTable(TableIndex.Constant, tableLayouts[11], isSorted: true), new MetadataTable(TableIndex.CustomAttribute, tableLayouts[12], isSorted: true), new MetadataTable(TableIndex.FieldMarshal, tableLayouts[13], isSorted: true), new MetadataTable(TableIndex.DeclSecurity, tableLayouts[14], isSorted: true), new MetadataTable(TableIndex.ClassLayout, tableLayouts[15], isSorted: true), new MetadataTable(TableIndex.FieldLayout, tableLayouts[16], isSorted: true), new MetadataTable(TableIndex.StandAloneSig, tableLayouts[17]), new MetadataTable(TableIndex.EventMap, tableLayouts[18]), new MetadataTable(TableIndex.EventPtr, tableLayouts[19]), new MetadataTable(TableIndex.Event, tableLayouts[20]), new MetadataTable(TableIndex.PropertyMap, tableLayouts[21]), new MetadataTable(TableIndex.PropertyPtr, tableLayouts[22]), new MetadataTable(TableIndex.Property, tableLayouts[23]), new MetadataTable(TableIndex.MethodSemantics, tableLayouts[24], isSorted: true), new MetadataTable(TableIndex.MethodImpl, tableLayouts[25], isSorted: true), new MetadataTable(TableIndex.ModuleRef, tableLayouts[26]), new MetadataTable(TableIndex.TypeSpec, tableLayouts[27]), new MetadataTable(TableIndex.ImplMap, tableLayouts[28], isSorted: true), new MetadataTable(TableIndex.FieldRva, tableLayouts[29], isSorted: true), new MetadataTable(TableIndex.EncLog, tableLayouts[30]), new MetadataTable(TableIndex.EncMap, tableLayouts[31]), new MetadataTable(TableIndex.Assembly, tableLayouts[32]), new MetadataTable(TableIndex.AssemblyProcessor, tableLayouts[33]), new MetadataTable(TableIndex.AssemblyOS, tableLayouts[34]), new MetadataTable(TableIndex.AssemblyRef, tableLayouts[35]), new MetadataTable(TableIndex.AssemblyRefProcessor, tableLayouts[36]), new MetadataTable(TableIndex.AssemblyRefProcessor, tableLayouts[37]), new MetadataTable(TableIndex.File, tableLayouts[38]), new MetadataTable(TableIndex.ExportedType, tableLayouts[39]), new MetadataTable(TableIndex.ManifestResource, tableLayouts[40]), new MetadataTable(TableIndex.NestedClass, tableLayouts[41], isSorted: true), new MetadataTable(TableIndex.GenericParam, tableLayouts[42], isSorted: true), new MetadataTable(TableIndex.MethodSpec, tableLayouts[43]), new MetadataTable(TableIndex.GenericParamConstraint, tableLayouts[44], isSorted: true), null, null, null, new MetadataTable(TableIndex.Document, tableLayouts[48]), new MetadataTable(TableIndex.MethodDebugInformation, tableLayouts[49]), new MetadataTable(TableIndex.LocalScope, tableLayouts[50], isSorted: true), new MetadataTable(TableIndex.LocalVariable, tableLayouts[51]), new MetadataTable(TableIndex.LocalConstant, tableLayouts[52]), new MetadataTable(TableIndex.ImportScope, tableLayouts[53]), new MetadataTable(TableIndex.StateMachineMethod, tableLayouts[54]), new MetadataTable(TableIndex.CustomDebugInformation, tableLayouts[55], isSorted: true) }; } private Dictionary CreateIndexEncoders() { Dictionary dictionary = new Dictionary(); dictionary[CodedIndex.TypeDefOrRef] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.TypeSpec); dictionary[CodedIndex.HasConstant] = new IndexEncoder(this, TableIndex.Field, TableIndex.Param, TableIndex.Property); dictionary[CodedIndex.HasCustomAttribute] = new IndexEncoder(this, TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec); dictionary[CodedIndex.HasFieldMarshal] = new IndexEncoder(this, TableIndex.Field, TableIndex.Param); dictionary[CodedIndex.HasDeclSecurity] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.Method, TableIndex.Assembly); dictionary[CodedIndex.MemberRefParent] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.TypeRef, TableIndex.ModuleRef, TableIndex.Method, TableIndex.TypeSpec); dictionary[CodedIndex.HasSemantics] = new IndexEncoder(this, TableIndex.Event, TableIndex.Property); dictionary[CodedIndex.MethodDefOrRef] = new IndexEncoder(this, TableIndex.Method, TableIndex.MemberRef); dictionary[CodedIndex.MemberForwarded] = new IndexEncoder(this, TableIndex.Field, TableIndex.Method); dictionary[CodedIndex.Implementation] = new IndexEncoder(this, TableIndex.File, TableIndex.AssemblyRef, TableIndex.ExportedType); dictionary[CodedIndex.CustomAttributeType] = new IndexEncoder(this, TableIndex.Module, TableIndex.Module, TableIndex.Method, TableIndex.MemberRef, TableIndex.Module); dictionary[CodedIndex.ResolutionScope] = new IndexEncoder(this, TableIndex.Module, TableIndex.ModuleRef, TableIndex.AssemblyRef, TableIndex.TypeRef); dictionary[CodedIndex.TypeOrMethodDef] = new IndexEncoder(this, TableIndex.TypeDef, TableIndex.Method); dictionary[CodedIndex.HasCustomDebugInformation] = new IndexEncoder(this, TableIndex.Method, TableIndex.Field, TableIndex.TypeRef, TableIndex.TypeDef, TableIndex.Param, TableIndex.InterfaceImpl, TableIndex.MemberRef, TableIndex.Module, TableIndex.DeclSecurity, TableIndex.Property, TableIndex.Event, TableIndex.StandAloneSig, TableIndex.ModuleRef, TableIndex.TypeSpec, TableIndex.Assembly, TableIndex.AssemblyRef, TableIndex.File, TableIndex.ExportedType, TableIndex.ManifestResource, TableIndex.GenericParam, TableIndex.GenericParamConstraint, TableIndex.MethodSpec, TableIndex.Document, TableIndex.LocalScope, TableIndex.LocalVariable, TableIndex.LocalConstant, TableIndex.ImportScope); return dictionary; } protected TableLayout[] GetTableLayouts() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_0637: Unknown result type (might be due to invalid IL or missing references) //IL_06ee: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07d9: Unknown result type (might be due to invalid IL or missing references) //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_08f0: Unknown result type (might be due to invalid IL or missing references) //IL_094d: Unknown result type (might be due to invalid IL or missing references) //IL_0ac3: Unknown result type (might be due to invalid IL or missing references) //IL_0adc: Unknown result type (might be due to invalid IL or missing references) //IL_0af5: Unknown result type (might be due to invalid IL or missing references) //IL_0c0e: Unknown result type (might be due to invalid IL or missing references) //IL_0c27: Unknown result type (might be due to invalid IL or missing references) //IL_0c40: Unknown result type (might be due to invalid IL or missing references) //IL_0c59: Unknown result type (might be due to invalid IL or missing references) //IL_0d4f: Unknown result type (might be due to invalid IL or missing references) //IL_0d68: Unknown result type (might be due to invalid IL or missing references) //IL_0dc0: Unknown result type (might be due to invalid IL or missing references) //IL_0dd9: Unknown result type (might be due to invalid IL or missing references) //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_0f1f: Unknown result type (might be due to invalid IL or missing references) //IL_0f65: Unknown result type (might be due to invalid IL or missing references) //IL_0fda: Unknown result type (might be due to invalid IL or missing references) //IL_0ff3: Unknown result type (might be due to invalid IL or missing references) //IL_100c: Unknown result type (might be due to invalid IL or missing references) //IL_1025: Unknown result type (might be due to invalid IL or missing references) //IL_106c: Unknown result type (might be due to invalid IL or missing references) //IL_116d: Unknown result type (might be due to invalid IL or missing references) //IL_1199: Unknown result type (might be due to invalid IL or missing references) //IL_11b2: Unknown result type (might be due to invalid IL or missing references) //IL_11f9: Unknown result type (might be due to invalid IL or missing references) //IL_1285: Unknown result type (might be due to invalid IL or missing references) //IL_129e: Unknown result type (might be due to invalid IL or missing references) return new TableLayout[56] { new TableLayout(new ColumnLayout("Generation", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Mvid", ColumnType.Guid, GuidIndexSize), new ColumnLayout("EncId", ColumnType.Guid, GuidIndexSize), new ColumnLayout("EncBaseId", ColumnType.Guid, GuidIndexSize)), new TableLayout(new ColumnLayout("ResolutionScope", ColumnType.ResolutionScope, GetColumnSize(ColumnType.ResolutionScope)), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.Guid, StringIndexSize)), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.String, StringIndexSize), new ColumnLayout("Extends", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef)), new ColumnLayout("FieldList", ColumnType.Field, GetColumnSize(ColumnType.Field)), new ColumnLayout("MethodList", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("Field", ColumnType.Field, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("RVA", ColumnType.UInt32), new ColumnLayout("ImplFlags", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize), new ColumnLayout("ParamList", ColumnType.Param, GetColumnSize(ColumnType.Param))), new TableLayout(new ColumnLayout("Parameter", ColumnType.Param, GetColumnSize(ColumnType.Param))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Sequence", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Class", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("Interface", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), new TableLayout(new ColumnLayout("Parent", ColumnType.MemberRefParent, GetColumnSize(ColumnType.MemberRefParent)), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Type", ColumnType.Byte), new ColumnLayout("Padding", ColumnType.Byte), new ColumnLayout("Parent", ColumnType.HasConstant, GetColumnSize(ColumnType.HasConstant)), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.HasCustomAttribute, GetColumnSize(ColumnType.HasCustomAttribute)), new ColumnLayout("Type", ColumnType.CustomAttributeType, GetColumnSize(ColumnType.CustomAttributeType)), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.HasFieldMarshal, GetColumnSize(ColumnType.HasFieldMarshal)), new ColumnLayout("NativeType", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Action", ColumnType.UInt16), new ColumnLayout("Parent", ColumnType.HasDeclSecurity, GetColumnSize(ColumnType.HasDeclSecurity)), new ColumnLayout("PermissionSet", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("PackingSize", ColumnType.UInt16), new ColumnLayout("ClassSize", ColumnType.UInt32), new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef))), new TableLayout(new ColumnLayout("Offset", ColumnType.UInt32), new ColumnLayout("Field", ColumnType.TypeDef, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("EventList", ColumnType.Event, GetColumnSize(ColumnType.Event))), new TableLayout(new ColumnLayout("Event", ColumnType.Event, GetColumnSize(ColumnType.Event))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("EventType", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), new TableLayout(new ColumnLayout("Parent", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("PropertyList", ColumnType.Event, GetColumnSize(ColumnType.Property))), new TableLayout(new ColumnLayout("Property", ColumnType.Property, GetColumnSize(ColumnType.Property))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("PropertyType", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Semantic", ColumnType.UInt16), new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("Association", ColumnType.HasSemantics, GetColumnSize(ColumnType.HasSemantics))), new TableLayout(new ColumnLayout("Class", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("MethodBody", ColumnType.MethodDefOrRef, GetColumnSize(ColumnType.MethodDefOrRef)), new ColumnLayout("MethodDeclaration", ColumnType.MethodDefOrRef, GetColumnSize(ColumnType.MethodDefOrRef))), new TableLayout(new ColumnLayout("Name", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("MappingFlags", ColumnType.UInt16), new ColumnLayout("MemberForwarded", ColumnType.MemberForwarded, GetColumnSize(ColumnType.MemberForwarded)), new ColumnLayout("ImportName", ColumnType.String, StringIndexSize), new ColumnLayout("ImportScope", ColumnType.ModuleRef, GetColumnSize(ColumnType.ModuleRef))), new TableLayout(new ColumnLayout("RVA", ColumnType.UInt32), new ColumnLayout("Field", ColumnType.Field, GetColumnSize(ColumnType.Field))), new TableLayout(new ColumnLayout("Token", ColumnType.UInt32), new ColumnLayout("FuncCode", ColumnType.UInt32)), new TableLayout(new ColumnLayout("Token", ColumnType.UInt32)), new TableLayout(new ColumnLayout("HashAlgId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt16), new ColumnLayout("MinorVersion", ColumnType.UInt16), new ColumnLayout("BuildNumber", ColumnType.UInt16), new ColumnLayout("RevisionNumber", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("PublicKey", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Culture", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Processor", ColumnType.UInt32)), new TableLayout(new ColumnLayout("PlatformId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt32), new ColumnLayout("MinorVersion", ColumnType.UInt32)), new TableLayout(new ColumnLayout("MajorVersion", ColumnType.UInt16), new ColumnLayout("MinorVersion", ColumnType.UInt16), new ColumnLayout("BuildNumber", ColumnType.UInt16), new ColumnLayout("RevisionNumber", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("PublicKeyOrToken", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Culture", ColumnType.String, StringIndexSize), new ColumnLayout("HashValue", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Processor", ColumnType.UInt32), new ColumnLayout("AssemblyRef", ColumnType.AssemblyRef, GetColumnSize(ColumnType.AssemblyRef))), new TableLayout(new ColumnLayout("PlatformId", ColumnType.UInt32), new ColumnLayout("MajorVersion", ColumnType.UInt32), new ColumnLayout("MinorVersion", ColumnType.UInt32), new ColumnLayout("AssemblyRef", ColumnType.AssemblyRef, GetColumnSize(ColumnType.AssemblyRef))), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("HashValue", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("TypeDefId", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Namespace", ColumnType.String, StringIndexSize), new ColumnLayout("Implementation", ColumnType.Implementation, GetColumnSize(ColumnType.Implementation))), new TableLayout(new ColumnLayout("Offset", ColumnType.UInt32), new ColumnLayout("Flags", ColumnType.UInt32), new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Implementation", ColumnType.Implementation, GetColumnSize(ColumnType.Implementation))), new TableLayout(new ColumnLayout("NestedClass", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef)), new ColumnLayout("EnclosingClass", ColumnType.TypeDef, GetColumnSize(ColumnType.TypeDef))), new TableLayout(new ColumnLayout("Number", ColumnType.UInt16), new ColumnLayout("Flags", ColumnType.UInt16), new ColumnLayout("Owner", ColumnType.TypeOrMethodDef, GetColumnSize(ColumnType.TypeOrMethodDef)), new ColumnLayout("EnclosingClass", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.MethodDefOrRef)), new ColumnLayout("Instantiation", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Owner", ColumnType.GenericParam, GetColumnSize(ColumnType.GenericParam)), new ColumnLayout("Constraint", ColumnType.TypeDefOrRef, GetColumnSize(ColumnType.TypeDefOrRef))), default(TableLayout), default(TableLayout), default(TableLayout), new TableLayout(new ColumnLayout("Name", ColumnType.Blob, BlobIndexSize), new ColumnLayout("HashAlgorithm", ColumnType.Guid, GuidIndexSize), new ColumnLayout("Hash", ColumnType.Blob, BlobIndexSize), new ColumnLayout("Language", ColumnType.Guid, GuidIndexSize)), new TableLayout(new ColumnLayout("Document", ColumnType.Document, GetColumnSize(ColumnType.Document)), new ColumnLayout("SequencePoints", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Method", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("ImportScope", ColumnType.ImportScope, GetColumnSize(ColumnType.ImportScope)), new ColumnLayout("VariableList", ColumnType.LocalVariable, GetColumnSize(ColumnType.LocalVariable)), new ColumnLayout("ConstantList", ColumnType.LocalConstant, GetColumnSize(ColumnType.LocalConstant)), new ColumnLayout("StartOffset", ColumnType.UInt32), new ColumnLayout("Length", ColumnType.UInt32)), new TableLayout(new ColumnLayout("Attributes", ColumnType.UInt16), new ColumnLayout("Index", ColumnType.UInt16), new ColumnLayout("VariableList", ColumnType.String, StringIndexSize)), new TableLayout(new ColumnLayout("Name", ColumnType.String, StringIndexSize), new ColumnLayout("Signature", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("Parent", ColumnType.ImportScope, GetColumnSize(ColumnType.ImportScope)), new ColumnLayout("Imports", ColumnType.Blob, BlobIndexSize)), new TableLayout(new ColumnLayout("MoveNextMethod", ColumnType.Method, GetColumnSize(ColumnType.Method)), new ColumnLayout("KickoffMethod", ColumnType.Method, GetColumnSize(ColumnType.Method))), new TableLayout(new ColumnLayout("Parent", ColumnType.HasCustomDebugInformation, GetColumnSize(ColumnType.HasCustomDebugInformation)), new ColumnLayout("Kind", ColumnType.Guid, GuidIndexSize), new ColumnLayout("Value", ColumnType.Blob, BlobIndexSize)) }; } } [Flags] public enum TablesStreamFlags : byte { LongStringIndices = 1, LongGuidIndices = 2, LongBlobIndices = 4, PaddingBit = 8, DeltaOnly = 0x20, ExtraData = 0x40, HasDelete = 0x80 } public abstract class UserStringsStream : MetadataHeap { public const string DefaultName = "#US"; protected UserStringsStream() : base("#US") { } protected UserStringsStream(string name) : base(name) { } public abstract string? GetStringByIndex(uint index); public abstract bool TryFindStringIndex(string value, out uint index); public bool TryFindStringToken(string value, out MetadataToken token) { if (TryFindStringIndex(value, out var index)) { token = new MetadataToken(TableIndex.String, index); return true; } token = MetadataToken.Zero; return false; } } } namespace AsmResolver.PE.DotNet.Metadata.Tables { [Flags] public enum AssemblyAttributes : uint { PublicKey = 1u, ArchitectureNone = 0u, ArchitectureMsil = 0x10u, ArchitectureX86 = 0x20u, ArchitectureIa64 = 0x30u, ArchitectureAmd64 = 0x40u, ArchitectureMask = 0x70u, Specified = 0x80u, FullMask = 0xF0u, EnableJitCompileTracking = 0x8000u, DisableJitCompileOptimizer = 0x4000u, Retargetable = 0x100u, ContentDefault = 0u, ContentWindowsRuntime = 0x200u, ContentMask = 0xE00u } public struct AssemblyDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Assembly; public int Count => 9; public uint this[int index] => index switch { 0 => (uint)HashAlgorithm, 1 => MajorVersion, 2 => MinorVersion, 3 => BuildNumber, 4 => RevisionNumber, 5 => (uint)Attributes, 6 => PublicKey, 7 => Name, 8 => Culture, _ => throw new IndexOutOfRangeException(), }; public AssemblyHashAlgorithm HashAlgorithm { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public ushort BuildNumber { get; set; } public ushort RevisionNumber { get; set; } public AssemblyAttributes Attributes { get; set; } public uint PublicKey { get; set; } public uint Name { get; set; } public uint Culture { get; set; } public static AssemblyDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyDefinitionRow((AssemblyHashAlgorithm)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), (AssemblyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[6].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[7].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[8].Size)); } public AssemblyDefinitionRow(AssemblyHashAlgorithm hashAlgorithm, ushort majorVersion, ushort minorVersion, ushort buildNumber, ushort revisionNumber, AssemblyAttributes attributes, uint publicKey, uint name, uint culture) { HashAlgorithm = hashAlgorithm; MajorVersion = majorVersion; MinorVersion = minorVersion; BuildNumber = buildNumber; RevisionNumber = revisionNumber; Attributes = attributes; PublicKey = publicKey; Name = name; Culture = culture; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)HashAlgorithm); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt16(BuildNumber); writer.WriteUInt16(RevisionNumber); writer.WriteUInt32((uint)Attributes); writer.WriteIndex(PublicKey, (IndexSize)layout.Columns[6].Size); writer.WriteIndex(Name, (IndexSize)layout.Columns[7].Size); writer.WriteIndex(Culture, (IndexSize)layout.Columns[8].Size); } public bool Equals(AssemblyDefinitionRow other) { if (HashAlgorithm == other.HashAlgorithm && MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion && BuildNumber == other.BuildNumber && RevisionNumber == other.RevisionNumber && Attributes == other.Attributes && PublicKey == other.PublicKey && Name == other.Name) { return Culture == other.Culture; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)((((((((((int)HashAlgorithm * 397) ^ MajorVersion.GetHashCode()) * 397) ^ MinorVersion.GetHashCode()) * 397) ^ BuildNumber.GetHashCode()) * 397) ^ RevisionNumber.GetHashCode()) * 397) ^ (uint)Attributes) * 397) ^ PublicKey) * 397) ^ Name) * 397) ^ Culture); } public override string ToString() { return $"({HashAlgorithm:X8}, {MajorVersion:X4}, {MinorVersion:X4}, {BuildNumber:X4}, {RevisionNumber:X4}, {Attributes:X8}, {PublicKey:X8}, {Name:X8}, {Culture:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum AssemblyHashAlgorithm : uint { None = 0u, Md2 = 32769u, Md4 = 32770u, Md5 = 32771u, Sha1 = 32772u, Mac = 32773u, Ripemd = 32774u, Ripemd160 = 32775u, Ssl3Shamd5 = 32776u, Hmac = 32777u, Tls1Prf = 32778u, HashReplaceOwf = 32779u, Sha256 = 32780u, Sha384 = 32781u, Sha512 = 32782u } public struct AssemblyOSRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyOS; public int Count => 3; public uint this[int index] => index switch { 0 => PlatformId, 1 => MajorVersion, 2 => MinorVersion, _ => throw new IndexOutOfRangeException(), }; public uint PlatformId { get; set; } public uint MajorVersion { get; set; } public uint MinorVersion { get; set; } public static AssemblyOSRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyOSRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32()); } public AssemblyOSRow(uint platformId, uint majorVersion, uint minorVersion) { PlatformId = platformId; MajorVersion = majorVersion; MinorVersion = minorVersion; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(PlatformId); writer.WriteUInt32(MajorVersion); writer.WriteUInt32(MinorVersion); } public bool Equals(AssemblyOSRow other) { if (PlatformId == other.PlatformId && MajorVersion == other.MajorVersion) { return MinorVersion == other.MinorVersion; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyOSRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((PlatformId * 397) ^ MajorVersion) * 397) ^ MinorVersion); } public override string ToString() { return $"({PlatformId:X8}, {MajorVersion:X8}, {MinorVersion:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyProcessorRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyProcessor; public int Count => 1; public uint this[int index] { get { if (index == 0) { return ProcessorId; } throw new IndexOutOfRangeException(); } } public uint ProcessorId { get; set; } public static AssemblyProcessorRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyProcessorRow(((BinaryStreamReader)(ref reader)).ReadUInt32()); } public AssemblyProcessorRow(uint processorId) { ProcessorId = processorId; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(ProcessorId); } public bool Equals(AssemblyProcessorRow other) { return ProcessorId == other.ProcessorId; } public override bool Equals(object? obj) { if (obj is AssemblyProcessorRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)ProcessorId; } public override string ToString() { return $"({ProcessorId:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Assembly; public int Count => 9; public uint this[int index] => index switch { 0 => MajorVersion, 1 => MinorVersion, 2 => BuildNumber, 3 => RevisionNumber, 4 => (uint)Attributes, 5 => PublicKeyOrToken, 6 => Name, 7 => Culture, 8 => HashValue, _ => throw new IndexOutOfRangeException(), }; public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public ushort BuildNumber { get; set; } public ushort RevisionNumber { get; set; } public AssemblyAttributes Attributes { get; set; } public uint PublicKeyOrToken { get; set; } public uint Name { get; set; } public uint Culture { get; set; } public uint HashValue { get; set; } public static AssemblyReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyReferenceRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), (AssemblyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[6].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[7].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[8].Size)); } public AssemblyReferenceRow(ushort majorVersion, ushort minorVersion, ushort buildNumber, ushort revisionNumber, AssemblyAttributes attributes, uint publicKeyOrToken, uint name, uint culture, uint hashValue) { MajorVersion = majorVersion; MinorVersion = minorVersion; BuildNumber = buildNumber; RevisionNumber = revisionNumber; Attributes = attributes; PublicKeyOrToken = publicKeyOrToken; Name = name; Culture = culture; HashValue = hashValue; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt16(BuildNumber); writer.WriteUInt16(RevisionNumber); writer.WriteUInt32((uint)Attributes); writer.WriteIndex(PublicKeyOrToken, (IndexSize)layout.Columns[5].Size); writer.WriteIndex(Name, (IndexSize)layout.Columns[6].Size); writer.WriteIndex(Culture, (IndexSize)layout.Columns[7].Size); writer.WriteIndex(HashValue, (IndexSize)layout.Columns[8].Size); } public bool Equals(AssemblyReferenceRow other) { if (MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion && BuildNumber == other.BuildNumber && RevisionNumber == other.RevisionNumber && Attributes == other.Attributes && PublicKeyOrToken == other.PublicKeyOrToken && Name == other.Name && Culture == other.Culture) { return HashValue == other.HashValue; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((uint)(((((((MajorVersion.GetHashCode() * 397) ^ MinorVersion.GetHashCode()) * 397) ^ BuildNumber.GetHashCode()) * 397) ^ RevisionNumber.GetHashCode()) * 397) ^ (uint)Attributes) * 397) ^ PublicKeyOrToken) * 397) ^ Name) * 397) ^ Culture) * 397) ^ HashValue); } public override string ToString() { return $"({MajorVersion:X4}, {MinorVersion:X4}, {BuildNumber:X4}, {RevisionNumber:X4}, {Attributes:X8}, {PublicKeyOrToken:X8}, {Name:X8}, {Culture:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyRefOSRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyRefOS; public int Count => 4; public uint this[int index] => index switch { 0 => PlatformId, 1 => MajorVersion, 2 => MinorVersion, 3 => AssemblyReference, _ => throw new IndexOutOfRangeException(), }; public uint PlatformId { get; set; } public uint MajorVersion { get; set; } public uint MinorVersion { get; set; } public uint AssemblyReference { get; set; } public static AssemblyRefOSRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyRefOSRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public AssemblyRefOSRow(uint platformId, uint majorVersion, uint minorVersion, uint assemblyReference) { PlatformId = platformId; MajorVersion = majorVersion; MinorVersion = minorVersion; AssemblyReference = assemblyReference; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(PlatformId); writer.WriteUInt32(MajorVersion); writer.WriteUInt32(MinorVersion); writer.WriteIndex(AssemblyReference, (IndexSize)layout.Columns[3].Size); } public bool Equals(AssemblyRefOSRow other) { if (PlatformId == other.PlatformId && MajorVersion == other.MajorVersion && MinorVersion == other.MinorVersion) { return AssemblyReference == other.AssemblyReference; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyRefOSRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((PlatformId * 397) ^ MajorVersion) * 397) ^ MinorVersion) * 397) ^ AssemblyReference); } public override string ToString() { return $"({PlatformId:X8}, {MajorVersion:X8}, {MinorVersion:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct AssemblyRefProcessorRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.AssemblyRefProcessor; public int Count => 2; public uint this[int index] => index switch { 0 => ProcessorId, 1 => AssemblyReference, _ => throw new IndexOutOfRangeException(), }; public uint ProcessorId { get; set; } public uint AssemblyReference { get; set; } public static AssemblyRefProcessorRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new AssemblyRefProcessorRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public AssemblyRefProcessorRow(uint processorId, uint assemblyReference) { ProcessorId = processorId; AssemblyReference = assemblyReference; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(ProcessorId); writer.WriteIndex(AssemblyReference, (IndexSize)layout.Columns[1].Size); } public bool Equals(AssemblyRefProcessorRow other) { if (ProcessorId == other.ProcessorId) { return AssemblyReference == other.AssemblyReference; } return false; } public override bool Equals(object? obj) { if (obj is AssemblyRefProcessorRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((ProcessorId * 397) ^ AssemblyReference); } public override string ToString() { return $"({ProcessorId:X8}, {AssemblyReference:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ClassLayoutRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ClassLayout; public int Count => 3; public uint this[int index] => index switch { 0 => PackingSize, 1 => ClassSize, 2 => Parent, _ => throw new IndexOutOfRangeException(), }; public ushort PackingSize { get; set; } public uint ClassSize { get; set; } public uint Parent { get; set; } public static ClassLayoutRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ClassLayoutRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public ClassLayoutRow(ushort packingSize, uint classSize, uint parent) { PackingSize = packingSize; ClassSize = classSize; Parent = parent; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(PackingSize); writer.WriteUInt32(ClassSize); writer.WriteIndex(Parent, (IndexSize)layout.Columns[2].Size); } public bool Equals(ClassLayoutRow other) { if (PackingSize == other.PackingSize && ClassSize == other.ClassSize) { return Parent == other.Parent; } return false; } public override bool Equals(object? obj) { if (obj is ClassLayoutRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)(PackingSize.GetHashCode() * 397) ^ ClassSize) * 397) ^ Parent); } public override string ToString() { return $"({PackingSize:X4}, {ClassSize:X8}, {Parent:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum CodedIndex { TypeDefOrRef = 56, HasConstant, HasCustomAttribute, HasFieldMarshal, HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef, MemberForwarded, Implementation, CustomAttributeType, ResolutionScope, TypeOrMethodDef, HasCustomDebugInformation } public readonly struct ColumnLayout { public string Name { get; } public ColumnType Type { get; } public uint Size { get; } public ColumnLayout(string name, ColumnType type) { Name = name; Type = type; if (type < ColumnType.Byte) { throw new ArgumentException("Size was not explicitly defined."); } Size = (uint)(type & (ColumnType)255); } public ColumnLayout(string name, ColumnType type, IndexSize size) : this(name, type, (uint)(int)size) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected I4, but got Unknown public ColumnLayout(string name, ColumnType type, uint size) { Name = name; Type = type; Size = size; } public override string ToString() { return $"{Name} : {Type} ({Size} bytes)"; } } public enum ColumnType { Module = 0, TypeRef = 1, TypeDef = 2, FieldPtr = 3, Field = 4, MethodPtr = 5, Method = 6, ParamPtr = 7, Param = 8, InterfaceImpl = 9, MemberRef = 10, Constant = 11, CustomAttribute = 12, FieldMarshal = 13, DeclSecurity = 14, ClassLayout = 15, FieldLayout = 16, StandAloneSig = 17, EventMap = 18, EventPtr = 19, Event = 20, PropertyMap = 21, PropertyPtr = 22, Property = 23, MethodSemantics = 24, MethodImpl = 25, ModuleRef = 26, TypeSpec = 27, ImplMap = 28, FieldRva = 29, EncLog = 30, EncMap = 31, Assembly = 32, AssemblyProcessor = 33, AssemblyOS = 34, AssemblyRef = 35, AssemblyRefProcessor = 36, AssemblyRefOS = 37, File = 38, ExportedType = 39, ManifestResource = 40, NestedClass = 41, GenericParam = 42, MethodSpec = 43, GenericParamConstraint = 44, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55, TypeDefOrRef = 56, HasConstant = 57, HasCustomAttribute = 58, HasFieldMarshal = 59, HasDeclSecurity = 60, MemberRefParent = 61, HasSemantics = 62, MethodDefOrRef = 63, MemberForwarded = 64, Implementation = 65, CustomAttributeType = 66, ResolutionScope = 67, TypeOrMethodDef = 68, HasCustomDebugInformation = 69, String = 70, Blob = 71, Guid = 72, Byte = 134217729, UInt16 = 134217730, UInt32 = 134217732 } public struct ConstantRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Constant; public int Count => 4; public uint this[int index] => index switch { 0 => (uint)Type, 1 => Padding, 2 => Parent, 3 => Value, _ => throw new IndexOutOfRangeException(), }; public ElementType Type { get; } public byte Padding { get; set; } public uint Parent { get; set; } public uint Value { get; set; } public static ConstantRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ConstantRow((ElementType)((BinaryStreamReader)(ref reader)).ReadByte(), ((BinaryStreamReader)(ref reader)).ReadByte(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ConstantRow(ElementType type, uint parent, uint value) { Type = type; Padding = 0; Parent = parent; Value = value; } public ConstantRow(ElementType type, byte padding, uint parent, uint value) { Type = type; Padding = padding; Parent = parent; Value = value; } public bool Equals(ConstantRow other) { if (Type == other.Type && Padding == other.Padding && Parent == other.Parent) { return Value == other.Value; } return false; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteByte((byte)Type); writer.WriteByte(Padding); writer.WriteIndex(Parent, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Value, (IndexSize)layout.Columns[3].Size); } public override bool Equals(object? obj) { if (obj is ConstantRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((((int)Type * 397) ^ Padding.GetHashCode()) * 397) ^ Parent) * 397) ^ Value); } public override string ToString() { return $"({Type:X2}, {Padding:X2}, {Parent:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct CustomAttributeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.CustomAttribute; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Type, 2 => Value, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Type { get; set; } public uint Value { get; set; } public static CustomAttributeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new CustomAttributeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public CustomAttributeRow(uint parent, uint type, uint value) { Parent = parent; Type = type; Value = value; } public bool Equals(CustomAttributeRow other) { if (Parent == other.Parent && Type == other.Type) { return Value == other.Value; } return false; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Type, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Value, (IndexSize)layout.Columns[2].Size); } public override bool Equals(object? obj) { if (obj is CustomAttributeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Type) * 397) ^ Value); } public override string ToString() { return $"({Parent:X8}, {Type:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct CustomDebugInformationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.CustomDebugInformation; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Kind, 2 => Value, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Kind { get; set; } public uint Value { get; set; } public CustomDebugInformationRow(uint parent, uint kind, uint value) { Parent = parent; Kind = kind; Value = value; } public static CustomDebugInformationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new CustomDebugInformationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Kind, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Value, (IndexSize)layout.Columns[2].Size); } public bool Equals(CustomDebugInformationRow other) { if (Parent == other.Parent && Kind == other.Kind) { return Value == other.Value; } return false; } public override bool Equals(object? obj) { if (obj is CustomDebugInformationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Kind) * 397) ^ Value); } public override string ToString() { return $"({Parent:X8}, {Kind:X8}, {Value:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum DeltaFunctionCode : uint { FuncDefault, MethodCreate, FieldCreate, ParamCreate, PropertyCreate, EventCreate } public struct DocumentRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 4; public uint this[int index] => index switch { 0 => Name, 1 => HashAlgorithm, 2 => Hash, 3 => Language, _ => throw new IndexOutOfRangeException(), }; public uint Name { get; set; } public uint HashAlgorithm { get; set; } public uint Hash { get; set; } public uint Language { get; set; } public DocumentRow(uint name, uint hashAlgorithm, uint hash, uint language) { Name = name; HashAlgorithm = hashAlgorithm; Hash = hash; Language = language; } public static DocumentRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new DocumentRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Name, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(HashAlgorithm, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Hash, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Language, (IndexSize)layout.Columns[3].Size); } public bool Equals(DocumentRow other) { if (Name == other.Name && HashAlgorithm == other.HashAlgorithm && Hash == other.Hash) { return Language == other.Language; } return false; } public override bool Equals(object? obj) { if (obj is DocumentRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((Name * 397) ^ HashAlgorithm) * 397) ^ Hash) * 397) ^ Language); } public override string ToString() { return $"({Name:X8}, {HashAlgorithm:X8}, {Hash:X8}, {Language:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum ElementType : byte { None = 0, Void = 1, Boolean = 2, Char = 3, I1 = 4, U1 = 5, I2 = 6, U2 = 7, I4 = 8, U4 = 9, I8 = 10, U8 = 11, R4 = 12, R8 = 13, String = 14, Ptr = 15, ByRef = 16, ValueType = 17, Class = 18, Var = 19, Array = 20, GenericInst = 21, TypedByRef = 22, I = 24, U = 25, FnPtr = 27, Object = 28, SzArray = 29, MVar = 30, CModReqD = 31, CModOpt = 32, Internal = 33, Modifier = 64, Sentinel = 65, Pinned = 69, Type = 80, Boxed = 81, Enum = 85 } public struct EncLogRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EncLog; public int Count => 2; public uint this[int index] => index switch { 0 => Token.ToUInt32(), 1 => (uint)FuncCode, _ => throw new IndexOutOfRangeException(), }; public MetadataToken Token { get; set; } public DeltaFunctionCode FuncCode { get; set; } public static EncLogRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EncLogRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), (DeltaFunctionCode)((BinaryStreamReader)(ref reader)).ReadUInt32()); } public EncLogRow(MetadataToken token, DeltaFunctionCode funcCode) { Token = token; FuncCode = funcCode; } public bool Equals(EncLogRow other) { if (Token.Equals(other.Token)) { return FuncCode == other.FuncCode; } return false; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Token.ToUInt32()); writer.WriteUInt32((uint)FuncCode); } public override bool Equals(object? obj) { if (obj is EncLogRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (Token.GetHashCode() * 397) ^ (int)FuncCode; } public override string ToString() { return $"({Token}, {FuncCode:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EncMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EncMap; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Token.ToUInt32(); } throw new IndexOutOfRangeException(); } } public MetadataToken Token { get; set; } public static EncMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EncMapRow(((BinaryStreamReader)(ref reader)).ReadUInt32()); } public EncMapRow(MetadataToken token) { Token = token; } public bool Equals(EncMapRow other) { return Token.Equals(other.Token); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Token.ToUInt32()); } public override bool Equals(object? obj) { if (obj is EncMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return Token.GetHashCode(); } public override string ToString() { return $"({Token})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum EventAttributes : ushort { SpecialName = 0x200, RtSpecialName = 0x400 } public struct EventDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Event; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => EventType, _ => throw new IndexOutOfRangeException(), }; public EventAttributes Attributes { get; set; } public uint Name { get; set; } public uint EventType { get; set; } public static EventDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventDefinitionRow((EventAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public EventDefinitionRow(EventAttributes attributes, uint name, uint eventType) { Attributes = attributes; Name = name; EventType = eventType; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(EventType, (IndexSize)layout.Columns[2].Size); } public bool Equals(EventDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return EventType == other.EventType; } return false; } public override bool Equals(object? obj) { if (obj is EventDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ EventType); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {EventType:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EventMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EventMap; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => EventList, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint EventList { get; set; } public static EventMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventMapRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public EventMapRow(uint parent, uint eventList) { Parent = parent; EventList = eventList; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(EventList, (IndexSize)layout.Columns[1].Size); } public bool Equals(EventMapRow other) { if (Parent == other.Parent) { return EventList == other.EventList; } return false; } public override bool Equals(object? obj) { if (obj is EventMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ EventList); } public override string ToString() { return $"({Parent:X8}, {EventList:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct EventPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.EventPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Event; } throw new IndexOutOfRangeException(); } } public uint Event { get; set; } public static EventPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new EventPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public EventPointerRow(uint @event) { Event = @event; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Event, (IndexSize)layout.Columns[0].Size); } public bool Equals(EventPointerRow other) { return Event == other.Event; } public override bool Equals(object? obj) { if (obj is EventPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Event; } public override string ToString() { return $"({Event:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ExportedTypeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ExportedType; public int Count => 5; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => TypeDefinitionId, 2 => Name, 3 => Namespace, 4 => Implementation, _ => throw new IndexOutOfRangeException(), }; public TypeAttributes Attributes { get; set; } public uint TypeDefinitionId { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public uint Implementation { get; set; } public static ExportedTypeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ExportedTypeRow((TypeAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size)); } public ExportedTypeRow(TypeAttributes attributes, uint typeDefinitionId, uint name, uint ns, uint implementation) { Attributes = attributes; TypeDefinitionId = typeDefinitionId; Name = name; Namespace = ns; Implementation = implementation; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); writer.WriteUInt32(TypeDefinitionId); writer.WriteIndex(Name, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Namespace, (IndexSize)layout.Columns[3].Size); writer.WriteIndex(Implementation, (IndexSize)layout.Columns[4].Size); } public bool Equals(ExportedTypeRow other) { if (Attributes == other.Attributes && TypeDefinitionId == other.TypeDefinitionId && Name == other.Name && Namespace == other.Namespace) { return Implementation == other.Implementation; } return false; } public override bool Equals(object? obj) { if (obj is ExportedTypeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)((int)Attributes * 397) ^ TypeDefinitionId) * 397) ^ Name) * 397) ^ Namespace) * 397) ^ Implementation); } public override string ToString() { return $"({Attributes:X8}, {TypeDefinitionId:X8}, {Name:X8}, {Namespace:X8}, {Implementation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum FieldAttributes : ushort { FieldAccessMask = 7, PrivateScope = 0, Private = 1, FamilyAndAssembly = 2, Assembly = 3, Family = 4, FamilyOrAssembly = 5, Public = 6, Static = 0x10, InitOnly = 0x20, Literal = 0x40, NotSerialized = 0x80, SpecialName = 0x200, PInvokeImpl = 0x2000, ReservedMask = 0x9500, RuntimeSpecialName = 0x400, HasFieldMarshal = 0x1000, HasDefault = 0x8000, HasFieldRva = 0x100 } public struct FieldDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Field; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Signature, _ => throw new IndexOutOfRangeException(), }; public FieldAttributes Attributes { get; set; } public uint Name { get; set; } public uint Signature { get; } public static FieldDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldDefinitionRow((FieldAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public FieldDefinitionRow(FieldAttributes attributes, uint name, uint signature) { Attributes = attributes; Name = name; Signature = signature; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Signature, (IndexSize)layout.Columns[2].Size); } public bool Equals(FieldDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is FieldDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Signature); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldLayoutRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldLayout; public int Count => 2; public uint this[int index] => index switch { 0 => Offset, 1 => Field, _ => throw new IndexOutOfRangeException(), }; public uint Offset { get; set; } public uint Field { get; set; } public static FieldLayoutRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldLayoutRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldLayoutRow(uint offset, uint field) { Offset = offset; Field = field; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Offset); writer.WriteIndex(Field, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldLayoutRow other) { if (Offset == other.Offset) { return Field == other.Field; } return false; } public override bool Equals(object? obj) { if (obj is FieldLayoutRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Offset * 397) ^ Field); } public override string ToString() { return $"({Offset:X8}, {Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldMarshalRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldMarshal; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => NativeType, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint NativeType { get; set; } public static FieldMarshalRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldMarshalRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldMarshalRow(uint parent, uint nativeType) { Parent = parent; NativeType = nativeType; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(NativeType, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldMarshalRow other) { if (Parent == other.Parent) { return NativeType == other.NativeType; } return false; } public override bool Equals(object? obj) { if (obj is FieldMarshalRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ NativeType); } public override string ToString() { return $"({Parent:X8}, {NativeType:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Field; } throw new IndexOutOfRangeException(); } } public uint Field { get; set; } public static FieldPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FieldPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public FieldPointerRow(uint field) { Field = field; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Field, (IndexSize)layout.Columns[0].Size); } public bool Equals(FieldPointerRow other) { return Field == other.Field; } public override bool Equals(object? obj) { if (obj is FieldPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Field; } public override string ToString() { return $"({Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct FieldRvaRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.FieldRva; public int Count => 2; public uint this[int index] { get { switch (index) { case 0: { ISegmentReference data = Data; return (data != null) ? ((IOffsetProvider)data).Rva : 0u; } case 1: return Field; default: throw new IndexOutOfRangeException(); } } } public ISegmentReference Data { get; set; } public uint Field { get; set; } public static FieldRvaRow FromReader(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout) { return new FieldRvaRow(context.ReferenceFactory.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public FieldRvaRow(ISegmentReference data, uint field) { Data = data; Field = field; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(((IOffsetProvider)Data).Rva); writer.WriteIndex(Field, (IndexSize)layout.Columns[1].Size); } public bool Equals(FieldRvaRow other) { ISegmentReference data = Data; uint? num = ((data != null) ? new uint?(((IOffsetProvider)data).Rva) : null); ISegmentReference data2 = other.Data; if (num == ((data2 != null) ? new uint?(((IOffsetProvider)data2).Rva) : null)) { return Field == other.Field; } return false; } public override bool Equals(object? obj) { if (obj is FieldRvaRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((IOffsetProvider)Data).Rva * 397) ^ Field); } public override string ToString() { return $"({((IOffsetProvider)Data).Rva:X8}, {Field:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum FileAttributes : uint { ContainsMetadata, ContainsNoMetadata } public struct FileReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.File; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => HashValue, _ => throw new IndexOutOfRangeException(), }; public FileAttributes Attributes { get; set; } public uint Name { get; set; } public uint HashValue { get; set; } public static FileReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new FileReferenceRow((FileAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public FileReferenceRow(FileAttributes attributes, uint name, uint hashValue) { Attributes = attributes; Name = name; HashValue = hashValue; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(HashValue, (IndexSize)layout.Columns[2].Size); } public bool Equals(FileReferenceRow other) { if (Attributes == other.Attributes && Name == other.Name) { return HashValue == other.HashValue; } return false; } public override bool Equals(object? obj) { if (obj is FileReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ HashValue); } public override string ToString() { return $"({Attributes:X8}, {Name:X8}, {HashValue:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum GenericParameterAttributes : ushort { NonVariant = 0, Covariant = 1, Contravariant = 2, VarianceMask = 3, SpecialConstraintMask = 0x1C, ReferenceTypeConstraint = 4, NotNullableValueTypeConstraint = 8, DefaultConstructorConstraint = 0x10 } public struct GenericParameterConstraintRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.GenericParamConstraint; public int Count => 2; public uint this[int index] => index switch { 0 => Owner, 1 => Constraint, _ => throw new IndexOutOfRangeException(), }; public uint Owner { get; set; } public uint Constraint { get; set; } public static GenericParameterConstraintRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new GenericParameterConstraintRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public GenericParameterConstraintRow(uint owner, uint constraint) { Owner = owner; Constraint = constraint; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Owner, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Constraint, (IndexSize)layout.Columns[1].Size); } public bool Equals(GenericParameterConstraintRow other) { if (Owner == other.Owner) { return Constraint == other.Constraint; } return false; } public override bool Equals(object? obj) { if (obj is GenericParameterConstraintRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Owner * 397) ^ Constraint); } public override string ToString() { return $"({Owner:X8}, {Constraint:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct GenericParameterRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.GenericParam; public int Count => 4; public uint this[int index] => index switch { 0 => Number, 1 => (uint)Attributes, 2 => Owner, 3 => Name, _ => throw new IndexOutOfRangeException(), }; public ushort Number { get; set; } public GenericParameterAttributes Attributes { get; set; } public uint Owner { get; set; } public uint Name { get; set; } public static GenericParameterRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new GenericParameterRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), (GenericParameterAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public GenericParameterRow(ushort number, GenericParameterAttributes attributes, uint owner, uint name) { Number = number; Attributes = attributes; Owner = owner; Name = name; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(Number); writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Owner, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Name, (IndexSize)layout.Columns[3].Size); } public bool Equals(GenericParameterRow other) { if (Number == other.Number && Attributes == other.Attributes && Owner == other.Owner) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is GenericParameterRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((uint)(Number.GetHashCode() * 397) ^ (uint)Attributes) * 397) ^ Owner) * 397) ^ Name); } public override string ToString() { return $"({Number:X4}, {Attributes:X4}, {Owner:X8}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public interface IMetadataRow : IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { TableIndex TableIndex { get; } void Write(BinaryStreamWriter writer, TableLayout layout); } public interface IMetadataTable : ICollection, IEnumerable { TableLayout Layout { get; } IMetadataRow this[int index] { get; set; } bool IsSorted { get; set; } IMetadataRow GetByRid(uint rid); bool TryGetCell(uint rid, int column, out uint value); bool TryGetByRid(uint rid, out IMetadataRow row); bool TryGetRowByKey(int keyColumnIndex, uint key, out IMetadataRow row); void SetByRid(uint rid, IMetadataRow row); void UpdateTableLayout(TableLayout layout); void Write(BinaryStreamWriter writer); } [Flags] public enum ImplementationMapAttributes : ushort { NoMangle = 1, CharSetNotSpec = 0, CharSetAnsi = 2, CharSetUnicode = 4, CharSetAuto = 6, CharSetMask = 6, BestFitUseAssem = 0, BestFitEnabled = 0x10, BestFitDisabled = 0x20, BestFitMask = 0x30, ThrowOnUnmappableCharUseAssem = 0, ThrowOnUnmappableCharEnabled = 0x1000, ThrowOnUnmappableCharDisabled = 0x2000, ThrowOnUnmappableCharMask = 0x3000, SupportsLastError = 0x40, CallConvWinapi = 0x100, CallConvCdecl = 0x200, CallConvStdcall = 0x300, CallConvThiscall = 0x400, CallConvFastcall = 0x500, CallConvMask = 0x700 } public struct ImplementationMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ImplMap; public int Count => 4; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => MemberForwarded, 2 => ImportName, 3 => ImportScope, _ => throw new IndexOutOfRangeException(), }; public ImplementationMapAttributes Attributes { get; } public uint MemberForwarded { get; set; } public uint ImportName { get; set; } public uint ImportScope { get; set; } public static ImplementationMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ImplementationMapRow((ImplementationMapAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ImplementationMapRow(ImplementationMapAttributes attributes, uint memberForwarded, uint importName, uint importScope) { Attributes = attributes; MemberForwarded = memberForwarded; ImportName = importName; ImportScope = importScope; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(MemberForwarded, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(ImportName, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(ImportScope, (IndexSize)layout.Columns[3].Size); } public bool Equals(ImplementationMapRow other) { if (Attributes == other.Attributes && MemberForwarded == other.MemberForwarded && ImportName == other.ImportName) { return ImportScope == other.ImportScope; } return false; } public override bool Equals(object? obj) { if (obj is ImplementationMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((uint)((int)Attributes * 397) ^ MemberForwarded) * 397) ^ ImportName) * 397) ^ ImportScope); } public override string ToString() { return $"({Attributes:X4}, {MemberForwarded:X8}, {ImportName:X8}, {ImportScope:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ImportScopeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ImportScope; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => Imports, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Imports { get; set; } public ImportScopeRow(uint parent, uint imports) { Parent = parent; Imports = imports; } public static ImportScopeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ImportScopeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Imports, (IndexSize)layout.Columns[1].Size); } public bool Equals(ImportScopeRow other) { if (Parent == other.Parent) { return Imports == other.Imports; } return false; } public override bool Equals(object? obj) { if (obj is ImportScopeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ Imports); } public override string ToString() { return $"({Parent:X8}, {Imports:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class IndexEncoder { private readonly TablesStream _tableStream; private readonly TableIndex[] _tables; private readonly int _tableIndexBitCount; private readonly int _tableIndexBitMask; private readonly int _maxSmallTableMemberCount; public IndexSize IndexSize { get { if (!_tableStream.ForceLargeColumns) { uint num = 0u; TableIndex[] tables = _tables; foreach (TableIndex table in tables) { num = Math.Max(num, _tableStream.GetTableRowCount(table)); } if (num > _maxSmallTableMemberCount) { return (IndexSize)4; } return (IndexSize)2; } return (IndexSize)4; } } public IndexEncoder(TablesStream tableStream, params TableIndex[] tables) { _tableStream = tableStream ?? throw new ArgumentNullException("tableStream"); _tables = tables ?? throw new ArgumentNullException("tables"); _tableIndexBitCount = (int)Math.Ceiling(Math.Log(tables.Length, 2.0)); _tableIndexBitMask = (int)(Math.Pow(2.0, _tableIndexBitCount) - 1.0); _maxSmallTableMemberCount = 65535 >> _tableIndexBitCount; } public uint EncodeToken(MetadataToken token) { int num = Array.IndexOf(_tables, token.Table); if (num == -1) { throw new ArgumentException("Table is not supported by this encoder.", "token"); } return (token.Rid << _tableIndexBitCount) | (uint)num; } public MetadataToken DecodeIndex(uint codedIndex) { long num = codedIndex & _tableIndexBitMask; uint rid = codedIndex >> _tableIndexBitCount; return new MetadataToken((num < _tables.Length) ? _tables[num] : TableIndex.Module, rid); } } public struct InterfaceImplementationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.InterfaceImpl; public int Count => 2; public uint this[int index] => index switch { 0 => Class, 1 => Interface, _ => throw new IndexOutOfRangeException(), }; public uint Class { get; set; } public uint Interface { get; set; } public static InterfaceImplementationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new InterfaceImplementationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public InterfaceImplementationRow(uint @class, uint @interface) { Class = @class; Interface = @interface; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Class, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Interface, (IndexSize)layout.Columns[1].Size); } public bool Equals(InterfaceImplementationRow other) { if (Class == other.Class) { return Interface == other.Interface; } return false; } public override bool Equals(object? obj) { if (obj is InterfaceImplementationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Class * 397) ^ Interface); } public override string ToString() { return $"({Class:X8}, {Interface:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct LocalConstantRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.LocalConstant; public int Count => 2; public uint this[int index] => index switch { 0 => Name, 1 => Signature, _ => throw new IndexOutOfRangeException(), }; public uint Name { get; set; } public uint Signature { get; set; } public LocalConstantRow(uint name, uint signature) { Name = name; Signature = signature; } public static LocalConstantRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalConstantRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Name, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Signature, (IndexSize)layout.Columns[1].Size); } public bool Equals(LocalConstantRow other) { if (Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is LocalConstantRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Name * 397) ^ Signature); } public override string ToString() { return $"({Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct LocalScopeRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 6; public uint this[int index] => index switch { 0 => Method, 1 => ImportScope, 2 => VariableList, 3 => ConstantList, 4 => StartOffset, 5 => Length, _ => throw new IndexOutOfRangeException(), }; public uint Method { get; set; } public uint ImportScope { get; set; } public uint VariableList { get; set; } public uint ConstantList { get; set; } public uint StartOffset { get; set; } public uint Length { get; set; } public LocalScopeRow(uint method, uint importScope, uint variableList, uint constantList, uint startOffset, uint length) { Method = method; ImportScope = importScope; VariableList = variableList; ConstantList = constantList; StartOffset = startOffset; Length = length; } public static LocalScopeRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalScopeRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadUInt32()); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Method, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(ImportScope, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(VariableList, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(ConstantList, (IndexSize)layout.Columns[3].Size); writer.WriteUInt32(StartOffset); writer.WriteUInt32(Length); } public bool Equals(LocalScopeRow other) { if (Method == other.Method && ImportScope == other.ImportScope && VariableList == other.VariableList && ConstantList == other.ConstantList && StartOffset == other.StartOffset) { return Length == other.Length; } return false; } public override bool Equals(object? obj) { if (obj is LocalScopeRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((Method * 397) ^ ImportScope) * 397) ^ VariableList) * 397) ^ ConstantList) * 397) ^ StartOffset) * 397) ^ Length); } public override string ToString() { return $"({Method:X8}, {ImportScope:X8}, {VariableList:X8}, {ConstantList:X8}, {StartOffset:X8}, {Length:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum LocalVariableAttributes : ushort { DebuggerHidden = 1 } public struct LocalVariableRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.LocalVariable; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Index, 2 => Name, _ => throw new IndexOutOfRangeException(), }; public LocalVariableAttributes Attributes { get; set; } public ushort Index { get; set; } public uint Name { get; set; } public LocalVariableRow(LocalVariableAttributes attributes, ushort index, uint name) { Attributes = attributes; Index = index; Name = name; } public static LocalVariableRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new LocalVariableRow((LocalVariableAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteUInt16(Index); writer.WriteIndex(Name, (IndexSize)layout.Columns[2].Size); } public bool Equals(LocalVariableRow other) { if (Attributes == other.Attributes && Index == other.Index) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is LocalScopeRow localScopeRow) { return Equals(localScopeRow); } return false; } public override int GetHashCode() { return ((((int)Attributes * 397) ^ Index) * 397) ^ (int)Name; } public override string ToString() { return $"({Attributes:X4}, {Index:X4}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum ManifestResourceAttributes : uint { Public = 1u, Private } public struct ManifestResourceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ManifestResource; public int Count => 4; public uint this[int index] => index switch { 0 => Offset, 1 => (uint)Attributes, 2 => Name, 3 => Implementation, _ => throw new IndexOutOfRangeException(), }; public uint Offset { get; set; } public ManifestResourceAttributes Attributes { get; set; } public uint Name { get; set; } public uint Implementation { get; set; } public static ManifestResourceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ManifestResourceRow(((BinaryStreamReader)(ref reader)).ReadUInt32(), (ManifestResourceAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size)); } public ManifestResourceRow(uint offset, ManifestResourceAttributes attributes, uint name, uint implementation) { Offset = offset; Attributes = attributes; Name = name; Implementation = implementation; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32(Offset); writer.WriteUInt32((uint)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Implementation, (IndexSize)layout.Columns[3].Size); } public bool Equals(ManifestResourceRow other) { if (Offset == other.Offset && Attributes == other.Attributes && Name == other.Name) { return Implementation == other.Implementation; } return false; } public override bool Equals(object? obj) { if (obj is ManifestResourceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((Offset * 397) ^ (uint)Attributes) * 397) ^ Name) * 397) ^ Implementation); } public override string ToString() { return $"({Offset:X8}, {Attributes:X8}, {Name:X8}, {Implementation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MemberReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MemberRef; public int Count => 3; public uint this[int index] => index switch { 0 => Parent, 1 => Name, 2 => Signature, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint Name { get; set; } public uint Signature { get; set; } public static MemberReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MemberReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MemberReferenceRow(uint parent, uint name, uint signature) { Parent = parent; Name = name; Signature = signature; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Signature, (IndexSize)layout.Columns[2].Size); } public bool Equals(MemberReferenceRow other) { if (Parent == other.Parent && Name == other.Name) { return Signature == other.Signature; } return false; } public override bool Equals(object? obj) { if (obj is MemberReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Parent * 397) ^ Name) * 397) ^ Signature); } public override string ToString() { return $"({Parent:X8}, {Name:X8}, {Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public readonly struct MetadataRange : IEnumerable, IEnumerable, IEquatable { public struct Enumerator : IEnumerator, IEnumerator, IDisposable { private readonly MetadataRange _range; private uint _currentRid; public MetadataToken Current { get { uint value; if (!_range.IsRedirected) { value = _currentRid; } else { _range.RedirectionTable.TryGetCell(_currentRid, 0, out value); } return new MetadataToken(_range.Table, value); } } object IEnumerator.Current => Current; public Enumerator(MetadataRange range) { _range = range; _currentRid = range.StartRid - 1; } public bool MoveNext() { if (_currentRid < _range.EndRid - 1) { _currentRid++; return true; } return false; } public void Reset() { _currentRid = 0u; } public void Dispose() { } } public static readonly MetadataRange Empty = new MetadataRange(TableIndex.Module, 1u, 1u); public TableIndex Table { get; } public uint StartRid { get; } public uint EndRid { get; } public int Count => (int)(EndRid - StartRid); public bool IsEmpty => EndRid == StartRid; public IMetadataTable? RedirectionTable { get; } [MemberNotNullWhen(true, "RedirectionTable")] public bool IsRedirected { [MemberNotNullWhen(true, "RedirectionTable")] get { return RedirectionTable != null; } } public MetadataRange(TableIndex table, uint startRid, uint endRid) { Table = table; StartRid = startRid; EndRid = endRid; RedirectionTable = null; } public MetadataRange(IMetadataTable redirectionTable, TableIndex table, uint startRid, uint endRid) { Table = table; StartRid = startRid; EndRid = endRid; RedirectionTable = redirectionTable; } public Enumerator GetEnumerator() { return new Enumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override string ToString() { MetadataToken metadataToken = new MetadataToken(Table, StartRid); MetadataToken metadataToken2 = new MetadataToken(Table, EndRid); return $"[0x{metadataToken.ToString()}..0x{metadataToken2.ToString()})"; } public bool Equals(MetadataRange other) { if (IsEmpty && other.IsEmpty) { return true; } if (Table == other.Table && StartRid == other.StartRid && EndRid == other.EndRid) { return object.Equals(RedirectionTable, other.RedirectionTable); } return false; } public override bool Equals(object? obj) { if (obj is MetadataRange other) { return Equals(other); } return false; } public override int GetHashCode() { if (IsEmpty) { return 0; } return (int)(((((uint)((int)Table * 397) ^ StartRid) * 397) ^ EndRid) * 397) ^ ((RedirectionTable != null) ? RedirectionTable.GetHashCode() : 0); } } public struct MetadataRowColumnEnumerator : IEnumerator, IEnumerator, IDisposable { private readonly IMetadataRow _row; private int _index; public uint Current { get { if (_index < 0 || _index >= _row.Count) { return 0u; } return _row[_index]; } } object IEnumerator.Current => Current; public MetadataRowColumnEnumerator(IMetadataRow row) { _row = row; _index = -1; } public bool MoveNext() { if (_index < _row.Count - 1) { _index++; return true; } return false; } public void Reset() { _index = 0; } public void Dispose() { } } public class MetadataTable : IMetadataTable, ICollection, IEnumerable, ICollection, IEnumerable where TRow : struct, IMetadataRow { private RefList? _items; public TableIndex TableIndex { get; } public TableLayout Layout { get; private set; } public TRow this[int index] { get { return Rows[index]; } set { Rows[index] = value; } } public bool IsSorted { get; set; } IMetadataRow IMetadataTable.this[int index] { get { return this[index]; } set { this[index] = (TRow)value; } } public int Version => Rows.Version; protected RefList Rows { get { if (_items == null) { Interlocked.CompareExchange(ref _items, GetRows(), null); } return _items; } } protected bool IsInitialized => _items != null; public virtual int Count => Rows.Count; public int Capacity { get { return Rows.Capacity; } set { Rows.Capacity = value; } } public bool IsReadOnly => false; public object SyncRoot => this; public bool IsSynchronized => false; public MetadataTable(TableIndex tableIndex, TableLayout layout) : this(tableIndex, layout, isSorted: false) { } public MetadataTable(TableIndex tableIndex, TableLayout layout, bool isSorted) { TableIndex = tableIndex; Layout = layout; IsSorted = isSorted; } public ref TRow GetRowRef(uint rid) { return ref Rows.GetElementRef((int)(rid - 1)); } public ref TRow GetRowRef(uint rid, out int version) { return ref Rows.GetElementRef((int)(rid - 1), ref version); } public void Add(TRow item) { Rows.Add(ref item); } public void Clear() { Rows.Clear(); } public bool Contains(TRow item) { return Rows.Contains(ref item); } public void CopyTo(TRow[] array, int arrayIndex) { Rows.CopyTo(array, arrayIndex); } void ICollection.CopyTo(Array array, int index) { ((ICollection)Rows).CopyTo(array, index); } public bool Remove(TRow item) { return Rows.Remove(ref item); } public IEnumerator GetEnumerator() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return (IEnumerator)(object)Rows.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } protected virtual RefList GetRows() { return new RefList(); } public TRow GetByRid(uint rid) { return this[(int)(rid - 1)]; } public bool TryGetCell(uint rid, int column, out uint value) { if (column >= 0 && column < Layout.Columns.Count && TryGetByRid(rid, out var row)) { value = row[column]; return true; } value = 0u; return false; } IMetadataRow IMetadataTable.GetByRid(uint rid) { return GetByRid(rid); } public bool TryGetByRid(uint rid, out TRow row) { if (rid >= 1 && rid <= Count) { row = GetByRid(rid); return true; } row = default(TRow); return false; } bool IMetadataTable.TryGetByRid(uint rid, out IMetadataRow row) { TRow row2; bool result = TryGetByRid(rid, out row2); row = row2; return result; } public bool TryGetRowByKey(int keyColumnIndex, uint key, out TRow row) { row = default(TRow); if (Count == 0) { return false; } int num = 0; int num2 = Count - 1; while (num <= num2) { int num3 = (num + num2) / 2; TRow val = Rows[num3]; uint num4 = val[keyColumnIndex]; if (num4 > key) { num2 = num3 - 1; continue; } if (num4 < key) { num = num3 + 1; continue; } row = val; return true; } return false; } bool IMetadataTable.TryGetRowByKey(int keyColumnIndex, uint key, out IMetadataRow row) { TRow row2; bool result = TryGetRowByKey(keyColumnIndex, key, out row2); row = row2; return result; } public void SetByRid(uint rid, TRow row) { this[(int)(rid - 1)] = row; } void IMetadataTable.SetByRid(uint rid, IMetadataRow row) { SetByRid(rid, (TRow)row); } public virtual void UpdateTableLayout(TableLayout layout) { for (int i = 0; i < Layout.Columns.Count; i++) { if (Layout.Columns[i].Name != layout.Columns[i].Name || Layout.Columns[i].Type != layout.Columns[i].Type) { throw new ArgumentException("New table layout does not match the original one."); } } Layout = layout; } public void Write(BinaryStreamWriter writer) { for (int i = 0; i < Rows.Count; i++) { Rows[i].Write(writer, Layout); } } } public readonly struct MetadataToken : IComparable { public static readonly MetadataToken Zero = new MetadataToken(0u); private readonly uint _value; public TableIndex Table => (TableIndex)(_value >> 24); public uint Rid => _value & 0xFFFFFFu; public static implicit operator MetadataToken(int token) { return new MetadataToken((uint)token); } public static implicit operator MetadataToken(uint token) { return new MetadataToken(token); } public static bool operator ==(MetadataToken a, MetadataToken b) { return a.Equals(b); } public static bool operator !=(MetadataToken a, MetadataToken b) { return !(a == b); } public MetadataToken(uint value) { _value = value; } public MetadataToken(TableIndex table, uint rid) : this(((uint)table << 24) | (rid & 0xFFFFFFu)) { if (rid > 16777215) { throw new ArgumentOutOfRangeException("rid"); } } public uint ToUInt32() { return _value; } public int ToInt32() { return (int)_value; } public override string ToString() { return _value.ToString("X8"); } public bool Equals(MetadataToken other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is MetadataToken other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)_value; } public int CompareTo(MetadataToken other) { return _value.CompareTo(other._value); } } [Flags] public enum MethodAttributes : ushort { CompilerControlled = 0, Private = 1, FamilyAndAssembly = 2, Assembly = 3, Family = 4, FamilyOrAssembly = 5, Public = 6, MemberAccessMask = 7, UnmanagedExport = 8, Static = 0x10, Final = 0x20, Virtual = 0x40, HideBySig = 0x80, ReuseSlot = 0, NewSlot = 0x100, VtableLayoutMask = 0x100, CheckAccessOnOverride = 0x200, Abstract = 0x400, SpecialName = 0x800, RuntimeSpecialName = 0x1000, PInvokeImpl = 0x2000, HasSecurity = 0x4000, RequireSecObject = 0x8000 } public struct MethodDebugInformationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Document; public int Count => 2; public uint this[int index] => index switch { 0 => Document, 1 => SequencePoints, _ => throw new IndexOutOfRangeException(), }; public uint Document { get; set; } public uint SequencePoints { get; set; } public MethodDebugInformationRow(uint document, uint sequencePoints) { Document = document; SequencePoints = sequencePoints; } public static MethodDebugInformationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodDebugInformationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Document, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(SequencePoints, (IndexSize)layout.Columns[1].Size); } public bool Equals(MethodDebugInformationRow other) { if (Document == other.Document) { return SequencePoints == other.SequencePoints; } return false; } public override bool Equals(object? obj) { if (obj is MethodDebugInformationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Document * 397) ^ SequencePoints); } public override string ToString() { return $"({Document:X8}, {SequencePoints:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Method; public int Count => 6; public uint this[int index] { get { switch (index) { case 0: { ISegmentReference body = Body; return (body != null) ? ((IOffsetProvider)body).Rva : 0u; } case 1: return (uint)ImplAttributes; case 2: return (uint)Attributes; case 3: return Name; case 4: return Signature; case 5: return ParameterList; default: throw new IndexOutOfRangeException(); } } } public ISegmentReference Body { get; set; } public MethodImplAttributes ImplAttributes { get; set; } public MethodAttributes Attributes { get; set; } public uint Name { get; set; } public uint Signature { get; set; } public uint ParameterList { get; set; } public static MethodDefinitionRow FromReader(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout) { return new MethodDefinitionRow(context.ReferenceFactory.GetReferenceToRva(((BinaryStreamReader)(ref reader)).ReadUInt32()), (MethodImplAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), (MethodAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size)); } public MethodDefinitionRow(ISegmentReference body, MethodImplAttributes implAttributes, MethodAttributes attributes, uint name, uint signature, uint parameterList) { Body = body; ImplAttributes = implAttributes; Attributes = attributes; Name = name; Signature = signature; ParameterList = parameterList; } public void Write(BinaryStreamWriter writer, TableLayout layout) { ISegmentReference body = Body; writer.WriteUInt32((body != null) ? ((IOffsetProvider)body).Rva : 0u); writer.WriteUInt16((ushort)ImplAttributes); writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[3].Size); writer.WriteIndex(Signature, (IndexSize)layout.Columns[4].Size); writer.WriteIndex(ParameterList, (IndexSize)layout.Columns[5].Size); } public bool Equals(MethodDefinitionRow other) { ISegmentReference body = Body; uint? num = ((body != null) ? new uint?(((IOffsetProvider)body).Rva) : null); ISegmentReference body2 = other.Body; if (num == ((body2 != null) ? new uint?(((IOffsetProvider)body2).Rva) : null) && ImplAttributes == other.ImplAttributes && Attributes == other.Attributes && Name == other.Name && Signature == other.Signature) { return ParameterList == other.ParameterList; } return false; } public override bool Equals(object? obj) { if (obj is MethodDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { ISegmentReference body = Body; return (int)((((((((((((body != null) ? ((IOffsetProvider)body).Rva : 0) * 397) ^ (uint)ImplAttributes) * 397) ^ (uint)Attributes) * 397) ^ Name) * 397) ^ Signature) * 397) ^ ParameterList); } public override string ToString() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(12, 6); defaultInterpolatedStringHandler.AppendLiteral("("); ISegmentReference body = Body; defaultInterpolatedStringHandler.AppendFormatted((body != null) ? ((IOffsetProvider)body).Rva : 0u, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted((int)ImplAttributes, "X4"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted((int)Attributes, "X4"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(Name, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(Signature, "X8"); defaultInterpolatedStringHandler.AppendLiteral(", "); defaultInterpolatedStringHandler.AppendFormatted(ParameterList, "X8"); defaultInterpolatedStringHandler.AppendLiteral(")"); return defaultInterpolatedStringHandler.ToStringAndClear(); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum MethodImplAttributes : ushort { IL = 0, Native = 1, OPTIL = 2, Runtime = 3, CodeTypeMask = 3, Unmanaged = 4, Managed = 0, ManagedMask = 4, ForwardRef = 0x10, NoOptimization = 0x40, PreserveSig = 0x80, InternalCall = 0x1000, Synchronized = 0x20, NoInlining = 8, AggressiveInlining = 0x100, AggressiveOptimization = 0x200, SecurityMitigations = 0x201 } public struct MethodImplementationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodImpl; public int Count => 3; public uint this[int index] => index switch { 0 => Class, 1 => MethodBody, 2 => MethodDeclaration, _ => throw new IndexOutOfRangeException(), }; public uint Class { get; set; } public uint MethodBody { get; set; } public uint MethodDeclaration { get; set; } public static MethodImplementationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodImplementationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MethodImplementationRow(uint @class, uint methodBody, uint methodDeclaration) { Class = @class; MethodBody = methodBody; MethodDeclaration = methodDeclaration; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Class, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(MethodBody, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(MethodDeclaration, (IndexSize)layout.Columns[2].Size); } public bool Equals(MethodImplementationRow other) { if (Class == other.Class && MethodBody == other.MethodBody) { return MethodDeclaration == other.MethodDeclaration; } return false; } public override bool Equals(object? obj) { if (obj is MethodImplementationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((Class * 397) ^ MethodBody) * 397) ^ MethodDeclaration); } public override string ToString() { return $"({Class:X8}, {MethodBody:X8}, {MethodDeclaration:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Method; } throw new IndexOutOfRangeException(); } } public uint Method { get; set; } public static MethodPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public MethodPointerRow(uint method) { Method = method; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Method, (IndexSize)layout.Columns[0].Size); } public bool Equals(MethodPointerRow other) { return Method == other.Method; } public override bool Equals(object? obj) { if (obj is MethodPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Method; } public override string ToString() { return $"({Method:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum MethodSemanticsAttributes : ushort { Setter = 1, Getter = 2, Other = 4, AddOn = 8, RemoveOn = 0x10, Fire = 0x20 } public struct MethodSemanticsRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodSemantics; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Method, 2 => Association, _ => throw new IndexOutOfRangeException(), }; public MethodSemanticsAttributes Attributes { get; set; } public uint Method { get; set; } public uint Association { get; set; } public static MethodSemanticsRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodSemanticsRow((MethodSemanticsAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public MethodSemanticsRow(MethodSemanticsAttributes attributes, uint method, uint association) { Attributes = attributes; Method = method; Association = association; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Method, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Association, (IndexSize)layout.Columns[2].Size); } public bool Equals(MethodSemanticsRow other) { if (Attributes == other.Attributes && Method == other.Method) { return Association == other.Association; } return false; } public override bool Equals(object? obj) { if (obj is MethodSemanticsRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Method) * 397) ^ Association); } public override string ToString() { return $"({Attributes:X4}, {Method:X8}, {Association:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct MethodSpecificationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.MethodSpec; public int Count => 2; public uint this[int index] => index switch { 0 => Method, 1 => Instantiation, _ => throw new IndexOutOfRangeException(), }; public uint Method { get; set; } public uint Instantiation { get; set; } public static MethodSpecificationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new MethodSpecificationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public MethodSpecificationRow(uint method, uint instantiation) { Method = method; Instantiation = instantiation; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Method, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Instantiation, (IndexSize)layout.Columns[1].Size); } public bool Equals(MethodSpecificationRow other) { if (Method == other.Method) { return Instantiation == other.Instantiation; } return false; } public override bool Equals(object? obj) { if (obj is MethodSpecificationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Method * 397) ^ Instantiation); } public override string ToString() { return $"({Method:X8}, {Instantiation:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ModuleDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Module; public int Count => 5; public uint this[int index] => index switch { 0 => Generation, 1 => Name, 2 => Mvid, 3 => EncId, 4 => EncBaseId, _ => throw new IndexOutOfRangeException(), }; public ushort Generation { get; set; } public uint Name { get; set; } public uint Mvid { get; set; } public uint EncId { get; set; } public uint EncBaseId { get; set; } public static ModuleDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ModuleDefinitionRow(((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size)); } public ModuleDefinitionRow(ushort generation, uint name, uint mvid, uint encId, uint encBaseId) { Generation = generation; Name = name; Mvid = mvid; EncId = encId; EncBaseId = encBaseId; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16(Generation); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Mvid, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(EncId, (IndexSize)layout.Columns[3].Size); writer.WriteIndex(EncBaseId, (IndexSize)layout.Columns[4].Size); } public override string ToString() { return $"({Generation:X4}, {Name:X8}, {Mvid:X8}, {EncId:X8}, {EncBaseId:X8})"; } public bool Equals(ModuleDefinitionRow other) { if (Generation == other.Generation && Name == other.Name && Mvid == other.Mvid && EncId == other.EncId) { return EncBaseId == other.EncBaseId; } return false; } public override bool Equals(object? obj) { if (obj is ModuleDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((uint)(Generation.GetHashCode() * 397) ^ Name) * 397) ^ Mvid) * 397) ^ EncId) * 397) ^ EncBaseId); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ModuleReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ModuleRef; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Name; } throw new IndexOutOfRangeException(); } } public uint Name { get; set; } public static ModuleReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ModuleReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public ModuleReferenceRow(uint name) { Name = name; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Name, (IndexSize)layout.Columns[0].Size); } public bool Equals(ModuleReferenceRow other) { return Name == other.Name; } public override bool Equals(object? obj) { if (obj is ModuleReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Name; } public override string ToString() { return $"({Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct NestedClassRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.NestedClass; public int Count => 2; public uint this[int index] => index switch { 0 => NestedClass, 1 => EnclosingClass, _ => throw new IndexOutOfRangeException(), }; public uint NestedClass { get; set; } public uint EnclosingClass { get; set; } public static NestedClassRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new NestedClassRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public NestedClassRow(uint nestedClass, uint enclosingClass) { NestedClass = nestedClass; EnclosingClass = enclosingClass; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(NestedClass, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(EnclosingClass, (IndexSize)layout.Columns[1].Size); } public bool Equals(NestedClassRow other) { if (NestedClass == other.NestedClass) { return EnclosingClass == other.EnclosingClass; } return false; } public override bool Equals(object? obj) { if (obj is NestedClassRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((NestedClass * 397) ^ EnclosingClass); } public override string ToString() { return $"({NestedClass:X8}, {EnclosingClass:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum ParameterAttributes : ushort { In = 1, Out = 2, Optional = 0x10, HasDefault = 0x1000, HasFieldMarshal = 0x2000 } public struct ParameterDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Param; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Sequence, 2 => Name, _ => throw new IndexOutOfRangeException(), }; public ParameterAttributes Attributes { get; set; } public ushort Sequence { get; set; } public uint Name { get; set; } public static ParameterDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ParameterDefinitionRow((ParameterAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public ParameterDefinitionRow(ParameterAttributes attributes, ushort sequence, uint name) { Attributes = attributes; Sequence = sequence; Name = name; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteUInt16(Sequence); writer.WriteIndex(Name, (IndexSize)layout.Columns[2].Size); } public bool Equals(ParameterDefinitionRow other) { if (Attributes == other.Attributes && Sequence == other.Sequence) { return Name == other.Name; } return false; } public override bool Equals(object? obj) { if (obj is ParameterDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return ((((int)Attributes * 397) ^ Sequence.GetHashCode()) * 397) ^ (int)Name; } public override string ToString() { return $"({Attributes:X4}, {Sequence:X4}, {Name:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct ParameterPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ParamPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Parameter; } throw new IndexOutOfRangeException(); } } public uint Parameter { get; set; } public static ParameterPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new ParameterPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public ParameterPointerRow(uint parameter) { Parameter = parameter; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parameter, (IndexSize)layout.Columns[0].Size); } public bool Equals(ParameterPointerRow other) { return Parameter == other.Parameter; } public override bool Equals(object? obj) { if (obj is ParameterPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Parameter; } public override string ToString() { return $"({Parameter:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Flags] public enum PropertyAttributes : ushort { None = 0, SpecialName = 0x200, RuntimeSpecialName = 0x400, HasDefault = 0x1000 } public struct PropertyDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.Property; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Type, _ => throw new IndexOutOfRangeException(), }; public PropertyAttributes Attributes { get; set; } public uint Name { get; set; } public uint Type { get; set; } public static PropertyDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyDefinitionRow((PropertyAttributes)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public PropertyDefinitionRow(PropertyAttributes attributes, uint name, uint type) { Attributes = attributes; Name = name; Type = type; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Type, (IndexSize)layout.Columns[2].Size); } public bool Equals(PropertyDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name) { return Type == other.Type; } return false; } public override bool Equals(object? obj) { if (obj is PropertyDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Type); } public override string ToString() { return $"({Attributes:X4}, {Name:X8}, {Type:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct PropertyMapRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.PropertyMap; public int Count => 2; public uint this[int index] => index switch { 0 => Parent, 1 => PropertyList, _ => throw new IndexOutOfRangeException(), }; public uint Parent { get; set; } public uint PropertyList { get; set; } public static PropertyMapRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyMapRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public PropertyMapRow(uint parent, uint propertyList) { Parent = parent; PropertyList = propertyList; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Parent, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(PropertyList, (IndexSize)layout.Columns[1].Size); } public bool Equals(PropertyMapRow other) { if (Parent == other.Parent) { return PropertyList == other.PropertyList; } return false; } public override bool Equals(object? obj) { if (obj is PropertyMapRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((Parent * 397) ^ PropertyList); } public override string ToString() { return $"({Parent:X8}, {PropertyList:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct PropertyPointerRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.PropertyPtr; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Property; } throw new IndexOutOfRangeException(); } } public uint Property { get; set; } public static PropertyPointerRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new PropertyPointerRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public PropertyPointerRow(uint property) { Property = property; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Property, (IndexSize)layout.Columns[0].Size); } public bool Equals(PropertyPointerRow other) { return Property == other.Property; } public override bool Equals(object? obj) { if (obj is PropertyPointerRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Property; } public override string ToString() { return $"({Property:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum SecurityAction : ushort { Demand = 2, Assert, Deny, PermitOnly, LinkDemand, InheritanceDemand, RequestMinimum, RequestOptional, RequestRefuse } public struct SecurityDeclarationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.DeclSecurity; public int Count => 3; public uint this[int index] => index switch { 0 => (uint)Action, 1 => Parent, 2 => PermissionSet, _ => throw new IndexOutOfRangeException(), }; public SecurityAction Action { get; set; } public uint Parent { get; set; } public uint PermissionSet { get; set; } public static SecurityDeclarationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new SecurityDeclarationRow((SecurityAction)((BinaryStreamReader)(ref reader)).ReadUInt16(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public SecurityDeclarationRow(SecurityAction action, uint parent, uint permissionSet) { Action = action; Parent = parent; PermissionSet = permissionSet; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt16((ushort)Action); writer.WriteIndex(Parent, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(PermissionSet, (IndexSize)layout.Columns[2].Size); } public bool Equals(SecurityDeclarationRow other) { if (Action == other.Action && Parent == other.Parent) { return PermissionSet == other.PermissionSet; } return false; } public override bool Equals(object? obj) { if (obj is SecurityDeclarationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((uint)((int)Action * 397) ^ Parent) * 397) ^ PermissionSet); } public override string ToString() { return $"({Action:X4}, {Parent:X8}, {PermissionSet:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class SerializedMetadataTable : MetadataTable where TRow : struct, IMetadataRow { public delegate TRow ReadRowDelegate(ref BinaryStreamReader reader, TableLayout layout); public delegate TRow ReadRowExtendedDelegate(MetadataReaderContext context, ref BinaryStreamReader reader, TableLayout layout); private readonly BinaryStreamReader _reader; private readonly TableLayout _originalLayout; private readonly int _rowCount; private readonly ReadRowDelegate _readRow; public override int Count { get { if (!base.IsInitialized) { return _rowCount; } return base.Rows.Count; } } public SerializedMetadataTable(in BinaryStreamReader reader, TableIndex tableIndex, TableLayout originalLayout, bool isSorted, ReadRowDelegate readRow) : base(tableIndex, originalLayout, isSorted) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _originalLayout = originalLayout; _rowCount = (int)(((BinaryStreamReader)(ref reader)).Length / originalLayout.RowSize); _readRow = readRow ?? throw new ArgumentNullException("readRow"); } public SerializedMetadataTable(MetadataReaderContext context, in BinaryStreamReader reader, TableIndex tableIndex, TableLayout originalLayout, bool isSorted, ReadRowExtendedDelegate readRow) { ReadRowExtendedDelegate readRow2 = readRow; MetadataReaderContext context2 = context; this..ctor(in reader, tableIndex, originalLayout, isSorted, (ReadRowDelegate)delegate(ref BinaryStreamReader r, TableLayout l) { return readRow2(context2, ref r, l); }); } protected override RefList GetRows() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) RefList val = new RefList(_rowCount); BinaryStreamReader reader = ((BinaryStreamReader)(ref _reader)).Fork(); for (int i = 0; i < _rowCount; i++) { TRow val2 = _readRow(ref reader, _originalLayout); val.Add(ref val2); } return val; } } public struct StandAloneSignatureRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.StandAloneSig; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Signature; } throw new IndexOutOfRangeException(); } } public uint Signature { get; set; } public static StandAloneSignatureRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new StandAloneSignatureRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public StandAloneSignatureRow(uint signature) { Signature = signature; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Signature, (IndexSize)layout.Columns[0].Size); } public bool Equals(StandAloneSignatureRow other) { return Signature == other.Signature; } public override bool Equals(object? obj) { if (obj is StandAloneSignatureRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Signature; } public override string ToString() { return $"({Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct StateMachineMethodRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.StateMachineMethod; public int Count => 2; public uint this[int index] => index switch { 0 => MoveNextMethod, 1 => KickoffMethod, _ => throw new IndexOutOfRangeException(), }; public uint MoveNextMethod { get; set; } public uint KickoffMethod { get; set; } public StateMachineMethodRow(uint moveNextMethod, uint kickoffMethod) { MoveNextMethod = moveNextMethod; KickoffMethod = kickoffMethod; } public static StateMachineMethodRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new StateMachineMethodRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size)); } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(MoveNextMethod, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(KickoffMethod, (IndexSize)layout.Columns[1].Size); } public bool Equals(StateMachineMethodRow other) { if (MoveNextMethod == other.MoveNextMethod) { return KickoffMethod == other.KickoffMethod; } return false; } public override bool Equals(object? obj) { if (obj is StateMachineMethodRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((MoveNextMethod * 397) ^ KickoffMethod); } public override string ToString() { return $"({MoveNextMethod:X8}, {KickoffMethod:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public enum TableIndex : byte { Module = 0, TypeRef = 1, TypeDef = 2, FieldPtr = 3, Field = 4, MethodPtr = 5, Method = 6, ParamPtr = 7, Param = 8, InterfaceImpl = 9, MemberRef = 10, Constant = 11, CustomAttribute = 12, FieldMarshal = 13, DeclSecurity = 14, ClassLayout = 15, FieldLayout = 16, StandAloneSig = 17, EventMap = 18, EventPtr = 19, Event = 20, PropertyMap = 21, PropertyPtr = 22, Property = 23, MethodSemantics = 24, MethodImpl = 25, ModuleRef = 26, TypeSpec = 27, ImplMap = 28, FieldRva = 29, EncLog = 30, EncMap = 31, Assembly = 32, AssemblyProcessor = 33, AssemblyOS = 34, AssemblyRef = 35, AssemblyRefProcessor = 36, AssemblyRefOS = 37, File = 38, ExportedType = 39, ManifestResource = 40, NestedClass = 41, GenericParam = 42, MethodSpec = 43, GenericParamConstraint = 44, MaxTypeSystemTableIndex = 44, Document = 48, MethodDebugInformation = 49, LocalScope = 50, LocalVariable = 51, LocalConstant = 52, ImportScope = 53, StateMachineMethod = 54, CustomDebugInformation = 55, Max = 56, String = 112 } public static class TableIndexExtensions { public static bool IsValidTableIndex(this TableIndex index) { if ((int)index >= 48) { if ((int)index <= 55 || index == TableIndex.String) { goto IL_0016; } } else if ((int)index <= 44) { goto IL_0016; } return false; IL_0016: return true; } } public readonly struct TableLayout { public IList Columns { get; } public uint RowSize { get; } public TableLayout(params ColumnLayout[] columns) { Columns = new ReadOnlyCollection(columns); RowSize = (uint)columns.Sum((ColumnLayout c) => c.Size); } public override string ToString() { return "(" + StringShim.Join(", ", (IEnumerable)Columns.Select((ColumnLayout c) => c.Name).ToArray()) + ")"; } } [Flags] public enum TypeAttributes : uint { NotPublic = 0u, Public = 1u, NestedPublic = 2u, NestedPrivate = 3u, NestedFamily = 4u, NestedAssembly = 5u, NestedFamilyAndAssembly = 6u, NestedFamilyOrAssembly = 7u, VisibilityMask = 7u, AutoLayout = 0u, SequentialLayout = 8u, ExplicitLayout = 0x10u, LayoutMask = 0x18u, Class = 0u, Interface = 0x20u, ClassSemanticsMask = 0x60u, Abstract = 0x80u, Sealed = 0x100u, SpecialName = 0x400u, RuntimeSpecialName = 0x800u, Import = 0x1000u, Serializable = 0x2000u, AnsiClass = 0u, UnicodeClass = 0x10000u, AutoClass = 0x20000u, CustomFormatClass = 0x30000u, StringFormatMask = 0x30000u, BeforeFieldInit = 0x100000u, Forwarder = 0x200000u, HasSecurity = 0x40000u } public struct TypeDefinitionRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.TypeDef; public int Count => 6; public uint this[int index] => index switch { 0 => (uint)Attributes, 1 => Name, 2 => Namespace, 3 => Extends, 4 => FieldList, 5 => MethodList, _ => throw new IndexOutOfRangeException(), }; public TypeAttributes Attributes { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public uint Extends { get; set; } public uint FieldList { get; set; } public uint MethodList { get; set; } public static TypeDefinitionRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeDefinitionRow((TypeAttributes)((BinaryStreamReader)(ref reader)).ReadUInt32(), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[3].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[4].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[5].Size)); } public TypeDefinitionRow(TypeAttributes attributes, uint name, uint ns, uint extends, uint fieldList, uint methodList) { Attributes = attributes; Name = name; Namespace = ns; Extends = extends; FieldList = fieldList; MethodList = methodList; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteUInt32((uint)Attributes); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Namespace, (IndexSize)layout.Columns[2].Size); writer.WriteIndex(Extends, (IndexSize)layout.Columns[3].Size); writer.WriteIndex(FieldList, (IndexSize)layout.Columns[4].Size); writer.WriteIndex(MethodList, (IndexSize)layout.Columns[5].Size); } public override string ToString() { return $"({Attributes:X8}, {Name:X8}, {Namespace:X8}, {Extends:X8}, {FieldList:X8}, {MethodList:X8})"; } public bool Equals(TypeDefinitionRow other) { if (Attributes == other.Attributes && Name == other.Name && Namespace == other.Namespace && Extends == other.Extends && FieldList == other.FieldList) { return MethodList == other.MethodList; } return false; } public override bool Equals(object? obj) { if (obj is TypeDefinitionRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((((((((uint)((int)Attributes * 397) ^ Name) * 397) ^ Namespace) * 397) ^ Extends) * 397) ^ FieldList) * 397) ^ MethodList); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static class TypeReferenceHash { public static byte[] GetTypeReferenceHash(this PEImage image) { return (image.DotNetDirectory?.Metadata ?? throw new ArgumentException("Portable executable does not contain a .NET image.")).GetTypeReferenceHash(); } public static byte[] GetTypeReferenceHash(this MetadataDirectory metadata) { TablesStream stream = metadata.GetStream(); StringsStream stringsStream = metadata.GetStream(); string[] value = (from row in stream.GetTable(TableIndex.TypeRef) orderby stringsStream.GetStringByIndex(row.Namespace), stringsStream.GetStringByIndex(row.Name) select $"{stringsStream.GetStringByIndex(row.Namespace)}-{stringsStream.GetStringByIndex(row.Name)}").ToArray(); string s = string.Join(",", value); using SHA256 sHA = SHA256.Create(); return sHA.ComputeHash(Encoding.UTF8.GetBytes(s)); } } public struct TypeReferenceRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.TypeRef; public int Count => 3; public uint this[int index] => index switch { 0 => ResolutionScope, 1 => Name, 2 => Namespace, _ => throw new IndexOutOfRangeException(), }; public uint ResolutionScope { get; set; } public uint Name { get; set; } public uint Namespace { get; set; } public static TypeReferenceRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeReferenceRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[1].Size), ((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[2].Size)); } public TypeReferenceRow(uint resolutionScope, uint name, uint ns) { ResolutionScope = resolutionScope; Name = name; Namespace = ns; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(ResolutionScope, (IndexSize)layout.Columns[0].Size); writer.WriteIndex(Name, (IndexSize)layout.Columns[1].Size); writer.WriteIndex(Namespace, (IndexSize)layout.Columns[2].Size); } public override string ToString() { return $"({ResolutionScope:X8}, {Name:X8}, {Namespace:X8})"; } public bool Equals(TypeReferenceRow other) { if (ResolutionScope == other.ResolutionScope && Name == other.Name) { return Namespace == other.Namespace; } return false; } public override bool Equals(object? obj) { if (obj is TypeReferenceRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)((((ResolutionScope * 397) ^ Name) * 397) ^ Namespace); } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct TypeSpecificationRow : IMetadataRow, IReadOnlyList, IEnumerable, IEnumerable, IReadOnlyCollection { public TableIndex TableIndex => TableIndex.ModuleRef; public int Count => 1; public uint this[int index] { get { if (index == 0) { return Signature; } throw new IndexOutOfRangeException(); } } public uint Signature { get; set; } public static TypeSpecificationRow FromReader(ref BinaryStreamReader reader, TableLayout layout) { return new TypeSpecificationRow(((BinaryStreamReader)(ref reader)).ReadIndex((IndexSize)layout.Columns[0].Size)); } public TypeSpecificationRow(uint signature) { Signature = signature; } public void Write(BinaryStreamWriter writer, TableLayout layout) { writer.WriteIndex(Signature, (IndexSize)layout.Columns[0].Size); } public bool Equals(TypeSpecificationRow other) { return Signature == other.Signature; } public override bool Equals(object? obj) { if (obj is TypeSpecificationRow other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Signature; } public override string ToString() { return $"({Signature:X8})"; } public IEnumerator GetEnumerator() { return new MetadataRowColumnEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } namespace AsmResolver.PE.DotNet.Cil { public class CilAssembler { private readonly BinaryStreamWriter _writer; private readonly ICilOperandBuilder _operandBuilder; private readonly Func? _getMethodBodyName; private readonly IErrorListener _errorListener; private string? _diagnosticPrefix; private string? DiagnosticPrefix { get { if (_diagnosticPrefix == null && _getMethodBodyName != null) { string text = _getMethodBodyName(); if (!string.IsNullOrEmpty(text)) { _diagnosticPrefix = "[In " + text + "]: "; } } return _diagnosticPrefix; } } public CilAssembler(BinaryStreamWriter writer, ICilOperandBuilder operandBuilder) : this(writer, operandBuilder, (string?)null, (IErrorListener)(object)ThrowErrorListener.Instance) { } public CilAssembler(BinaryStreamWriter writer, ICilOperandBuilder operandBuilder, string? methodBodyName, IErrorListener errorListener) { _writer = writer ?? throw new ArgumentNullException("writer"); _errorListener = errorListener ?? throw new ArgumentNullException("errorListener"); _operandBuilder = operandBuilder ?? throw new ArgumentNullException("operandBuilder"); _diagnosticPrefix = ((!string.IsNullOrEmpty(methodBodyName)) ? ("[In " + methodBodyName + "]: ") : null); } public CilAssembler(BinaryStreamWriter writer, ICilOperandBuilder operandBuilder, Func? getMethodBodyName, IErrorListener errorListener) { _writer = writer ?? throw new ArgumentNullException("writer"); _errorListener = errorListener ?? throw new ArgumentNullException("errorListener"); _operandBuilder = operandBuilder ?? throw new ArgumentNullException("operandBuilder"); _getMethodBodyName = getMethodBodyName; } public void WriteInstructions(IList instructions) { for (int i = 0; i < instructions.Count; i++) { WriteInstruction(instructions[i]); } } public void WriteInstruction(CilInstruction instruction) { WriteOpCode(instruction.OpCode); WriteOperand(instruction); } private void WriteOpCode(CilOpCode opCode) { _writer.WriteByte(opCode.Byte1); if (opCode.IsLarge) { _writer.WriteByte(opCode.Byte2); } } private void WriteOperand(CilInstruction instruction) { switch (instruction.OpCode.OperandType) { case CilOperandType.ShortInlineI: _writer.WriteSByte(OperandToSByte(instruction)); break; case CilOperandType.InlineI: _writer.WriteInt32(OperandToInt32(instruction)); break; case CilOperandType.InlineI8: _writer.WriteInt64(OperandToInt64(instruction)); break; case CilOperandType.ShortInlineR: _writer.WriteSingle(OperandToFloat32(instruction)); break; case CilOperandType.InlineR: _writer.WriteDouble(OperandToFloat64(instruction)); break; case CilOperandType.ShortInlineVar: _writer.WriteByte((byte)OperandToLocalIndex(instruction)); break; case CilOperandType.InlineVar: _writer.WriteUInt16(OperandToLocalIndex(instruction)); break; case CilOperandType.ShortInlineArgument: _writer.WriteByte((byte)OperandToArgumentIndex(instruction)); break; case CilOperandType.InlineArgument: _writer.WriteUInt16(OperandToArgumentIndex(instruction)); break; case CilOperandType.ShortInlineBrTarget: _writer.WriteSByte((sbyte)OperandToBranchDelta(instruction)); break; case CilOperandType.InlineBrTarget: _writer.WriteInt32(OperandToBranchDelta(instruction)); break; case CilOperandType.InlineSwitch: { IList list = (instruction.Operand as IList) ?? ArrayShim.Empty(); _writer.WriteInt32(list.Count); int num = (int)_writer.Offset + list.Count * 4; for (int i = 0; i < list.Count; i++) { _writer.WriteInt32(list[i].Offset - num); } break; } case CilOperandType.InlineString: _writer.WriteUInt32(_operandBuilder.GetStringToken(instruction.Operand)); break; case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: _writer.WriteUInt32(_operandBuilder.GetMemberToken(instruction.Operand).ToUInt32()); break; default: throw new ArgumentOutOfRangeException(); case CilOperandType.InlineNone: break; } } private int OperandToBranchDelta(CilInstruction instruction) { bool flag = instruction.OpCode.OperandType == CilOperandType.ShortInlineBrTarget; object operand = instruction.Operand; int num3; if (!(operand is sbyte b)) { if (!(operand is int num)) { if (!(operand is ICilLabel cilLabel)) { return ThrowInvalidOperandType(instruction, new Type[2] { typeof(ICilLabel), typeof(sbyte) }); } int num2 = (flag ? 1 : 4); num3 = cilLabel.Offset - (int)((long)_writer.Offset + (long)num2); } else { num3 = num; } } else { num3 = b; } bool flag2 = flag; if (flag2) { bool flag3 = ((num3 < -128 || num3 > 127) ? true : false); flag2 = flag3; } if (flag2) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Branch target at IL_{instruction.Offset:X4} is too far away for a ShortInlineBr instruction.")); } return num3; } private ushort OperandToLocalIndex(CilInstruction instruction) { int variableIndex = _operandBuilder.GetVariableIndex(instruction.Operand); if (instruction.OpCode.OperandType == CilOperandType.ShortInlineVar && variableIndex > 255) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Local index at IL_{instruction.Offset:X4} is too large for a ShortInlineVar instruction.")); } return (ushort)variableIndex; } private ushort OperandToArgumentIndex(CilInstruction instruction) { int argumentIndex = _operandBuilder.GetArgumentIndex(instruction.Operand); if (instruction.OpCode.OperandType == CilOperandType.ShortInlineArgument && argumentIndex > 255) { _errorListener.RegisterException((Exception)new OverflowException($"{DiagnosticPrefix}Argument index at IL_{instruction.Offset:X4} is too large for a ShortInlineArgument instruction.")); } return (ushort)argumentIndex; } private sbyte OperandToSByte(CilInstruction instruction) { object operand = instruction.Operand; if (operand is sbyte) { return (sbyte)operand; } return ThrowInvalidOperandType(instruction, typeof(sbyte)); } private int OperandToInt32(CilInstruction instruction) { object operand = instruction.Operand; if (operand is int) { return (int)operand; } return ThrowInvalidOperandType(instruction, typeof(int)); } private long OperandToInt64(CilInstruction instruction) { object operand = instruction.Operand; if (operand is long) { return (long)operand; } return ThrowInvalidOperandType(instruction, typeof(long)); } private float OperandToFloat32(CilInstruction instruction) { object operand = instruction.Operand; if (operand is float) { return (float)operand; } return ThrowInvalidOperandType(instruction, typeof(float)); } private double OperandToFloat64(CilInstruction instruction) { object operand = instruction.Operand; if (operand is double) { return (double)operand; } return ThrowInvalidOperandType(instruction, typeof(double)); } private T? ThrowInvalidOperandType(CilInstruction instruction, Type expectedOperand) { string value = instruction.Operand?.GetType().Name ?? "null"; _errorListener.RegisterException((Exception)new ArgumentOutOfRangeException($"{DiagnosticPrefix}Expected a {expectedOperand.Name} operand at IL_{instruction.Offset:X4}, but found {value}.")); return default(T); } private T? ThrowInvalidOperandType(CilInstruction instruction, params Type[] expectedOperands) { string[] array = expectedOperands.Select((Type o) => o.Name).ToArray(); string value = ((expectedOperands.Length > 1) ? (StringShim.Join(", ", array.Take(array.Length - 1)) + " or " + array[^1]) : array[0]); string value2 = instruction.Operand?.GetType().Name ?? "null"; _errorListener.RegisterException((Exception)new ArgumentOutOfRangeException($"{DiagnosticPrefix}Expected a {value} operand at IL_{instruction.Offset:X4}, but found {value2}.")); return default(T); } } public enum CilCode : ushort { Nop = 0, Break = 1, Ldarg_0 = 2, Ldarg_1 = 3, Ldarg_2 = 4, Ldarg_3 = 5, Ldloc_0 = 6, Ldloc_1 = 7, Ldloc_2 = 8, Ldloc_3 = 9, Stloc_0 = 10, Stloc_1 = 11, Stloc_2 = 12, Stloc_3 = 13, Ldarg_S = 14, Ldarga_S = 15, Starg_S = 16, Ldloc_S = 17, Ldloca_S = 18, Stloc_S = 19, Ldnull = 20, Ldc_I4_M1 = 21, Ldc_I4_0 = 22, Ldc_I4_1 = 23, Ldc_I4_2 = 24, Ldc_I4_3 = 25, Ldc_I4_4 = 26, Ldc_I4_5 = 27, Ldc_I4_6 = 28, Ldc_I4_7 = 29, Ldc_I4_8 = 30, Ldc_I4_S = 31, Ldc_I4 = 32, Ldc_I8 = 33, Ldc_R4 = 34, Ldc_R8 = 35, Dup = 37, Pop = 38, Jmp = 39, Call = 40, Calli = 41, Ret = 42, Br_S = 43, Brfalse_S = 44, Brtrue_S = 45, Beq_S = 46, Bge_S = 47, Bgt_S = 48, Ble_S = 49, Blt_S = 50, Bne_Un_S = 51, Bge_Un_S = 52, Bgt_Un_S = 53, Ble_Un_S = 54, Blt_Un_S = 55, Br = 56, Brfalse = 57, Brtrue = 58, Beq = 59, Bge = 60, Bgt = 61, Ble = 62, Blt = 63, Bne_Un = 64, Bge_Un = 65, Bgt_Un = 66, Ble_Un = 67, Blt_Un = 68, Switch = 69, Ldind_I1 = 70, Ldind_U1 = 71, Ldind_I2 = 72, Ldind_U2 = 73, Ldind_I4 = 74, Ldind_U4 = 75, Ldind_I8 = 76, Ldind_I = 77, Ldind_R4 = 78, Ldind_R8 = 79, Ldind_Ref = 80, Stind_Ref = 81, Stind_I1 = 82, Stind_I2 = 83, Stind_I4 = 84, Stind_I8 = 85, Stind_R4 = 86, Stind_R8 = 87, Add = 88, Sub = 89, Mul = 90, Div = 91, Div_Un = 92, Rem = 93, Rem_Un = 94, And = 95, Or = 96, Xor = 97, Shl = 98, Shr = 99, Shr_Un = 100, Neg = 101, Not = 102, Conv_I1 = 103, Conv_I2 = 104, Conv_I4 = 105, Conv_I8 = 106, Conv_R4 = 107, Conv_R8 = 108, Conv_U4 = 109, Conv_U8 = 110, Callvirt = 111, Cpobj = 112, Ldobj = 113, Ldstr = 114, Newobj = 115, Castclass = 116, Isinst = 117, Conv_R_Un = 118, Unbox = 121, Throw = 122, Ldfld = 123, Ldflda = 124, Stfld = 125, Ldsfld = 126, Ldsflda = 127, Stsfld = 128, Stobj = 129, Conv_Ovf_I1_Un = 130, Conv_Ovf_I2_Un = 131, Conv_Ovf_I4_Un = 132, Conv_Ovf_I8_Un = 133, Conv_Ovf_U1_Un = 134, Conv_Ovf_U2_Un = 135, Conv_Ovf_U4_Un = 136, Conv_Ovf_U8_Un = 137, Conv_Ovf_I_Un = 138, Conv_Ovf_U_Un = 139, Box = 140, Newarr = 141, Ldlen = 142, Ldelema = 143, Ldelem_I1 = 144, Ldelem_U1 = 145, Ldelem_I2 = 146, Ldelem_U2 = 147, Ldelem_I4 = 148, Ldelem_U4 = 149, Ldelem_I8 = 150, Ldelem_I = 151, Ldelem_R4 = 152, Ldelem_R8 = 153, Ldelem_Ref = 154, Stelem_I = 155, Stelem_I1 = 156, Stelem_I2 = 157, Stelem_I4 = 158, Stelem_I8 = 159, Stelem_R4 = 160, Stelem_R8 = 161, Stelem_Ref = 162, Ldelem = 163, Stelem = 164, Unbox_Any = 165, Conv_Ovf_I1 = 179, Conv_Ovf_U1 = 180, Conv_Ovf_I2 = 181, Conv_Ovf_U2 = 182, Conv_Ovf_I4 = 183, Conv_Ovf_U4 = 184, Conv_Ovf_I8 = 185, Conv_Ovf_U8 = 186, Refanyval = 194, Ckfinite = 195, Mkrefany = 198, Ldtoken = 208, Conv_U2 = 209, Conv_U1 = 210, Conv_I = 211, Conv_Ovf_I = 212, Conv_Ovf_U = 213, Add_Ovf = 214, Add_Ovf_Un = 215, Mul_Ovf = 216, Mul_Ovf_Un = 217, Sub_Ovf = 218, Sub_Ovf_Un = 219, Endfinally = 220, Leave = 221, Leave_S = 222, Stind_I = 223, Conv_U = 224, Prefix7 = 248, Prefix6 = 249, Prefix5 = 250, Prefix4 = 251, Prefix3 = 252, Prefix2 = 253, Prefix1 = 254, Prefixref = 255, Arglist = 65024, Ceq = 65025, Cgt = 65026, Cgt_Un = 65027, Clt = 65028, Clt_Un = 65029, Ldftn = 65030, Ldvirtftn = 65031, Ldarg = 65033, Ldarga = 65034, Starg = 65035, Ldloc = 65036, Ldloca = 65037, Stloc = 65038, Localloc = 65039, Endfilter = 65041, Unaligned = 65042, Volatile = 65043, Tailcall = 65044, Initobj = 65045, Constrained = 65046, Cpblk = 65047, Initblk = 65048, Rethrow = 65050, Sizeof = 65052, Refanytype = 65053, Readonly = 65054 } public static class CilCodeExtensions { public static CilOpCode ToOpCode(this CilCode code) { if ((int)code < 256) { return CilOpCodes.SingleByteOpCodes[(uint)code]; } return CilOpCodes.MultiByteOpCodes[(uint)(code - 65024)]; } } public class CilDisassembler { private readonly ICilOperandResolver _operandResolver; private BinaryStreamReader _reader; public bool ResolveBranchTargets { get; set; } = true; public CilDisassembler(in BinaryStreamReader reader) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _operandResolver = EmptyOperandResolver.Instance; } public CilDisassembler(in BinaryStreamReader reader, ICilOperandResolver operandResolver) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _reader = reader; _operandResolver = operandResolver ?? throw new ArgumentNullException("operandResolver"); } public IList ReadInstructions() { List list = null; List list2 = null; List list3 = new List(); while (((BinaryStreamReader)(ref _reader)).Offset < ((BinaryStreamReader)(ref _reader)).StartOffset + ((BinaryStreamReader)(ref _reader)).Length) { CilInstruction cilInstruction = ReadInstruction(); list3.Add(cilInstruction); if (!ResolveBranchTargets) { continue; } switch (cilInstruction.OpCode.OperandType) { case CilOperandType.InlineBrTarget: case CilOperandType.ShortInlineBrTarget: if (list == null) { list = new List(); } list.Add(cilInstruction); break; case CilOperandType.InlineSwitch: if (list2 == null) { list2 = new List(); } list2.Add(cilInstruction); break; } } if (ResolveBranchTargets) { if (list != null) { foreach (CilInstruction item in list) { item.Operand = TryResolveLabel(list3, (ICilLabel)item.Operand); } } if (list2 != null) { foreach (CilInstruction item2 in list2) { IList list4 = (IList)item2.Operand; for (int i = 0; i < list4.Count; i++) { list4[i] = TryResolveLabel(list3, list4[i]); } } } } return list3; } private static ICilLabel TryResolveLabel(IList instructions, ICilLabel label) { int indexByOffset = instructions.GetIndexByOffset(label.Offset); if (indexByOffset != -1) { label = instructions[indexByOffset].CreateLabel(); } return label; } private CilInstruction ReadInstruction() { uint relativeOffset = ((BinaryStreamReader)(ref _reader)).RelativeOffset; CilOpCode opCode = ReadOpCode(); return new CilInstruction(operand: ReadOperand(opCode.OperandType), offset: (int)relativeOffset, opCode: opCode); } private CilOpCode ReadOpCode() { byte b = ((BinaryStreamReader)(ref _reader)).ReadByte(); if (b != 254) { return CilOpCodes.SingleByteOpCodes[b]; } return CilOpCodes.MultiByteOpCodes[((BinaryStreamReader)(ref _reader)).ReadByte()]; } private object? ReadOperand(CilOperandType operandType) { switch (operandType) { case CilOperandType.InlineNone: return null; case CilOperandType.ShortInlineI: return ((BinaryStreamReader)(ref _reader)).ReadSByte(); case CilOperandType.ShortInlineBrTarget: return new CilOffsetLabel((int)((BinaryStreamReader)(ref _reader)).ReadSByte() + (int)((BinaryStreamReader)(ref _reader)).RelativeOffset); case CilOperandType.ShortInlineVar: { byte b2 = ((BinaryStreamReader)(ref _reader)).ReadByte(); return _operandResolver.ResolveLocalVariable(b2) ?? ((object)b2); } case CilOperandType.ShortInlineArgument: { byte b = ((BinaryStreamReader)(ref _reader)).ReadByte(); return _operandResolver.ResolveParameter(b) ?? ((object)b); } case CilOperandType.InlineVar: { ushort num = ((BinaryStreamReader)(ref _reader)).ReadUInt16(); return _operandResolver.ResolveLocalVariable(num) ?? ((object)num); } case CilOperandType.InlineArgument: { ushort num2 = ((BinaryStreamReader)(ref _reader)).ReadUInt16(); return _operandResolver.ResolveParameter(num2) ?? ((object)num2); } case CilOperandType.InlineI: return ((BinaryStreamReader)(ref _reader)).ReadInt32(); case CilOperandType.InlineBrTarget: return new CilOffsetLabel(((BinaryStreamReader)(ref _reader)).ReadInt32() + (int)((BinaryStreamReader)(ref _reader)).RelativeOffset); case CilOperandType.ShortInlineR: return ((BinaryStreamReader)(ref _reader)).ReadSingle(); case CilOperandType.InlineI8: return ((BinaryStreamReader)(ref _reader)).ReadInt64(); case CilOperandType.InlineR: return ((BinaryStreamReader)(ref _reader)).ReadDouble(); case CilOperandType.InlineString: { MetadataToken metadataToken2 = new MetadataToken(((BinaryStreamReader)(ref _reader)).ReadUInt32()); return _operandResolver.ResolveString(metadataToken2) ?? ((object)metadataToken2); } case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: { MetadataToken metadataToken = new MetadataToken(((BinaryStreamReader)(ref _reader)).ReadUInt32()); return _operandResolver.ResolveMember(metadataToken) ?? ((object)metadataToken); } case CilOperandType.InlinePhi: throw new NotSupportedException(); case CilOperandType.InlineSwitch: return ReadSwitchTable(); default: throw new ArgumentOutOfRangeException("operandType", operandType, null); } } private IList ReadSwitchTable() { int num = ((BinaryStreamReader)(ref _reader)).ReadInt32(); int num2 = (int)((BinaryStreamReader)(ref _reader)).RelativeOffset + num * 4; List list = new List(num); for (int i = 0; i < num; i++) { list.Add(new CilOffsetLabel(num2 + ((BinaryStreamReader)(ref _reader)).ReadInt32())); } return list; } } public class CilExtraSection : SegmentBase { public CilExtraSectionAttributes Attributes { get; set; } public bool IsEHTable { get { return (Attributes & CilExtraSectionAttributes.EHTable) == CilExtraSectionAttributes.EHTable; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.EHTable) | (value ? CilExtraSectionAttributes.EHTable : ((CilExtraSectionAttributes)0)); } } public bool IsOptILTable { get { return (Attributes & CilExtraSectionAttributes.OptILTable) == CilExtraSectionAttributes.OptILTable; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.OptILTable) | (value ? CilExtraSectionAttributes.OptILTable : ((CilExtraSectionAttributes)0)); } } public bool IsFat { get { return (Attributes & CilExtraSectionAttributes.FatFormat) == CilExtraSectionAttributes.FatFormat; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.FatFormat) | (value ? CilExtraSectionAttributes.FatFormat : ((CilExtraSectionAttributes)0)); } } public bool HasMoreSections { get { return (Attributes & CilExtraSectionAttributes.MoreSections) == CilExtraSectionAttributes.MoreSections; } set { Attributes = (Attributes & ~CilExtraSectionAttributes.MoreSections) | (value ? CilExtraSectionAttributes.MoreSections : ((CilExtraSectionAttributes)0)); } } public byte[] Data { get; set; } private CilExtraSection() { Data = ArrayShim.Empty(); } public CilExtraSection(CilExtraSectionAttributes attributes, byte[] data) { Attributes = attributes; Data = data ?? throw new ArgumentNullException("data"); } public static CilExtraSection FromReader(ref BinaryStreamReader reader) { CilExtraSection cilExtraSection = new CilExtraSection(); ((SegmentBase)cilExtraSection).Offset = ((BinaryStreamReader)(ref reader)).Offset; ((SegmentBase)cilExtraSection).Rva = ((BinaryStreamReader)(ref reader)).Rva; cilExtraSection.Attributes = (CilExtraSectionAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); CilExtraSection cilExtraSection2 = cilExtraSection; int num; if (cilExtraSection2.IsFat) { num = ((BinaryStreamReader)(ref reader)).ReadByte() | (((BinaryStreamReader)(ref reader)).ReadByte() << 8) | (((BinaryStreamReader)(ref reader)).ReadByte() << 16); } else { num = ((BinaryStreamReader)(ref reader)).ReadByte(); ((BinaryStreamReader)(ref reader)).ReadUInt16(); } cilExtraSection2.Data = new byte[num]; ((BinaryStreamReader)(ref reader)).ReadBytes(cilExtraSection2.Data, 0, num); return cilExtraSection2; } public override uint GetPhysicalSize() { return (uint)(Data.Length + 4); } public override void Write(BinaryStreamWriter writer) { writer.WriteByte((byte)Attributes); if (IsFat) { writer.WriteByte((byte)((uint)Data.Length & 0xFFu)); writer.WriteByte((byte)((Data.Length & 0xFF00) >> 8)); writer.WriteByte((byte)((Data.Length & 0xFF0000) >> 16)); } else { writer.WriteByte((byte)Data.Length); writer.WriteUInt16((ushort)0); } writer.WriteBytes(Data); } } [Flags] public enum CilExtraSectionAttributes : byte { EHTable = 1, OptILTable = 2, FatFormat = 0x40, MoreSections = 0x80 } public enum CilFlowControl { Branch, Break, Call, ConditionalBranch, Meta, Next, Phi, Return, Throw } public class CilInstruction { public int Offset { get; set; } public CilOpCode OpCode { get; set; } public object? Operand { get; set; } public int Size => OpCode.Size + GetOperandSize(); public CilInstruction(CilOpCode opCode) : this(0, opCode, null) { } public CilInstruction(int offset, CilOpCode opCode) : this(offset, opCode, null) { } public CilInstruction(CilOpCode opCode, object? operand) : this(0, opCode, operand) { } public CilInstruction(int offset, CilOpCode opCode, object? operand) { Offset = offset; OpCode = opCode; Operand = operand; } public static CilInstruction CreateLdcI4(int value) { var (opCode, operand) = GetLdcI4OpCodeOperand(value); return new CilInstruction(opCode, operand); } public static (CilOpCode code, object? operand) GetLdcI4OpCodeOperand(int value) { object item = null; CilOpCode item2; if (value <= 127 && value >= -128) { switch (value) { case -1: item2 = CilOpCodes.Ldc_I4_M1; break; case 0: item2 = CilOpCodes.Ldc_I4_0; break; case 1: item2 = CilOpCodes.Ldc_I4_1; break; case 2: item2 = CilOpCodes.Ldc_I4_2; break; case 3: item2 = CilOpCodes.Ldc_I4_3; break; case 4: item2 = CilOpCodes.Ldc_I4_4; break; case 5: item2 = CilOpCodes.Ldc_I4_5; break; case 6: item2 = CilOpCodes.Ldc_I4_6; break; case 7: item2 = CilOpCodes.Ldc_I4_7; break; case 8: item2 = CilOpCodes.Ldc_I4_8; break; default: item2 = CilOpCodes.Ldc_I4_S; item = (sbyte)value; break; } } else { item2 = CilOpCodes.Ldc_I4; item = value; } return (item2, item); } private int GetOperandSize() { switch (OpCode.OperandType) { case CilOperandType.InlineNone: return 0; case CilOperandType.ShortInlineI: return 1; case CilOperandType.ShortInlineArgument: return 1; case CilOperandType.ShortInlineBrTarget: return 1; case CilOperandType.ShortInlineVar: return 1; case CilOperandType.InlineVar: return 2; case CilOperandType.InlineArgument: return 2; case CilOperandType.InlineBrTarget: return 4; case CilOperandType.InlineI: return 4; case CilOperandType.InlineField: return 4; case CilOperandType.InlineMethod: return 4; case CilOperandType.InlineSig: return 4; case CilOperandType.InlineString: return 4; case CilOperandType.InlineTok: return 4; case CilOperandType.InlineType: return 4; case CilOperandType.InlineI8: return 8; case CilOperandType.ShortInlineR: return 4; case CilOperandType.InlineR: return 8; case CilOperandType.InlineSwitch: if (Operand is IList list) { return (list.Count + 1) * 4; } return 4; case CilOperandType.InlinePhi: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(); } } public override string ToString() { return CilInstructionFormatter.Instance.FormatInstruction(this); } protected bool Equals(CilInstruction other) { if (Offset != other.Offset || !OpCode.Equals(other.OpCode)) { return false; } if (OpCode.Code == CilCode.Switch && Operand is IEnumerable first && other.Operand is IEnumerable second) { return first.SequenceEqual(second); } return object.Equals(Operand, other.Operand); } public override bool Equals(object? obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((CilInstruction)obj); } public override int GetHashCode() { return (((Offset * 397) ^ OpCode.GetHashCode()) * 397) ^ ((Operand != null) ? Operand.GetHashCode() : 0); } public ICilLabel CreateLabel() { return new CilInstructionLabel(this); } public bool IsLdloc() { CilCode code = OpCode.Code; if (code - 6 <= CilCode.Ldarg_1 || code == CilCode.Ldloc_S || code == CilCode.Ldloc) { return true; } return false; } public bool IsStloc() { CilCode code = OpCode.Code; if (code - 10 <= CilCode.Ldarg_1 || code == CilCode.Stloc_S || code == CilCode.Stloc) { return true; } return false; } public bool IsLdarg() { CilCode code = OpCode.Code; if (code - 2 <= CilCode.Ldarg_1 || code == CilCode.Ldarg_S || code == CilCode.Ldarg) { return true; } return false; } public bool IsStarg() { CilCode code = OpCode.Code; if (code == CilCode.Starg_S || code == CilCode.Starg) { return true; } return false; } public bool IsBranch() { CilFlowControl flowControl = OpCode.FlowControl; if (flowControl == CilFlowControl.Branch || flowControl == CilFlowControl.ConditionalBranch) { return true; } return false; } public bool IsUnconditionalBranch() { return OpCode.FlowControl == CilFlowControl.Branch; } public bool IsConditionalBranch() { return OpCode.FlowControl == CilFlowControl.ConditionalBranch; } public bool IsLdcI4() { CilCode code = OpCode.Code; if (code - 21 <= CilCode.Stloc_1) { return true; } return false; } public int GetLdcI4Constant() { return OpCode.Code switch { CilCode.Ldc_I4 => (int)(Operand ?? ((object)0)), CilCode.Ldc_I4_S => (sbyte)(Operand ?? ((object)(sbyte)0)), CilCode.Ldc_I4_0 => 0, CilCode.Ldc_I4_1 => 1, CilCode.Ldc_I4_2 => 2, CilCode.Ldc_I4_3 => 3, CilCode.Ldc_I4_4 => 4, CilCode.Ldc_I4_5 => 5, CilCode.Ldc_I4_6 => 6, CilCode.Ldc_I4_7 => 7, CilCode.Ldc_I4_8 => 8, CilCode.Ldc_I4_M1 => -1, _ => throw new ArgumentOutOfRangeException(), }; } public void ReplaceWith(CilOpCode opCode) { ReplaceWith(opCode, null); } public void ReplaceWith(CilOpCode opCode, object? operand) { OpCode = opCode; Operand = operand; } public void ReplaceWithNop() { ReplaceWith(CilOpCodes.Nop); } } public static class CilInstructionCollectionExtensions { public static int GetIndexByOffset(this IList self, int offset) { int num = 0; int num2 = self.Count - 1; while (num <= num2) { int num3 = (num + num2) / 2; int offset2 = self[num3].Offset; if (offset2 > offset) { num2 = num3 - 1; continue; } if (offset2 < offset) { num = num3 + 1; continue; } return num3; } return -1; } public static CilInstruction? GetByOffset(this IList self, int offset) { int indexByOffset = self.GetIndexByOffset(offset); if (indexByOffset == -1) { return null; } return self[indexByOffset]; } } public class CilInstructionFormatter : ICilInstructionFormatter { private const string InvalidOperandString = "<<>>"; public static CilInstructionFormatter Instance { get; } = new CilInstructionFormatter(); public string FormatInstruction(CilInstruction instruction) { string text = FormatLabel(instruction.Offset) + ": " + FormatOpCode(instruction.OpCode); if (instruction.Operand != null) { return text + " " + FormatOperand(instruction.OpCode.OperandType, instruction.Operand); } return text; } public virtual string FormatLabel(int offset) { return $"IL_{offset:X4}"; } public virtual string FormatOpCode(CilOpCode opcode) { return opcode.Mnemonic.ToLowerInvariant(); } public virtual string FormatOperand(CilOperandType operandType, object? operand) { return operandType switch { CilOperandType.InlineNone => string.Empty, CilOperandType.ShortInlineBrTarget => FormatBranchTarget(operand), CilOperandType.InlineBrTarget => FormatBranchTarget(operand), CilOperandType.InlineType => FormatMember(operand), CilOperandType.InlineField => FormatMember(operand), CilOperandType.InlineMethod => FormatMember(operand), CilOperandType.InlineTok => FormatMember(operand), CilOperandType.InlineSig => FormatSignature(operand), CilOperandType.ShortInlineI => FormatInteger(operand), CilOperandType.InlineI => FormatInteger(operand), CilOperandType.InlineI8 => FormatInteger(operand), CilOperandType.InlineR => FormatFloat(operand), CilOperandType.ShortInlineR => FormatFloat(operand), CilOperandType.InlineString => FormatString(operand), CilOperandType.InlineSwitch => FormatSwitch(operand), CilOperandType.InlineVar => FormatVariable(operand), CilOperandType.ShortInlineVar => FormatVariable(operand), CilOperandType.InlineArgument => FormatArgument(operand), CilOperandType.ShortInlineArgument => FormatArgument(operand), _ => throw new ArgumentOutOfRangeException("operandType", operandType, null), }; } protected virtual string FormatArgument(object? operand) { if (!(operand is short num)) { if (!(operand is byte b)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "A_" + b; } return "A_" + num; } protected virtual string FormatVariable(object? operand) { if (!(operand is short num)) { if (!(operand is byte b)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "V_" + b; } return "V_" + num; } protected virtual string FormatInteger(object? operand) { return Convert.ToString(operand, CultureInfo.InvariantCulture) ?? "<<>>"; } protected virtual string FormatFloat(object? operand) { return Convert.ToString(operand, CultureInfo.InvariantCulture) ?? "<<>>"; } protected virtual string FormatSignature(object? operand) { if (!(operand is MetadataToken token)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatToken(token); } protected virtual string FormatToken(MetadataToken token) { return "TOKEN<0x" + token.ToString() + ">"; } protected virtual string FormatSwitch(object? operand) { if (!(operand is IEnumerable source)) { if (!(operand is IEnumerable source2)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return "(" + StringShim.Join(", ", (IEnumerable)source2.Select((int x) => FormatBranchTarget(x)).ToArray()) + ")"; } return "(" + StringShim.Join(", ", (IEnumerable)source.Select(FormatBranchTarget).ToArray()) + ")"; } protected virtual string FormatString(object? operand) { if (!(operand is string text)) { if (operand is MetadataToken token) { return FormatToken(token); } return "<<>>"; } return Extensions.CreateEscapedString(text); } protected virtual string FormatBranchTarget(object? operand) { if (!(operand is ICilLabel cilLabel)) { if (!(operand is int offset)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatLabel(offset); } return FormatLabel(cilLabel.Offset); } protected virtual string FormatMember(object? operand) { if (!(operand is MetadataToken token)) { if (operand == null) { return "<<>>"; } return operand.ToString() ?? string.Empty; } return FormatToken(token); } } public class CilInstructionLabel : ICilLabel, IEquatable { public CilInstruction? Instruction { get; set; } public int Offset => Instruction?.Offset ?? (-1); public CilInstructionLabel() { } public CilInstructionLabel(CilInstruction instruction) { Instruction = instruction ?? throw new ArgumentNullException("instruction"); } public bool Equals(ICilLabel? other) { if (other != null) { return Offset == other.Offset; } return false; } public override bool Equals(object? obj) { return Equals(obj as ICilLabel); } public override int GetHashCode() { return Offset; } public override string ToString() { if (Instruction != null) { return $"IL_{Offset:X4}"; } return "IL_????"; } } [Flags] public enum CilMethodBodyAttributes : ushort { Tiny = 2, Fat = 3, MoreSections = 8, InitLocals = 0x10 } public class CilOffsetLabel : ICilLabel, IEquatable { public int Offset { get; } public CilOffsetLabel(int offset) { Offset = offset; } public override string ToString() { return $"IL_{Offset:X4}"; } public bool Equals(ICilLabel? other) { if (other != null) { return Offset == other.Offset; } return false; } public override bool Equals(object? obj) { return Equals(obj as ICilLabel); } public override int GetHashCode() { return Offset; } } public readonly struct CilOpCode { internal const int ValueBitLength = 8; internal const int ValueOffset = 0; internal const int TwoBytesBitLength = 1; internal const int TwoBytesOffset = 8; internal const int StackBehaviourBitLength = 5; internal const int StackBehaviourPushOffset = 9; internal const int StackBehaviourPopOffset = 14; internal const int OpCodeTypeBitLength = 3; internal const int OpCodeTypeOffset = 19; internal const int OperandTypeBitLength = 5; internal const int OperandTypeOffset = 22; internal const int FlowControlBitLength = 4; internal const int FlowControlOffset = 27; private readonly uint _value; public bool IsValid { get { if (_value != 0) { return Mnemonic != "unused"; } return false; } } public string Mnemonic => CilOpCodeNames.Names[IsLarge ? (Byte2 + 256) : Byte1]; public CilCode Code => (CilCode)((ushort)(_value & 0xFFu) | (IsLarge ? 65024u : 0u)); public bool IsLarge => ((_value >> 8) & 1) == 1; public int Size { get { if (!IsLarge) { return 1; } return 2; } } public byte Byte1 => (byte)(IsLarge ? 254u : (_value & 0xFFu)); public byte Byte2 => (byte)(IsLarge ? (_value & 0xFFu) : 0u); public CilStackBehaviour StackBehaviourPush => (CilStackBehaviour)((_value >> 9) & 0x1Fu); public CilStackBehaviour StackBehaviourPop => (CilStackBehaviour)((_value >> 14) & 0x1Fu); public CilOpCodeType OpCodeType => (CilOpCodeType)((_value >> 19) & 7u); public CilOperandType OperandType => (CilOperandType)((int)(_value >> 22) & 0x1F); public CilFlowControl FlowControl => (CilFlowControl)((int)(_value >> 27) & 0xF); public static bool operator ==(CilOpCode a, CilOpCode b) { return a.Equals(b); } public static bool operator !=(CilOpCode a, CilOpCode b) { return !(a == b); } internal CilOpCode(uint value) { _value = value; if (IsLarge) { CilOpCodes.MultiByteOpCodes[Byte2] = this; } else { CilOpCodes.SingleByteOpCodes[Byte1] = this; } } public override string ToString() { return Mnemonic; } public bool Equals(CilOpCode other) { return Code == other.Code; } public override bool Equals(object? obj) { if (obj is CilOpCode other) { return Equals(other); } return false; } public override int GetHashCode() { return (int)Code; } } internal static class CilOpCodeNames { internal static readonly string[] Names = new string[291] { "nop", "break", "ldarg.0", "ldarg.1", "ldarg.2", "ldarg.3", "ldloc.0", "ldloc.1", "ldloc.2", "ldloc.3", "stloc.0", "stloc.1", "stloc.2", "stloc.3", "ldarg.s", "ldarga.s", "starg.s", "ldloc.s", "ldloca.s", "stloc.s", "ldnull", "ldc.i4.m1", "ldc.i4.0", "ldc.i4.1", "ldc.i4.2", "ldc.i4.3", "ldc.i4.4", "ldc.i4.5", "ldc.i4.6", "ldc.i4.7", "ldc.i4.8", "ldc.i4.s", "ldc.i4", "ldc.i8", "ldc.r4", "ldc.r8", "unused", "dup", "pop", "jmp", "call", "calli", "ret", "br.s", "brfalse.s", "brtrue.s", "beq.s", "bge.s", "bgt.s", "ble.s", "blt.s", "bne.un.s", "bge.un.s", "bgt.un.s", "ble.un.s", "blt.un.s", "br", "brfalse", "brtrue", "beq", "bge", "bgt", "ble", "blt", "bne.un", "bge.un", "bgt.un", "ble.un", "blt.un", "switch", "ldind.i1", "ldind.u1", "ldind.i2", "ldind.u2", "ldind.i4", "ldind.u4", "ldind.i8", "ldind.i", "ldind.r4", "ldind.r8", "ldind.ref", "stind.ref", "stind.i1", "stind.i2", "stind.i4", "stind.i8", "stind.r4", "stind.r8", "add", "sub", "mul", "div", "div.un", "rem", "rem.un", "and", "or", "xor", "shl", "shr", "shr.un", "neg", "not", "conv.i1", "conv.i2", "conv.i4", "conv.i8", "conv.r4", "conv.r8", "conv.u4", "conv.u8", "callvirt", "cpobj", "ldobj", "ldstr", "newobj", "castclass", "isinst", "conv.r.un", "unused", "unused", "unbox", "throw", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda", "stsfld", "stobj", "conv.ovf.i1.un", "conv.ovf.i2.un", "conv.ovf.i4.un", "conv.ovf.i8.un", "conv.ovf.u1.un", "conv.ovf.u2.un", "conv.ovf.u4.un", "conv.ovf.u8.un", "conv.ovf.i.un", "conv.ovf.u.un", "box", "newarr", "ldlen", "ldelema", "ldelem.i1", "ldelem.u1", "ldelem.i2", "ldelem.u2", "ldelem.i4", "ldelem.u4", "ldelem.i8", "ldelem.i", "ldelem.r4", "ldelem.r8", "ldelem.ref", "stelem.i", "stelem.i1", "stelem.i2", "stelem.i4", "stelem.i8", "stelem.r4", "stelem.r8", "stelem.ref", "ldelem", "stelem", "unbox.any", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "conv.ovf.i1", "conv.ovf.u1", "conv.ovf.i2", "conv.ovf.u2", "conv.ovf.i4", "conv.ovf.u4", "conv.ovf.i8", "conv.ovf.u8", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "refanyval", "ckfinite", "unused", "unused", "mkrefany", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "ldtoken", "conv.u2", "conv.u1", "conv.i", "conv.ovf.i", "conv.ovf.u", "add.ovf", "add.ovf.un", "mul.ovf", "mul.ovf.un", "sub.ovf", "sub.ovf.un", "endfinally", "leave", "leave.s", "stind.i", "conv.u", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "unused", "prefix7", "prefix6", "prefix5", "prefix4", "prefix3", "prefix2", "prefix1", "prefixref", "arglist", "ceq", "cgt", "cgt.un", "clt", "clt.un", "ldftn", "ldvirtftn", "unused", "ldarg", "ldarga", "starg", "ldloc", "ldloca", "stloc", "localloc", "unused", "endfilter", "unaligned.", "volatile.", "tail.", "initobj", "constrained.", "cpblk", "initblk", "unused", "rethrow", "unused", "sizeof", "refanytype", "readonly.", "unused", "unused", "unused", "unused" }; } public static class CilOpCodes { public static readonly CilOpCode[] SingleByteOpCodes = new CilOpCode[256]; public static readonly CilOpCode[] MultiByteOpCodes = new CilOpCode[256]; public static readonly CilOpCode Nop = new CilOpCode(694691840u); public static readonly CilOpCode Break = new CilOpCode(157820929u); public static readonly CilOpCode Ldarg_0 = new CilOpCode(692595202u); public static readonly CilOpCode Ldarg_1 = new CilOpCode(692595203u); public static readonly CilOpCode Ldarg_2 = new CilOpCode(692595204u); public static readonly CilOpCode Ldarg_3 = new CilOpCode(692595205u); public static readonly CilOpCode Ldloc_0 = new CilOpCode(692595206u); public static readonly CilOpCode Ldloc_1 = new CilOpCode(692595207u); public static readonly CilOpCode Ldloc_2 = new CilOpCode(692595208u); public static readonly CilOpCode Ldloc_3 = new CilOpCode(692595209u); public static readonly CilOpCode Stloc_0 = new CilOpCode(692611082u); public static readonly CilOpCode Stloc_1 = new CilOpCode(692611083u); public static readonly CilOpCode Stloc_2 = new CilOpCode(692611084u); public static readonly CilOpCode Stloc_3 = new CilOpCode(692611085u); public static readonly CilOpCode Ldarg_S = new CilOpCode(755509774u); public static readonly CilOpCode Ldarga_S = new CilOpCode(755510799u); public static readonly CilOpCode Starg_S = new CilOpCode(755525648u); public static readonly CilOpCode Ldloc_S = new CilOpCode(747121169u); public static readonly CilOpCode Ldloca_S = new CilOpCode(747122194u); public static readonly CilOpCode Stloc_S = new CilOpCode(747137043u); public static readonly CilOpCode Ldnull = new CilOpCode(694695444u); public static readonly CilOpCode Ldc_I4_M1 = new CilOpCode(692596245u); public static readonly CilOpCode Ldc_I4_0 = new CilOpCode(692596246u); public static readonly CilOpCode Ldc_I4_1 = new CilOpCode(692596247u); public static readonly CilOpCode Ldc_I4_2 = new CilOpCode(692596248u); public static readonly CilOpCode Ldc_I4_3 = new CilOpCode(692596249u); public static readonly CilOpCode Ldc_I4_4 = new CilOpCode(692596250u); public static readonly CilOpCode Ldc_I4_5 = new CilOpCode(692596251u); public static readonly CilOpCode Ldc_I4_6 = new CilOpCode(692596252u); public static readonly CilOpCode Ldc_I4_7 = new CilOpCode(692596253u); public static readonly CilOpCode Ldc_I4_8 = new CilOpCode(692596254u); public static readonly CilOpCode Ldc_I4_S = new CilOpCode(738733599u); public static readonly CilOpCode Ldc_I4 = new CilOpCode(682110496u); public static readonly CilOpCode Ldc_I8 = new CilOpCode(686305313u); public static readonly CilOpCode Ldc_R4 = new CilOpCode(745026082u); public static readonly CilOpCode Ldc_R8 = new CilOpCode(703083555u); public static readonly CilOpCode Dup = new CilOpCode(694709285u); public static readonly CilOpCode Pop = new CilOpCode(694708262u); public static readonly CilOpCode Jmp = new CilOpCode(287844391u); public static readonly CilOpCode Call = new CilOpCode(288307752u); public static readonly CilOpCode Calli = new CilOpCode(309279273u); public static readonly CilOpCode Ret = new CilOpCode(963586090u); public static readonly CilOpCode Br_S = new CilOpCode(63449131u); public static readonly CilOpCode Brfalse_S = new CilOpCode(466151468u); public static readonly CilOpCode Brtrue_S = new CilOpCode(466151469u); public static readonly CilOpCode Beq_S = new CilOpCode(466135086u); public static readonly CilOpCode Bge_S = new CilOpCode(466135087u); public static readonly CilOpCode Bgt_S = new CilOpCode(466135088u); public static readonly CilOpCode Ble_S = new CilOpCode(466135089u); public static readonly CilOpCode Blt_S = new CilOpCode(466135090u); public static readonly CilOpCode Bne_Un_S = new CilOpCode(466135091u); public static readonly CilOpCode Bge_Un_S = new CilOpCode(466135092u); public static readonly CilOpCode Bgt_Un_S = new CilOpCode(466135093u); public static readonly CilOpCode Ble_Un_S = new CilOpCode(466135094u); public static readonly CilOpCode Blt_Un_S = new CilOpCode(466135095u); public static readonly CilOpCode Br = new CilOpCode(2631736u); public static readonly CilOpCode Brfalse = new CilOpCode(405334073u); public static readonly CilOpCode Brtrue = new CilOpCode(405334074u); public static readonly CilOpCode Beq = new CilOpCode(403220539u); public static readonly CilOpCode Bge = new CilOpCode(403220540u); public static readonly CilOpCode Bgt = new CilOpCode(403220541u); public static readonly CilOpCode Ble = new CilOpCode(403220542u); public static readonly CilOpCode Blt = new CilOpCode(403220543u); public static readonly CilOpCode Bne_Un = new CilOpCode(403220544u); public static readonly CilOpCode Bge_Un = new CilOpCode(403220545u); public static readonly CilOpCode Bgt_Un = new CilOpCode(403220546u); public static readonly CilOpCode Ble_Un = new CilOpCode(403220547u); public static readonly CilOpCode Blt_Un = new CilOpCode(403220548u); public static readonly CilOpCode Switch = new CilOpCode(451471429u); public static readonly CilOpCode Ldind_I1 = new CilOpCode(694742598u); public static readonly CilOpCode Ldind_U1 = new CilOpCode(694742599u); public static readonly CilOpCode Ldind_I2 = new CilOpCode(694742600u); public static readonly CilOpCode Ldind_U2 = new CilOpCode(694742601u); public static readonly CilOpCode Ldind_I4 = new CilOpCode(694742602u); public static readonly CilOpCode Ldind_U4 = new CilOpCode(694742603u); public static readonly CilOpCode Ldind_I8 = new CilOpCode(694743116u); public static readonly CilOpCode Ldind_I = new CilOpCode(694742605u); public static readonly CilOpCode Ldind_R4 = new CilOpCode(694743630u); public static readonly CilOpCode Ldind_R8 = new CilOpCode(694744143u); public static readonly CilOpCode Ldind_Ref = new CilOpCode(694744656u); public static readonly CilOpCode Stind_Ref = new CilOpCode(694773841u); public static readonly CilOpCode Stind_I1 = new CilOpCode(694773842u); public static readonly CilOpCode Stind_I2 = new CilOpCode(694773843u); public static readonly CilOpCode Stind_I4 = new CilOpCode(694773844u); public static readonly CilOpCode Stind_I8 = new CilOpCode(694790229u); public static readonly CilOpCode Stind_R4 = new CilOpCode(694822998u); public static readonly CilOpCode Stind_R8 = new CilOpCode(694839383u); public static readonly CilOpCode Add = new CilOpCode(694725208u); public static readonly CilOpCode Sub = new CilOpCode(694725209u); public static readonly CilOpCode Mul = new CilOpCode(694725210u); public static readonly CilOpCode Div = new CilOpCode(694725211u); public static readonly CilOpCode Div_Un = new CilOpCode(694725212u); public static readonly CilOpCode Rem = new CilOpCode(694725213u); public static readonly CilOpCode Rem_Un = new CilOpCode(694725214u); public static readonly CilOpCode And = new CilOpCode(694725215u); public static readonly CilOpCode Or = new CilOpCode(694725216u); public static readonly CilOpCode Xor = new CilOpCode(694725217u); public static readonly CilOpCode Shl = new CilOpCode(694725218u); public static readonly CilOpCode Shr = new CilOpCode(694725219u); public static readonly CilOpCode Shr_Un = new CilOpCode(694725220u); public static readonly CilOpCode Neg = new CilOpCode(694708837u); public static readonly CilOpCode Not = new CilOpCode(694708838u); public static readonly CilOpCode Conv_I1 = new CilOpCode(694709863u); public static readonly CilOpCode Conv_I2 = new CilOpCode(694709864u); public static readonly CilOpCode Conv_I4 = new CilOpCode(694709865u); public static readonly CilOpCode Conv_I8 = new CilOpCode(694710378u); public static readonly CilOpCode Conv_R4 = new CilOpCode(694710891u); public static readonly CilOpCode Conv_R8 = new CilOpCode(694711404u); public static readonly CilOpCode Conv_U4 = new CilOpCode(694709869u); public static readonly CilOpCode Conv_U8 = new CilOpCode(694710382u); public static readonly CilOpCode Callvirt = new CilOpCode(287259247u); public static readonly CilOpCode Cpobj = new CilOpCode(727279728u); public static readonly CilOpCode Ldobj = new CilOpCode(727247473u); public static readonly CilOpCode Ldstr = new CilOpCode(714618482u); public static readonly CilOpCode Newobj = new CilOpCode(287258227u); public static readonly CilOpCode Castclass = new CilOpCode(727365236u); public static readonly CilOpCode Isinst = new CilOpCode(727363189u); public static readonly CilOpCode Conv_R_Un = new CilOpCode(694711414u); public static readonly CilOpCode Unbox = new CilOpCode(728411769u); public static readonly CilOpCode Throw = new CilOpCode(1096460410u); public static readonly CilOpCode Ldfld = new CilOpCode(677030523u); public static readonly CilOpCode Ldflda = new CilOpCode(677031548u); public static readonly CilOpCode Stfld = new CilOpCode(677046397u); public static readonly CilOpCode Ldsfld = new CilOpCode(676866686u); public static readonly CilOpCode Ldsflda = new CilOpCode(676867711u); public static readonly CilOpCode Stsfld = new CilOpCode(676882560u); public static readonly CilOpCode Stobj = new CilOpCode(728311937u); public static readonly CilOpCode Conv_Ovf_I1_Un = new CilOpCode(694709890u); public static readonly CilOpCode Conv_Ovf_I2_Un = new CilOpCode(694709891u); public static readonly CilOpCode Conv_Ovf_I4_Un = new CilOpCode(694709892u); public static readonly CilOpCode Conv_Ovf_I8_Un = new CilOpCode(694710405u); public static readonly CilOpCode Conv_Ovf_U1_Un = new CilOpCode(694709894u); public static readonly CilOpCode Conv_Ovf_U2_Un = new CilOpCode(694709895u); public static readonly CilOpCode Conv_Ovf_U4_Un = new CilOpCode(694709896u); public static readonly CilOpCode Conv_Ovf_U8_Un = new CilOpCode(694710409u); public static readonly CilOpCode Conv_Ovf_I_Un = new CilOpCode(694709898u); public static readonly CilOpCode Conv_Ovf_U_Un = new CilOpCode(694709899u); public static readonly CilOpCode Box = new CilOpCode(728266380u); public static readonly CilOpCode Newarr = new CilOpCode(727250573u); public static readonly CilOpCode Ldlen = new CilOpCode(693808782u); public static readonly CilOpCode Ldelema = new CilOpCode(727395983u); public static readonly CilOpCode Ldelem_I1 = new CilOpCode(693841552u); public static readonly CilOpCode Ldelem_U1 = new CilOpCode(693841553u); public static readonly CilOpCode Ldelem_I2 = new CilOpCode(693841554u); public static readonly CilOpCode Ldelem_U2 = new CilOpCode(693841555u); public static readonly CilOpCode Ldelem_I4 = new CilOpCode(693841556u); public static readonly CilOpCode Ldelem_U4 = new CilOpCode(693841557u); public static readonly CilOpCode Ldelem_I8 = new CilOpCode(693842070u); public static readonly CilOpCode Ldelem_I = new CilOpCode(693841559u); public static readonly CilOpCode Ldelem_R4 = new CilOpCode(693842584u); public static readonly CilOpCode Ldelem_R8 = new CilOpCode(693843097u); public static readonly CilOpCode Ldelem_Ref = new CilOpCode(693843610u); public static readonly CilOpCode Stelem_I = new CilOpCode(693856411u); public static readonly CilOpCode Stelem_I1 = new CilOpCode(693856412u); public static readonly CilOpCode Stelem_I2 = new CilOpCode(693856413u); public static readonly CilOpCode Stelem_I4 = new CilOpCode(693856414u); public static readonly CilOpCode Stelem_I8 = new CilOpCode(693872799u); public static readonly CilOpCode Stelem_R4 = new CilOpCode(693889184u); public static readonly CilOpCode Stelem_R8 = new CilOpCode(693905569u); public static readonly CilOpCode Stelem_Ref = new CilOpCode(693921954u); public static readonly CilOpCode Ldelem = new CilOpCode(727394979u); public static readonly CilOpCode Stelem = new CilOpCode(727492772u); public static readonly CilOpCode Unbox_Any = new CilOpCode(727362213u); public static readonly CilOpCode Conv_Ovf_I1 = new CilOpCode(694709939u); public static readonly CilOpCode Conv_Ovf_U1 = new CilOpCode(694709940u); public static readonly CilOpCode Conv_Ovf_I2 = new CilOpCode(694709941u); public static readonly CilOpCode Conv_Ovf_U2 = new CilOpCode(694709942u); public static readonly CilOpCode Conv_Ovf_I4 = new CilOpCode(694709943u); public static readonly CilOpCode Conv_Ovf_U4 = new CilOpCode(694709944u); public static readonly CilOpCode Conv_Ovf_I8 = new CilOpCode(694710457u); public static readonly CilOpCode Conv_Ovf_U8 = new CilOpCode(694710458u); public static readonly CilOpCode Refanyval = new CilOpCode(728264386u); public static readonly CilOpCode Ckfinite = new CilOpCode(694711491u); public static readonly CilOpCode Mkrefany = new CilOpCode(728296134u); public static readonly CilOpCode Ldtoken = new CilOpCode(724053712u); public static readonly CilOpCode Conv_U2 = new CilOpCode(694709969u); public static readonly CilOpCode Conv_U1 = new CilOpCode(694709970u); public static readonly CilOpCode Conv_I = new CilOpCode(694709971u); public static readonly CilOpCode Conv_Ovf_I = new CilOpCode(694709972u); public static readonly CilOpCode Conv_Ovf_U = new CilOpCode(694709973u); public static readonly CilOpCode Add_Ovf = new CilOpCode(694725334u); public static readonly CilOpCode Add_Ovf_Un = new CilOpCode(694725335u); public static readonly CilOpCode Mul_Ovf = new CilOpCode(694725336u); public static readonly CilOpCode Mul_Ovf_Un = new CilOpCode(694725337u); public static readonly CilOpCode Sub_Ovf = new CilOpCode(694725338u); public static readonly CilOpCode Sub_Ovf_Un = new CilOpCode(694725339u); public static readonly CilOpCode Endfinally = new CilOpCode(963438812u); public static readonly CilOpCode Leave = new CilOpCode(2943197u); public static readonly CilOpCode Leave_S = new CilOpCode(65857758u); public static readonly CilOpCode Stind_I = new CilOpCode(694773983u); public static readonly CilOpCode Conv_U = new CilOpCode(694709984u); public static readonly CilOpCode Prefix7 = new CilOpCode(558901496u); public static readonly CilOpCode Prefix6 = new CilOpCode(558901497u); public static readonly CilOpCode Prefix5 = new CilOpCode(558901498u); public static readonly CilOpCode Prefix4 = new CilOpCode(558901499u); public static readonly CilOpCode Prefix3 = new CilOpCode(558901500u); public static readonly CilOpCode Prefix2 = new CilOpCode(558901501u); public static readonly CilOpCode Prefix1 = new CilOpCode(558901502u); public static readonly CilOpCode Prefixref = new CilOpCode(558901503u); public static readonly CilOpCode Arglist = new CilOpCode(694693632u); public static readonly CilOpCode Ceq = new CilOpCode(694726401u); public static readonly CilOpCode Cgt = new CilOpCode(694726402u); public static readonly CilOpCode Cgt_Un = new CilOpCode(694726403u); public static readonly CilOpCode Clt = new CilOpCode(694726404u); public static readonly CilOpCode Clt_Un = new CilOpCode(694726405u); public static readonly CilOpCode Ldftn = new CilOpCode(690499334u); public static readonly CilOpCode Ldvirtftn = new CilOpCode(690663175u); public static readonly CilOpCode Ldarg = new CilOpCode(753412873u); public static readonly CilOpCode Ldarga = new CilOpCode(753413898u); public static readonly CilOpCode Starg = new CilOpCode(753428747u); public static readonly CilOpCode Ldloc = new CilOpCode(732441356u); public static readonly CilOpCode Ldloca = new CilOpCode(732442381u); public static readonly CilOpCode Stloc = new CilOpCode(732457230u); public static readonly CilOpCode Localloc = new CilOpCode(694742799u); public static readonly CilOpCode Endfilter = new CilOpCode(963176721u); public static readonly CilOpCode Unaligned = new CilOpCode(606087442u); public static readonly CilOpCode Volatile = new CilOpCode(559950099u); public static readonly CilOpCode Tailcall = new CilOpCode(559950100u); public static readonly CilOpCode Initobj = new CilOpCode(727247125u); public static readonly CilOpCode Constrained = new CilOpCode(593504534u); public static readonly CilOpCode Cpblk = new CilOpCode(694806807u); public static readonly CilOpCode Initblk = new CilOpCode(694806808u); public static readonly CilOpCode Rethrow = new CilOpCode(1096296730u); public static readonly CilOpCode Sizeof = new CilOpCode(728248092u); public static readonly CilOpCode Refanytype = new CilOpCode(694710045u); public static readonly CilOpCode Readonly = new CilOpCode(559950110u); } public enum CilOpCodeType : byte { Annotation, Macro, Internal, ObjModel, Prefix, Primitive } public enum CilOperandType { InlineBrTarget = 0, InlineField = 1, InlineI = 2, InlineI8 = 3, InlineMethod = 4, InlineNone = 5, InlinePhi = 6, InlineR = 7, InlineSig = 9, InlineString = 10, InlineSwitch = 11, InlineTok = 12, InlineType = 13, InlineVar = 14, ShortInlineBrTarget = 15, ShortInlineI = 16, ShortInlineR = 17, ShortInlineVar = 18, InlineArgument = 19, ShortInlineArgument = 20 } public class CilRawFatMethodBody : CilRawMethodBody { private CilMethodBodyAttributes _attributes; public override bool IsFat => true; public CilMethodBodyAttributes Attributes { get { return _attributes; } set { _attributes = value | CilMethodBodyAttributes.Fat; } } public bool HasSections { get { return (Attributes & CilMethodBodyAttributes.MoreSections) != 0; } set { Attributes = (Attributes & ~CilMethodBodyAttributes.MoreSections) | (value ? CilMethodBodyAttributes.MoreSections : ((CilMethodBodyAttributes)0)); } } public bool InitLocals { get { return (Attributes & CilMethodBodyAttributes.InitLocals) != 0; } set { Attributes = (Attributes & ~CilMethodBodyAttributes.InitLocals) | (value ? CilMethodBodyAttributes.InitLocals : ((CilMethodBodyAttributes)0)); } } public ushort MaxStack { get; set; } public MetadataToken LocalVarSigToken { get; set; } public IList ExtraSections { get; } = new List(); public CilRawFatMethodBody(CilMethodBodyAttributes attributes, ushort maxStack, MetadataToken localVarSigToken, IReadableSegment code) : base(code) { Attributes = attributes; MaxStack = maxStack; LocalVarSigToken = localVarSigToken; } public new static CilRawFatMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; ushort num = ((BinaryStreamReader)(ref reader)).ReadUInt16(); CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)(num & 0xFFFu); int num2 = (num >> 12) * 4; if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Fat) != CilMethodBodyAttributes.Fat) { ErrorListenerExtensions.BadImage(errorListener, "Invalid fat CIL method body header."); return null; } ushort maxStack = ((BinaryStreamReader)(ref reader)).ReadUInt16(); uint num3 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); uint num4 = ((BinaryStreamReader)(ref reader)).ReadUInt32(); ((BinaryStreamReader)(ref reader)).Offset = offset + (ulong)num2; if (((BinaryStreamReader)(ref reader)).Offset + num3 > ((BinaryStreamReader)(ref reader)).StartOffset + ((BinaryStreamReader)(ref reader)).Length) { ErrorListenerExtensions.BadImage(errorListener, "Invalid fat CIL method body code size."); return null; } IReadableSegment code = ((BinaryStreamReader)(ref reader)).ReadSegment(num3); CilRawFatMethodBody cilRawFatMethodBody = new CilRawFatMethodBody(cilMethodBodyAttributes, maxStack, num4, code); RelocationParameters val = new RelocationParameters(offset, rva); ((SegmentBase)cilRawFatMethodBody).UpdateOffsets(ref val); if (cilRawFatMethodBody.HasSections) { ((BinaryStreamReader)(ref reader)).Align(4u); CilExtraSection cilExtraSection; do { cilExtraSection = CilExtraSection.FromReader(ref reader); cilRawFatMethodBody.ExtraSections.Add(cilExtraSection); } while (cilExtraSection.HasMoreSections); } return cilRawFatMethodBody; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(12u); ((ISegment)base.Code).UpdateOffsets(ref val); if (HasSections) { uint physicalSize = ((IWritable)base.Code).GetPhysicalSize(); ((RelocationParameters)(ref val)).Advance(physicalSize); ((RelocationParameters)(ref val)).Align(4u); for (int i = 0; i < ExtraSections.Count; i++) { ((SegmentBase)ExtraSections[i]).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(((SegmentBase)ExtraSections[i]).GetPhysicalSize()); } } } public override uint GetPhysicalSize() { uint num = 12 + ((IWritable)base.Code).GetPhysicalSize(); ulong num2 = ((SegmentBase)this).Offset + num; if (HasSections) { ulong num3 = Extensions.Align(num2, 4uL); num += (uint)(int)(num3 - num2); for (int i = 0; i < ExtraSections.Count; i++) { num += ((SegmentBase)ExtraSections[i]).GetPhysicalSize(); } } return num; } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt16((ushort)(_attributes | (CilMethodBodyAttributes)12288)); writer.WriteUInt16(MaxStack); writer.WriteUInt32(((IWritable)base.Code).GetPhysicalSize()); writer.WriteUInt32(LocalVarSigToken.ToUInt32()); ((IWritable)base.Code).Write(writer); if (HasSections) { writer.Align(4u); for (int i = 0; i < ExtraSections.Count; i++) { ((SegmentBase)ExtraSections[i]).Write(writer); } } } } public abstract class CilRawMethodBody : SegmentBase { public abstract bool IsFat { get; } public IReadableSegment Code { get; set; } protected CilRawMethodBody(IReadableSegment code) { Code = code; } public static CilRawMethodBody? FromReader(ref BinaryStreamReader reader) { return FromReader((IErrorListener)(object)ThrowErrorListener.Instance, ref reader); } public static CilRawMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); ulong offset = ((BinaryStreamReader)(ref reader)).Offset; ((BinaryStreamReader)(ref reader)).Offset = offset - 1; if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Fat) == CilMethodBodyAttributes.Fat) { return CilRawFatMethodBody.FromReader(errorListener, ref reader); } if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Tiny) == CilMethodBodyAttributes.Tiny) { return CilRawTinyMethodBody.FromReader(errorListener, ref reader); } throw new NotSupportedException("Invalid or unsupported method body format."); } } public class CilRawTinyMethodBody : CilRawMethodBody { public override bool IsFat => false; public CilRawTinyMethodBody(byte[] code) : base((IReadableSegment)new DataSegment(code)) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown public CilRawTinyMethodBody(IReadableSegment code) : base(code) { } public new static CilRawTinyMethodBody? FromReader(IErrorListener errorListener, ref BinaryStreamReader reader) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) ulong offset = ((BinaryStreamReader)(ref reader)).Offset; uint rva = ((BinaryStreamReader)(ref reader)).Rva; CilMethodBodyAttributes cilMethodBodyAttributes = (CilMethodBodyAttributes)((BinaryStreamReader)(ref reader)).ReadByte(); if ((cilMethodBodyAttributes & CilMethodBodyAttributes.Tiny) != CilMethodBodyAttributes.Tiny) { ErrorListenerExtensions.BadImage(errorListener, "Invalid tiny CIL method body header."); return null; } uint num = (uint)cilMethodBodyAttributes >> 2; CilRawTinyMethodBody cilRawTinyMethodBody = new CilRawTinyMethodBody(((BinaryStreamReader)(ref reader)).ReadSegment(num)); RelocationParameters val = new RelocationParameters(offset, rva); ((SegmentBase)cilRawTinyMethodBody).UpdateOffsets(ref val); return cilRawTinyMethodBody; } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); IReadableSegment code = base.Code; RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(1u); ((ISegment)code).UpdateOffsets(ref val); } public override uint GetPhysicalSize() { return 1 + ((IWritable)base.Code).GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { uint physicalSize = ((IWritable)base.Code).GetPhysicalSize(); if (physicalSize > 63) { throw new ArgumentException("Code of a tiny method body cannot be 64 bytes or larger."); } byte b = (byte)(2u | (physicalSize << 2)); writer.WriteByte(b); IReadableSegment code = base.Code; if (code != null) { ((IWritable)code).Write(writer); } } } public enum CilStackBehaviour : byte { Pop0, Pop1, Pop1_Pop1, PopI, PopI_Pop1, PopI_PopI, PopI_PopI8, PopI_PopI_PopI, PopI_PopR4, PopI_PopR8, PopRef, PopRef_Pop1, PopRef_PopI, PopRef_PopI_PopI, PopRef_PopI_PopI8, PopRef_PopI_PopR4, PopRef_PopI_PopR8, PopRef_PopI_PopRef, PopRef_PopI_Pop1, PopAll, Push0, Push1, Push1_Push1, PushI, PushI8, PushR4, PushR8, PushRef, VarPop, VarPush } public sealed class EmptyOperandResolver : ICilOperandResolver { public static EmptyOperandResolver Instance { get; } = new EmptyOperandResolver(); private EmptyOperandResolver() { } public object? ResolveMember(MetadataToken token) { return null; } public object? ResolveString(MetadataToken token) { return null; } public object? ResolveLocalVariable(int index) { return null; } public object? ResolveParameter(int index) { return null; } } public interface ICilInstructionFormatter { string FormatInstruction(CilInstruction instruction); } public interface ICilLabel : IEquatable { int Offset { get; } } public interface ICilOperandBuilder { int GetVariableIndex(object? operand); int GetArgumentIndex(object? operand); uint GetStringToken(object? operand); MetadataToken GetMemberToken(object? operand); } public interface ICilOperandResolver { object? ResolveMember(MetadataToken token); object? ResolveString(MetadataToken token); object? ResolveLocalVariable(int index); object? ResolveParameter(int index); } } namespace AsmResolver.PE.Debug { public abstract class CodeViewDataSegment : SegmentBase, IDebugDataSegment, ISegment, IOffsetProvider, IWritable { public abstract CodeViewSignature Signature { get; } public DebugDataType Type => DebugDataType.CodeView; public static CodeViewDataSegment? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { return (CodeViewSignature)((BinaryStreamReader)(ref reader)).ReadUInt32() switch { CodeViewSignature.Rsds => RsdsDataSegment.FromReader(context, ref reader), CodeViewSignature.Nb05 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb09 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb10 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), CodeViewSignature.Nb11 => ErrorListenerExtensions.NotSupportedAndReturn((IErrorListener)(object)context), _ => ErrorListenerExtensions.BadImageAndReturn((IErrorListener)(object)context, "Invalid code view debug data signature."), }; } } public enum CodeViewSignature { Rsds = 1396986706, Nb05 = 892355150, Nb09 = 959464014, Nb10 = 808534606, Nb11 = 825311822 } public class CustomDebugDataSegment : IDebugDataSegment, ISegment, IOffsetProvider, IWritable { public DebugDataType Type { get; } public ISegment? Contents { get; set; } public ulong Offset { get { ISegment? contents = Contents; if (contents == null) { return 0uL; } return ((IOffsetProvider)contents).Offset; } } public uint Rva { get { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IOffsetProvider)contents).Rva; } } public bool CanUpdateOffsets { get { ISegment? contents = Contents; if (contents == null) { return false; } return contents.CanUpdateOffsets; } } public CustomDebugDataSegment(DebugDataType type, ISegment contents) { Type = type; Contents = contents ?? throw new ArgumentNullException("contents"); } public void UpdateOffsets(in RelocationParameters parameters) { if (Contents != null) { Contents.UpdateOffsets(ref parameters); return; } throw new ArgumentNullException("Contents"); } public uint GetPhysicalSize() { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IWritable)contents).GetPhysicalSize(); } public uint GetVirtualSize() { ISegment? contents = Contents; if (contents == null) { return 0u; } return ((IWritable)contents).GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { ISegment? contents = Contents; if (contents != null) { ((IWritable)contents).Write(writer); } } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public class DebugDataEntry : SegmentBase { public const uint DebugDataEntryHeaderSize = 28u; private readonly LazyVariable _contents; public uint Characteristics { get; set; } public uint TimeDateStamp { get; set; } public ushort MajorVersion { get; set; } public ushort MinorVersion { get; set; } public IDebugDataSegment? Contents { get { return _contents.GetValue(this); } set { _contents.SetValue(value); } } protected DebugDataEntry() { _contents = new LazyVariable((Func)((DebugDataEntry x) => x.GetContents())); } public DebugDataEntry(IDebugDataSegment contents) { _contents = new LazyVariable(contents); } protected virtual IDebugDataSegment? GetContents() { return null; } public override uint GetPhysicalSize() { return 28u; } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32(Characteristics); writer.WriteUInt32(TimeDateStamp); writer.WriteUInt16(MajorVersion); writer.WriteUInt16(MinorVersion); writer.WriteUInt32((uint)(Contents?.Type ?? DebugDataType.Unknown)); IDebugDataSegment? contents = Contents; writer.WriteUInt32((contents != null) ? ((IWritable)contents).GetPhysicalSize() : 0u); IDebugDataSegment? contents2 = Contents; writer.WriteUInt32((contents2 != null) ? ((IOffsetProvider)contents2).Rva : 0u); IDebugDataSegment? contents3 = Contents; writer.WriteUInt32((uint)((contents3 != null) ? ((IOffsetProvider)contents3).Offset : 0)); } } public enum DebugDataType : uint { Unknown = 0u, Coff = 1u, CodeView = 2u, Fpo = 0u, Misc = 4u, Exception = 5u, FixUp = 6u, OMapToSrc = 7u, OMapFromSrc = 8u, Borland = 9u, Reserved10 = 10u, ClsId = 11u, VcFeature = 12u, Pogo = 13u, Iltcg = 14u, Mpx = 15u, Repro = 16u, ExDllCharacteristics = 20u } public class DefaultDebugDataReader : IDebugDataReader { public static DefaultDebugDataReader Instance { get; } = new DefaultDebugDataReader(); public IDebugDataSegment? ReadDebugData(PEReaderContext context, DebugDataType type, ref BinaryStreamReader reader) { if (type == DebugDataType.CodeView) { return CodeViewDataSegment.FromReader(context, ref reader); } return new CustomDebugDataSegment(type, (ISegment)(object)DataSegment.FromReader(ref reader)); } } public interface IDebugDataReader { IDebugDataSegment? ReadDebugData(PEReaderContext context, DebugDataType type, ref BinaryStreamReader reader); } public interface IDebugDataSegment : ISegment, IOffsetProvider, IWritable { DebugDataType Type { get; } } public class RsdsDataSegment : CodeViewDataSegment { private const uint RsdsExpectedDataSize = 25u; public override CodeViewSignature Signature => CodeViewSignature.Rsds; public Guid Guid { get; set; } public uint Age { get; set; } public string? Path { get; set; } public new static RsdsDataSegment? FromReader(PEReaderContext context, ref BinaryStreamReader reader) { if (((BinaryStreamReader)(ref reader)).Length < 25) { ErrorListenerExtensions.BadImage((IErrorListener)(object)context, "RSDS Data was shorter than the minimal expected length"); return null; } RsdsDataSegment rsdsDataSegment = new RsdsDataSegment(); byte[] array = new byte[16]; ((BinaryStreamReader)(ref reader)).ReadBytes(array, 0, 16); rsdsDataSegment.Guid = new Guid(array); rsdsDataSegment.Age = ((BinaryStreamReader)(ref reader)).ReadUInt32(); rsdsDataSegment.Path = Encoding.UTF8.GetString(((BinaryStreamReader)(ref reader)).ReadBytesUntil((byte)0)); return rsdsDataSegment; } public override uint GetPhysicalSize() { return (uint)(24 + (Path?.Length ?? 0) + 1); } public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32((uint)Signature); writer.WriteBytes(Guid.ToByteArray()); writer.WriteUInt32(Age); writer.WriteBytes(Encoding.UTF8.GetBytes(Path ?? string.Empty)); writer.WriteByte((byte)0); } } public class SerializedDebugDataEntry : DebugDataEntry { private readonly PEReaderContext _context; private readonly DebugDataType _type; private readonly uint _sizeOfData; private readonly uint _addressOfRawData; private readonly uint _pointerToRawData; public SerializedDebugDataEntry(PEReaderContext context, ref BinaryStreamReader directoryReader) { if (!((BinaryStreamReader)(ref directoryReader)).IsValid) { throw new ArgumentNullException("directoryReader"); } _context = context ?? throw new ArgumentNullException("context"); ((SegmentBase)this).Offset = ((BinaryStreamReader)(ref directoryReader)).Offset; ((SegmentBase)this).Rva = ((BinaryStreamReader)(ref directoryReader)).Rva; base.Characteristics = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.TimeDateStamp = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); base.MajorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); base.MinorVersion = ((BinaryStreamReader)(ref directoryReader)).ReadUInt16(); _type = (DebugDataType)((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _sizeOfData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _addressOfRawData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); _pointerToRawData = ((BinaryStreamReader)(ref directoryReader)).ReadUInt32(); } protected override IDebugDataSegment? GetContents() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (_sizeOfData == 0) { return null; } ISegmentReference referenceToRva = _context.File.GetReferenceToRva(_addressOfRawData); if (!referenceToRva.CanRead) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Debug data entry contains an invalid RVA."); return null; } BinaryStreamReader reader = referenceToRva.CreateReader(); if (_sizeOfData > ((BinaryStreamReader)(ref reader)).Length) { ErrorListenerExtensions.BadImage((IErrorListener)(object)_context, "Debug data entry contains a too large size."); return null; } ((BinaryStreamReader)(ref reader)).ChangeSize(_sizeOfData); return _context.Parameters.DebugDataReader.ReadDebugData(_context, _type, ref reader); } } } namespace AsmResolver.PE.Debug.Builder { public class DebugDirectoryBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _headers = new SegmentBuilder(); private readonly SegmentBuilder _streamsTable = new SegmentBuilder(); public ISegment ContentsTable => (ISegment)(object)_streamsTable; public bool IsEmpty => _headers.Count == 0; public ulong Offset => _headers.Offset; public uint Rva => _headers.Rva; public bool CanUpdateOffsets => true; public void AddEntry(DebugDataEntry entry) { _headers.Add((ISegment)(object)entry); if (entry.Contents != null) { _streamsTable.Add((ISegment)entry.Contents, 4u); } } public void UpdateOffsets(in RelocationParameters parameters) { _headers.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _headers.GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { _headers.Write(writer); } public uint GetVirtualSize() { return _headers.GetVirtualSize(); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } } namespace AsmResolver.PE.Code { [DebuggerDisplay("Patch {Offset} with &{Symbol} as {Type}")] public readonly struct AddressFixup { public uint Offset { get; } public AddressFixupType Type { get; } public ISymbol Symbol { get; } public AddressFixup(uint offset, AddressFixupType type, ISymbol referencedObject) { Offset = offset; Symbol = referencedObject ?? throw new ArgumentNullException("referencedObject"); Type = type; } public override string ToString() { return $"+{Offset:X8} <{Symbol}> ({Type})"; } } public static class AddressFixupExtensions { public static PatchedSegment Patch(this PatchedSegment segment, uint relativeOffset, AddressFixupType type, ISymbol referencedObject) { AddressFixup fixup = new AddressFixup(relativeOffset, type, referencedObject); return segment.Patch(in fixup); } public static PatchedSegment Patch(this PatchedSegment segment, uint relativeOffset, AddressFixupType type, uint symbolOffset) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown AddressFixup fixup = new AddressFixup(relativeOffset, type, (ISymbol)new Symbol(Extensions.ToReference((ISegment)(object)segment, (int)symbolOffset))); return segment.Patch(in fixup); } public static PatchedSegment Patch(this PatchedSegment segment, in AddressFixup fixup) { segment.Patches.Add((IPatch)(object)new AddressFixupPatch(fixup)); return segment; } } [DebuggerDisplay("{Fixup}")] public class AddressFixupPatch : IPatch { public AddressFixup Fixup { get; } public AddressFixupPatch(AddressFixup fixup) { Fixup = fixup; } public void UpdateOffsets(in RelocationParameters parameters) { } public void Apply(in PatchContext context) { ((PatchContext)(ref context)).Writer.Offset = ((IOffsetProvider)((PatchContext)(ref context)).Segment).Offset + Fixup.Offset; uint num = ((IOffsetProvider)((PatchContext)(ref context)).Segment).Rva + Fixup.Offset; ISegmentReference reference = Fixup.Symbol.GetReference(); uint num2 = ((reference != null) ? ((IOffsetProvider)reference).Rva : 0u); switch (Fixup.Type) { case AddressFixupType.Absolute32BitAddress: ((PatchContext)(ref context)).Writer.WriteUInt32((uint)(((PatchContext)(ref context)).ImageBase + num2)); break; case AddressFixupType.Relative32BitAddress: ((PatchContext)(ref context)).Writer.WriteInt32((int)(num2 - (num + 4))); break; case AddressFixupType.Absolute64BitAddress: ((PatchContext)(ref context)).Writer.WriteUInt64(((PatchContext)(ref context)).ImageBase + num2); break; default: throw new ArgumentOutOfRangeException(); } } void IPatch.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } void IPatch.Apply(in PatchContext context) { Apply(in context); } } public enum AddressFixupType { Absolute32BitAddress, Absolute64BitAddress, Relative32BitAddress } [Obsolete("This class has been superseded by AsmResolver.Patching.PatchedSegment.")] public class CodeSegment : SegmentBase { public ulong ImageBase { get; set; } public byte[] Code { get; set; } public IList AddressFixups { get; } = new List(); public CodeSegment(byte[] code) { Code = code; } public CodeSegment(ulong imageBase, byte[] code) { ImageBase = imageBase; Code = code ?? throw new ArgumentNullException("code"); } public override void UpdateOffsets(in RelocationParameters parameters) { ImageBase = ((RelocationParameters)(ref parameters)).ImageBase; ((SegmentBase)this).UpdateOffsets(ref parameters); } public override uint GetPhysicalSize() { return (uint)Code.Length; } public override void Write(BinaryStreamWriter writer) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) writer.WriteBytes(Code); for (int i = 0; i < AddressFixups.Count; i++) { AddressFixupPatch addressFixupPatch = new AddressFixupPatch(AddressFixups[i]); PatchContext context = new PatchContext((ISegment)(object)this, ImageBase, writer); addressFixupPatch.Apply(in context); } writer.Offset = ((SegmentBase)this).Offset + ((SegmentBase)this).GetPhysicalSize(); } } } namespace AsmResolver.PE.Certificates { public abstract class AttributeCertificate : SegmentBase { public const uint HeaderSize = 8u; public abstract CertificateRevision Revision { get; } public abstract CertificateType Type { get; } public abstract bool CanRead { get; } public abstract BinaryStreamReader CreateContentReader(); public override uint GetPhysicalSize() { return 8 + GetContentsSize(); } protected abstract uint GetContentsSize(); public override void Write(BinaryStreamWriter writer) { writer.WriteUInt32(((SegmentBase)this).GetPhysicalSize()); writer.WriteUInt16((ushort)Revision); writer.WriteUInt16((ushort)Type); WriteContents(writer); } protected abstract void WriteContents(BinaryStreamWriter writer); } public class CertificateCollection : Collection, ISegment, IOffsetProvider, IWritable { public ulong Offset { get; private set; } public uint Rva { get; private set; } public bool CanUpdateOffsets => true; public void UpdateOffsets(in RelocationParameters parameters) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Offset = ((RelocationParameters)(ref parameters)).Offset; Rva = ((RelocationParameters)(ref parameters)).Rva; RelocationParameters val = parameters; for (int i = 0; i < base.Items.Count; i++) { AttributeCertificate attributeCertificate = base.Items[i]; ((SegmentBase)attributeCertificate).UpdateOffsets(ref val); ((RelocationParameters)(ref val)).Advance(Extensions.Align(((SegmentBase)attributeCertificate).GetPhysicalSize(), 8u)); } } public uint GetPhysicalSize() { uint num = 0u; for (int i = 0; i < base.Items.Count; i++) { num += Extensions.Align(((SegmentBase)base.Items[i]).GetPhysicalSize(), 8u); } return num; } public uint GetVirtualSize() { return GetPhysicalSize(); } public void Write(BinaryStreamWriter writer) { for (int i = 0; i < base.Items.Count; i++) { ((SegmentBase)base.Items[i]).Write(writer); writer.Align(8u); } } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public enum CertificateRevision : ushort { Revision_v1_0 = 0x100, Revision_v2_0 = 0x200 } public enum CertificateType : ushort { X509 = 1, PkcsSignedData, Reserved1, TsStackSigned } [DebuggerDisplay("{Type}")] public class CustomAttributeCertificate : AttributeCertificate { public override CertificateRevision Revision { get; } public override CertificateType Type { get; } public IReadableSegment? Contents { get; set; } [MemberNotNullWhen(true, "Contents")] public override bool CanRead { [MemberNotNullWhen(true, "Contents")] get { return Contents != null; } } public CustomAttributeCertificate(CertificateType type, IReadableSegment? contents) : this(CertificateRevision.Revision_v2_0, type, contents) { } public CustomAttributeCertificate(CertificateRevision revision, CertificateType type, IReadableSegment? contents) { Revision = revision; Type = type; Contents = contents; } public override BinaryStreamReader CreateContentReader() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!CanRead) { throw new InvalidOperationException("Signature cannot be read."); } return Extensions.CreateReader(Contents); } public override void UpdateOffsets(in RelocationParameters parameters) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) ((SegmentBase)this).UpdateOffsets(ref parameters); IReadableSegment? contents = Contents; if (contents != null) { RelocationParameters val = ((RelocationParameters)(ref parameters)).WithAdvance(8u); ((ISegment)contents).UpdateOffsets(ref val); } } protected override uint GetContentsSize() { IReadableSegment? contents = Contents; if (contents == null) { return 0u; } return ((IWritable)contents).GetPhysicalSize(); } protected override void WriteContents(BinaryStreamWriter writer) { IReadableSegment? contents = Contents; if (contents != null) { ((IWritable)contents).Write(writer); } } } public class DefaultCertificateReader : ICertificateReader { public static DefaultCertificateReader Instance { get; } = new DefaultCertificateReader(); public AttributeCertificate ReadCertificate(PEReaderContext context, CertificateRevision revision, CertificateType type, BinaryStreamReader reader) { return new CustomAttributeCertificate(revision, type, ((BinaryStreamReader)(ref reader)).ReadSegment(((BinaryStreamReader)(ref reader)).Length)); } } public interface ICertificateReader { AttributeCertificate ReadCertificate(PEReaderContext context, CertificateRevision revision, CertificateType type, BinaryStreamReader reader); } } namespace AsmResolver.PE.Builder { public interface IPEFileBuilder { PEFile CreateFile(PEImage image); } public class ManagedPEFileBuilder : PEFileBuilder { public IErrorListener ErrorListener { get; set; } public ManagedPEFileBuilder() : this((IErrorListener)(object)ThrowErrorListener.Instance) { } public ManagedPEFileBuilder(IErrorListener errorListener) { ErrorListener = errorListener; } protected override IEnumerable CreateSections(PEFileBuilderContext context) { PEImage image = context.Image; if (image.DotNetDirectory == null) { ErrorListener.RegisterException((Exception)new ArgumentException("PE image does not contain a valid .NET data directory.")); } List list = new List(); list.Add(CreateTextSection(context)); if (!context.ExportDirectory.IsEmpty || image.DotNetDirectory?.VTableFixups != null) { list.Add(CreateSDataSection(context)); } if (!context.ResourceDirectory.IsEmpty) { list.Add(CreateRsrcSection(context)); } if (!context.RelocationsDirectory.IsEmpty) { list.Add(CreateRelocSection(context)); } return list; } protected virtual PESection CreateTextSection(PEFileBuilderContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown SegmentBuilder val = new SegmentBuilder(); if (!context.ImportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ImportDirectory.ImportAddressDirectory); } val.Add(CreateDotNetSegment(context)); if (!context.ImportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ImportDirectory); } if (!context.ExportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ExportDirectory); } if (!context.DebugDirectory.IsEmpty) { val.Add((ISegment)(object)context.DebugDirectory); val.Add(context.DebugDirectory.ContentsTable); } if (context.ClrBootstrapper.HasValue) { val.Add(context.ClrBootstrapper.Value.Segment); } ExportDirectory exports = context.Image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { for (int i = 0; i < entries.Count; i++) { ExportedSymbol exportedSymbol = entries[i]; if (exportedSymbol.Address.IsBounded) { ISegment segment = exportedSymbol.Address.GetSegment(); if (segment != null) { val.Add(segment, (uint)context.Platform.PointerSize); } } } } } return new PESection(Utf8String.op_Implicit(".text"), (SectionFlags)1610612768, (ISegment)(object)val); } private static ISegment CreateDotNetSegment(PEFileBuilderContext context) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown DotNetDirectory dotNetDirectory = context.Image.DotNetDirectory; SegmentBuilder val = new SegmentBuilder(); val.Add((ISegment)(object)dotNetDirectory); val.Add((ISegment)(object)context.FieldRvaTable); val.Add((ISegment)(object)context.MethodBodyTable); SegmentBuilder result = val; AddIfPresent((ISegment?)(object)dotNetDirectory.Metadata); AddIfPresent((ISegment?)(object)dotNetDirectory.DotNetResources); AddIfPresent((ISegment?)(object)dotNetDirectory.StrongName); VTableFixupsDirectory? vTableFixups = dotNetDirectory.VTableFixups; if (vTableFixups != null && vTableFixups.Count > 0) { result.Add((ISegment)(object)dotNetDirectory.VTableFixups); } AddIfPresent((ISegment?)(object)dotNetDirectory.ExportAddressTable); AddIfPresent((ISegment?)dotNetDirectory.ManagedNativeHeader); return (ISegment)(object)result; void AddIfPresent(ISegment? segment) { if (segment != null) { result.Add(segment, 4u); } } } protected virtual PESection CreateSDataSection(PEFileBuilderContext context) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown PEImage image = context.Image; SegmentBuilder val = new SegmentBuilder(); VTableFixupsDirectory vTableFixupsDirectory = image.DotNetDirectory?.VTableFixups; if (vTableFixupsDirectory != null) { for (int i = 0; i < vTableFixupsDirectory.Count; i++) { val.Add((ISegment)(object)vTableFixupsDirectory[i].Tokens, (uint)context.Platform.PointerSize); } } ExportDirectory exports = image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { val.Add((ISegment)(object)context.ExportDirectory, (uint)context.Platform.PointerSize); } } return new PESection(Utf8String.op_Implicit(".sdata"), (SectionFlags)(-1073741760), (ISegment)(object)val); } protected virtual PESection CreateRsrcSection(PEFileBuilderContext context) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return new PESection(Utf8String.op_Implicit(".rsrc"), (SectionFlags)1073741888, (ISegment)(object)context.ResourceDirectory); } protected virtual PESection CreateRelocSection(PEFileBuilderContext context) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return new PESection(Utf8String.op_Implicit(".reloc"), (SectionFlags)1107296320, (ISegment)(object)context.RelocationsDirectory); } protected override void CreateDataDirectoryBuffers(PEFileBuilderContext context) { CreateDotNetDirectories(context); base.CreateDataDirectoryBuffers(context); } protected override void CreateImportDirectory(PEFileBuilderContext context) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) PEImage image = context.Image; int num; if (image.DotNetDirectory != null) { if (!context.Platform.IsClrBootstrapperRequired) { DotNetDirectory? dotNetDirectory = image.DotNetDirectory; num = ((dotNetDirectory != null && (dotNetDirectory.Flags & DotNetDirectoryFlags.ILOnly) == 0) ? 1 : 0); } else { num = 1; } } else { num = 0; } bool flag = (byte)num != 0; string clrEntryPointName = (((image.Characteristics & 0x2000) != 0) ? "_CorDllMain" : "_CorExeMain"); ImportedSymbol clrEntryPoint; foreach (ImportedModule item in CollectImportedModules(image, flag, clrEntryPointName, out clrEntryPoint)) { context.ImportDirectory.AddModule(item); } if (flag) { if (clrEntryPoint == null) { throw new InvalidOperationException("Entry point symbol was required but not imported."); } context.ClrBootstrapper = context.Platform.CreateThunkStub((ISymbol)(object)clrEntryPoint); } } private static List CollectImportedModules(PEImage image, bool requireClrEntryPoint, string clrEntryPointName, out ImportedSymbol? clrEntryPoint) { string clrEntryPointName2 = clrEntryPointName; clrEntryPoint = null; List list = image.Imports.ToList(); if (requireClrEntryPoint) { ImportedModule importedModule = list.FirstOrDefault((ImportedModule x) => x.Name == "mscoree.dll"); if (importedModule == null) { importedModule = new ImportedModule("mscoree.dll"); list.Add(importedModule); } clrEntryPoint = importedModule.Symbols.FirstOrDefault((ImportedSymbol x) => x.Name == clrEntryPointName2); if (clrEntryPoint == null) { clrEntryPoint = new ImportedSymbol(0, clrEntryPointName2); importedModule.Symbols.Add(clrEntryPoint); } } else { ImportedModule importedModule2 = list.FirstOrDefault((ImportedModule x) => x.Name == "mscoree.dll"); if (importedModule2 != null) { ImportedSymbol importedSymbol = importedModule2.Symbols.FirstOrDefault((ImportedSymbol x) => x.Name == clrEntryPointName2); if (importedSymbol != null) { importedModule2.Symbols.Remove(importedSymbol); } if (importedModule2.Symbols.Count == 0) { list.Remove(importedModule2); } } } return list; } protected override void CreateRelocationsDirectory(PEFileBuilderContext context) { PEFileBuilderContext context2 = context; AddRange(context2.Image.Relocations.Where((BaseRelocation x) => !(x.Location is PESegmentReference))); RelocatableSegment? clrBootstrapper = context2.ClrBootstrapper; if (clrBootstrapper.HasValue) { AddRange(clrBootstrapper.GetValueOrDefault().Relocations); } void AddRange(IEnumerable relocations) { foreach (BaseRelocation relocation in relocations) { context2.RelocationsDirectory.Add(relocation); } } } private void CreateDotNetDirectories(PEFileBuilderContext context) { ProcessRvasInMetadataTables(context); } protected override void AssignDataDirectories(PEFileBuilderContext context, PEFile outputFile) { OptionalHeader optionalHeader = outputFile.OptionalHeader; optionalHeader.DataDirectories.Clear(); optionalHeader.EnsureDataDirectoryCount(16); if (!context.ImportDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)1, (ISegment)(object)context.ImportDirectory); optionalHeader.SetDataDirectory((DataDirectoryIndex)12, (ISegment)(object)context.ImportDirectory.ImportAddressDirectory); } if (!context.ExportDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)0, (ISegment)(object)context.ExportDirectory); } if (!context.DebugDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)6, (ISegment)(object)context.DebugDirectory); } if (!context.ResourceDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)2, (ISegment)(object)context.ResourceDirectory); } if (context.Image.DotNetDirectory != null) { optionalHeader.SetDataDirectory((DataDirectoryIndex)14, (ISegment)(object)context.Image.DotNetDirectory); } if (!context.RelocationsDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)5, (ISegment)(object)context.RelocationsDirectory); } } protected override uint GetEntryPointAddress(PEFileBuilderContext context, PEFile outputFile) { RelocatableSegment? clrBootstrapper = context.ClrBootstrapper; if (!clrBootstrapper.HasValue) { return 0u; } return ((IOffsetProvider)clrBootstrapper.GetValueOrDefault().Segment).Rva; } private void ProcessRvasInMetadataTables(PEFileBuilderContext context) { TablesStream tablesStream = context.Image.DotNetDirectory?.Metadata?.GetStream(); if (tablesStream == null) { ErrorListener.RegisterException((Exception)new ArgumentException("Image does not have a .NET metadata tables stream.")); return; } AddMethodBodiesToTable(context, tablesStream); AddFieldRvasToTable(context, tablesStream); } private void AddMethodBodiesToTable(PEFileBuilderContext context, TablesStream tablesStream) { MetadataTable table = tablesStream.GetTable(); for (uint num = 1u; num <= table.Count; num++) { ref MethodDefinitionRow rowRef = ref table.GetRowRef(num); ISegment methodBodySegment = GetMethodBodySegment(rowRef); if (methodBodySegment is CilRawMethodBody body) { context.MethodBodyTable.AddCilBody(body); } else { if (methodBodySegment == null) { continue; } context.MethodBodyTable.AddNativeBody(methodBodySegment, (uint)context.Platform.PointerSize); } rowRef.Body = Extensions.ToReference(methodBodySegment); } } private ISegment? GetMethodBodySegment(MethodDefinitionRow methodRow) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (methodRow.Body.IsBounded) { return methodRow.Body.GetSegment(); } if (methodRow.Body.CanRead) { if ((methodRow.ImplAttributes & AsmResolver.PE.DotNet.Metadata.Tables.MethodImplAttributes.Runtime) == 0) { BinaryStreamReader reader = methodRow.Body.CreateReader(); return (ISegment?)(object)CilRawMethodBody.FromReader((IErrorListener)(object)ThrowErrorListener.Instance, ref reader); } ErrorListenerExtensions.NotSupported(ErrorListener, "Native unbounded method bodies are not supported."); } return null; } private void AddFieldRvasToTable(PEFileBuilderContext context, TablesStream tablesStream) { DotNetDirectory dotNetDirectory = context.Image.DotNetDirectory; MetadataTable table = tablesStream.GetTable(TableIndex.FieldRva); if (table.Count == 0) { return; } SegmentBuilder fieldRvaTable = context.FieldRvaTable; IFieldRvaDataReader fieldRvaDataReader = context.FieldRvaDataReader; for (uint num = 1u; num <= table.Count; num++) { ref FieldRvaRow rowRef = ref table.GetRowRef(num); ISegment val = fieldRvaDataReader.ResolveFieldData(ErrorListener, context.Platform, dotNetDirectory, in rowRef); if (val != null) { fieldRvaTable.Add(val); rowRef.Data = Extensions.ToReference(val); } } } } public class MethodBodyTableBuffer : ISegment, IOffsetProvider, IWritable { private readonly SegmentBuilder _tinyBodies = new SegmentBuilder(); private readonly SegmentBuilder _fatBodies = new SegmentBuilder(); private readonly SegmentBuilder _nativeBodies = new SegmentBuilder(); private readonly SegmentBuilder _segments = new SegmentBuilder(); public ulong Offset => _segments.Offset; public uint Rva => _segments.Rva; public bool CanUpdateOffsets => _segments.CanUpdateOffsets; public bool IsEmpty { get { if (_tinyBodies.Count == 0 && _fatBodies.Count == 0) { return _nativeBodies.Count == 0; } return false; } } public MethodBodyTableBuffer() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown _segments.Add((ISegment)(object)_tinyBodies); _segments.Add((ISegment)(object)_fatBodies); _segments.Add((ISegment)(object)_nativeBodies); } public void AddCilBody(CilRawMethodBody body) { if (body.IsFat) { _fatBodies.Add((ISegment)(object)body, 4u); } else { _tinyBodies.Add((ISegment)(object)body); } } public void AddNativeBody(ISegment body, uint alignment) { _nativeBodies.Add(body, alignment); } public void UpdateOffsets(in RelocationParameters parameters) { _segments.UpdateOffsets(ref parameters); } public uint GetPhysicalSize() { return _segments.GetPhysicalSize(); } public uint GetVirtualSize() { return _segments.GetVirtualSize(); } public void Write(BinaryStreamWriter writer) { _segments.Write(writer); } void ISegment.UpdateOffsets(in RelocationParameters parameters) { UpdateOffsets(in parameters); } } public abstract class PEFileBuilder : PEFileBuilder { protected override PEFileBuilderContext CreateContext(PEImage image) { return new PEFileBuilderContext(image); } } public abstract class PEFileBuilder : IPEFileBuilder where TContext : PEFileBuilderContext { public virtual PEFile CreateFile(PEImage image) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown PEFile val = new PEFile(); TContext context = CreateContext(image); CreateDataDirectoryBuffers(context); foreach (PESection item in CreateSections(context)) { val.Sections.Add(item); } ComputeHeaderFields(context, val); return val; } protected abstract TContext CreateContext(PEImage image); protected abstract IEnumerable CreateSections(TContext context); protected abstract void AssignDataDirectories(TContext context, PEFile outputFile); protected abstract uint GetEntryPointAddress(TContext context, PEFile outputFile); protected virtual uint GetFileAlignment(TContext context, PEFile outputFile) { PEFile? pEFile = context.Image.PEFile; if (pEFile == null) { return 512u; } return pEFile.OptionalHeader.FileAlignment; } protected virtual uint GetSectionAlignment(TContext context, PEFile outputFile) { PEFile? pEFile = context.Image.PEFile; if (pEFile == null) { return 8192u; } return pEFile.OptionalHeader.SectionAlignment; } protected virtual ulong GetImageBase(TContext context, PEFile outputFile) { return context.Image.ImageBase; } protected virtual void ComputeHeaderFields(TContext context, PEFile outputFile) { ComputeOptionalHeaderFields(context, outputFile); ComputeFileHeaderFields(context, outputFile); outputFile.DosHeader.NextHeaderOffset = ((SegmentBase)outputFile.DosHeader).GetPhysicalSize(); } protected virtual void ComputeOptionalHeaderFields(TContext context, PEFile outputFile) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) PEImage image = context.Image; OptionalHeader optionalHeader = outputFile.OptionalHeader; optionalHeader.ImageBase = GetImageBase(context, outputFile); optionalHeader.SectionAlignment = GetSectionAlignment(context, outputFile); optionalHeader.FileAlignment = GetFileAlignment(context, outputFile); if (optionalHeader.SectionAlignment < optionalHeader.FileAlignment) { throw new ArgumentException("File alignment cannot be larger than the section alignment."); } outputFile.UpdateHeaders(); optionalHeader.Magic = image.PEKind; optionalHeader.MajorLinkerVersion = 48; optionalHeader.MinorLinkerVersion = 0; optionalHeader.SizeOfCode = 0u; optionalHeader.SizeOfInitializedData = 0u; optionalHeader.SizeOfUninitializedData = 0u; optionalHeader.SizeOfImage = 0u; for (int i = 0; i < outputFile.Sections.Count; i++) { PESection val = outputFile.Sections[i]; uint physicalSize = val.GetPhysicalSize(); if (val.IsContentCode) { optionalHeader.SizeOfCode += physicalSize; } if (val.IsContentInitializedData) { optionalHeader.SizeOfInitializedData += physicalSize; } if (val.IsContentUninitializedData) { optionalHeader.SizeOfUninitializedData += physicalSize; } optionalHeader.SizeOfImage += val.GetVirtualSize(); } optionalHeader.AddressOfEntryPoint = GetEntryPointAddress(context, outputFile); PESection? obj = ((IEnumerable)outputFile.Sections).FirstOrDefault((Func)((PESection s) => s.IsContentCode)); optionalHeader.BaseOfCode = ((obj != null) ? obj.Rva : 0u); PESection? obj2 = ((IEnumerable)outputFile.Sections).FirstOrDefault((Func)((PESection s) => s.IsContentInitializedData)); optionalHeader.BaseOfData = ((obj2 != null) ? obj2.Rva : 0u); optionalHeader.MajorOperatingSystemVersion = 4; optionalHeader.MinorOperatingSystemVersion = 0; optionalHeader.MajorImageVersion = 0; optionalHeader.MinorImageVersion = 0; optionalHeader.MajorSubsystemVersion = 4; optionalHeader.MinorSubsystemVersion = 0; optionalHeader.Win32VersionValue = 0u; optionalHeader.SizeOfImage = Extensions.Align(optionalHeader.SizeOfImage, optionalHeader.SectionAlignment); optionalHeader.SizeOfHeaders = Extensions.Align(((SegmentBase)outputFile.DosHeader).GetPhysicalSize() + ((SegmentBase)outputFile.FileHeader).GetPhysicalSize() + ((SegmentBase)outputFile.OptionalHeader).GetPhysicalSize() + (uint)(outputFile.Sections.Count * 40), optionalHeader.FileAlignment); optionalHeader.CheckSum = 0u; optionalHeader.SubSystem = image.SubSystem; optionalHeader.DllCharacteristics = image.DllCharacteristics; optionalHeader.SizeOfStackReserve = 1048576uL; optionalHeader.SizeOfStackCommit = 4096uL; optionalHeader.SizeOfHeapReserve = 1048576uL; optionalHeader.SizeOfHeapCommit = 4096uL; optionalHeader.LoaderFlags = 0u; AssignDataDirectories(context, outputFile); optionalHeader.NumberOfRvaAndSizes = 16u; } protected virtual void ComputeFileHeaderFields(TContext context, PEFile outputFile) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) PEImage image = context.Image; FileHeader fileHeader = outputFile.FileHeader; fileHeader.Machine = context.Image.MachineType; fileHeader.NumberOfSections = (ushort)outputFile.Sections.Count; fileHeader.TimeDateStamp = (uint)(image.TimeDateStamp - new DateTime(1970, 1, 1)).TotalSeconds; fileHeader.NumberOfSymbols = 0u; fileHeader.PointerToSymbolTable = 0u; fileHeader.SizeOfOptionalHeader = (ushort)((SegmentBase)outputFile.OptionalHeader).GetPhysicalSize(); fileHeader.Characteristics = image.Characteristics; } protected virtual void CreateDataDirectoryBuffers(TContext context) { CreateExportDirectory(context); CreateImportDirectory(context); CreateDebugDirectory(context); CreateResourcesDirectory(context); CreateRelocationsDirectory(context); } protected virtual void CreateImportDirectory(TContext context) { foreach (ImportedModule import in context.Image.Imports) { context.ImportDirectory.AddModule(import); } } protected virtual void CreateDebugDirectory(TContext context) { IList debugData = context.Image.DebugData; for (int i = 0; i < debugData.Count; i++) { context.DebugDirectory.AddEntry(debugData[i]); } } protected virtual void CreateExportDirectory(TContext context) { ExportDirectory exports = context.Image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { context.ExportDirectory.AddDirectory(exports); } } } protected virtual void CreateResourcesDirectory(TContext context) { if (context.Image.Resources != null) { context.ResourceDirectory.AddDirectory(context.Image.Resources); } } protected virtual void CreateRelocationsDirectory(TContext context) { IList relocations = context.Image.Relocations; for (int i = 0; i < relocations.Count; i++) { context.RelocationsDirectory.Add(relocations[i]); } } } public class PEFileBuilderContext { public PEImage Image { get; } public Platform Platform { get; } public ImportDirectoryBuffer ImportDirectory { get; } public ExportDirectoryBuffer ExportDirectory { get; } public DebugDirectoryBuffer DebugDirectory { get; } public ResourceDirectoryBuffer ResourceDirectory { get; } public RelocationsDirectoryBuffer RelocationsDirectory { get; } public RelocatableSegment? ClrBootstrapper { get; set; } public IFieldRvaDataReader FieldRvaDataReader { get; set; } public SegmentBuilder FieldRvaTable { get; } public MethodBodyTableBuffer MethodBodyTable { get; } public PEFileBuilderContext(PEImage image) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown Image = image; Platform = AsmResolver.PE.Platforms.Platform.Get(image.MachineType); ImportDirectory = new ImportDirectoryBuffer(Platform.Is32Bit); ExportDirectory = new ExportDirectoryBuffer(); ResourceDirectory = new ResourceDirectoryBuffer(); RelocationsDirectory = new RelocationsDirectoryBuffer(); DebugDirectory = new DebugDirectoryBuffer(); FieldRvaTable = new SegmentBuilder(); MethodBodyTable = new MethodBodyTableBuffer(); FieldRvaDataReader = new FieldRvaDataReader(); } } public class TrampolineTableBuffer : SegmentBase { private sealed class FunctionTrampoline { public ISymbol OriginalSymbol { get; } public BaseRelocation OriginalSymbolRelocation { get; } public Symbol TrampolineSymbol { get; } public RelocatableSegment TrampolineCode { get; } public FunctionTrampoline(Platform platform, ISymbol originalSymbol, ISymbol newSymbol) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown OriginalSymbol = originalSymbol; OriginalSymbolRelocation = new BaseRelocation(platform.Is32Bit ? RelocationType.HighLow : RelocationType.Dir64, originalSymbol.GetReference() ?? throw new ArgumentException($"{originalSymbol} does not have an address assigned.")); TrampolineCode = platform.CreateThunkStub(newSymbol); TrampolineSymbol = new Symbol(Extensions.ToReference(TrampolineCode.Segment)); } } private readonly Platform _platform; private readonly List _trampolines = new List(); private readonly SegmentBuilder _contents = new SegmentBuilder(); private readonly SegmentBuilder _trampolineTable = new SegmentBuilder(); private AddressTableInitializerStub? _initializerStub; [MemberNotNullWhen(true, "DataInitializerSymbol")] public bool RequiresDynamicInitialization { [MemberNotNullWhen(true, "DataInitializerSymbol")] get { return DataInitializerSymbol != null; } } public ISymbol? DataInitializerSymbol => _initializerStub?.EntryPoint; public ImportedSymbol? VirtualProtect { get; set; } public TrampolineTableBuffer(Platform platform) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _platform = platform; _contents.Add((ISegment)(object)_trampolineTable, (uint)platform.PointerSize); } public void AddFunctionTableSlotTrampoline(ISymbol functionTableSlot, ISymbol newSymbol) { FunctionTrampoline functionTrampoline = new FunctionTrampoline(_platform, functionTableSlot, newSymbol); _trampolines.Add(functionTrampoline); _trampolineTable.Add(functionTrampoline.TrampolineCode.Segment); } public void AddDataSlotInitializer(ISymbol originalSlot, ISymbol newSlot) { EnsureAddressTableInitializerAdded(); _initializerStub.AddInitializer(originalSlot, newSlot); } [MemberNotNull("_initializerStub")] private void EnsureAddressTableInitializerAdded() { if (VirtualProtect == null) { ImportedModule importedModule = new ImportedModule("KERNEL32.dll"); VirtualProtect = new ImportedSymbol(0, "VirtualProtect"); importedModule.Symbols.Add(VirtualProtect); } if (_initializerStub == null) { _initializerStub = _platform.CreateAddressTableInitializer((ISymbol)(object)VirtualProtect); _contents.Add((ISegment)(object)_initializerStub, (uint)_platform.PointerSize); } } public void ApplyPatches(PEFile file) { ApplyPatches(file.Sections); } public void ApplyPatches(IList sections) { foreach (FunctionTrampoline trampoline in _trampolines) { ISegmentReference reference = trampoline.OriginalSymbol.GetReference(); if (reference != null && TryGetSectionContainingRva(sections, ((IOffsetProvider)reference).Rva, out PESection section)) { PESection obj = section; ISegment contents = section.Contents; obj.Contents = (ISegment)(object)((contents != null) ? Extensions.AsPatchedSegment(contents).Patch(((IOffsetProvider)reference).Rva - section.Rva, (!_platform.Is32Bit) ? AddressFixupType.Absolute64BitAddress : AddressFixupType.Absolute32BitAddress, (ISymbol)(object)trampoline.TrampolineSymbol) : null); } } } public IEnumerable GetRequiredBaseRelocations() { foreach (FunctionTrampoline trampoline in _trampolines) { yield return trampoline.OriginalSymbolRelocation; foreach (BaseRelocation relocation in trampoline.TrampolineCode.Relocations) { yield return relocation; } } if (_initializerStub == null) { yield break; } foreach (BaseRelocation requiredBaseRelocation in _initializerStub.GetRequiredBaseRelocations()) { yield return requiredBaseRelocation; } } public override void UpdateOffsets(in RelocationParameters parameters) { ((SegmentBase)this).UpdateOffsets(ref parameters); _contents.UpdateOffsets(ref parameters); } public override uint GetPhysicalSize() { return _contents.GetPhysicalSize(); } public override void Write(BinaryStreamWriter writer) { _contents.Write(writer); } private static bool TryGetSectionContainingRva(IList sections, uint rva, [NotNullWhen(true)] out PESection? section) { for (int i = 0; i < sections.Count; i++) { if (sections[i].ContainsRva(rva)) { section = sections[i]; return true; } } section = null; return false; } } public class UnmanagedPEFileBuilder : PEFileBuilder { public class BuilderContext : PEFileBuilderContext { public List ClonedSections { get; } = new List(); public PEImage? BaseImage { get; } public TrampolineTableBuffer ImportTrampolines { get; } public TrampolineTableBuffer VTableTrampolines { get; } public BuilderContext(PEImage image, PEImage? baseImage) : base(image) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown BaseImage = baseImage; if (baseImage?.PEFile != null) { foreach (PESection section in baseImage.PEFile.Sections) { ClonedSections.Add(new PESection(section)); } } ImportTrampolines = new TrampolineTableBuffer(base.Platform); VTableTrampolines = new TrampolineTableBuffer(base.Platform); } public bool TryGetSectionContainingRva(uint rva, [NotNullWhen(true)] out PESection? section) { foreach (PESection clonedSection in ClonedSections) { if (clonedSection.ContainsRva(rva)) { section = clonedSection; return true; } } section = null; return false; } } private static readonly IImportedSymbolClassifier DefaultSymbolClassifier = new DelegatedSymbolClassifier((ImportedSymbol _) => ImportedSymbolType.Function); public IErrorListener ErrorListener { get; set; } public PEFile? BaseFile { get; set; } public bool TrampolineImports { get; set; } public bool TrampolineVTableFixups { get; set; } public IImportedSymbolClassifier ImportedSymbolClassifier { get; set; } = DefaultSymbolClassifier; public UnmanagedPEFileBuilder() : this((IErrorListener)(object)ThrowErrorListener.Instance, null) { } public UnmanagedPEFileBuilder(IErrorListener errorListener) : this(errorListener, null) { } public UnmanagedPEFileBuilder(IErrorListener errorListener, PEFile? baseFile) { ErrorListener = errorListener; BaseFile = baseFile; } protected override BuilderContext CreateContext(PEImage image) { PEFile val = BaseFile ?? image.PEFile; PEImage baseImage = ((val != null) ? PEImage.FromFile(val, new PEReaderParameters((IErrorListener)(object)EmptyErrorListener.Instance)) : null); return new BuilderContext(image, baseImage); } protected override IEnumerable CreateSections(BuilderContext context) { List list = new List(); list.AddRange(context.ClonedSections); PESection val = CreateAuxTextSection(context); if (val != null) { list.Add(val); } PESection val2 = CreateAuxRDataSection(context); if (val2 != null) { list.Add(val2); } PESection val3 = CreateAuxDataSection(context); if (val3 != null) { list.Add(val3); } PESection val4 = CreateAuxRsrcSection(context); if (val4 != null) { list.Add(val4); } PESection val5 = CreateAuxRelocSection(context); if (val5 != null) { list.Add(val5); } return list; } protected override uint GetEntryPointAddress(BuilderContext context, PEFile outputFile) { PEFile? pEFile = context.Image.PEFile; if (pEFile == null) { RelocatableSegment? clrBootstrapper = context.ClrBootstrapper; if (!clrBootstrapper.HasValue) { return 0u; } return ((IOffsetProvider)clrBootstrapper.GetValueOrDefault().Segment).Rva; } return pEFile.OptionalHeader.AddressOfEntryPoint; } protected override void AssignDataDirectories(BuilderContext context, PEFile outputFile) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) OptionalHeader optionalHeader = outputFile.OptionalHeader; PEFile pEFile = context.Image.PEFile; if (pEFile != null) { optionalHeader.DataDirectories.Clear(); foreach (DataDirectory dataDirectory in pEFile.OptionalHeader.DataDirectories) { optionalHeader.DataDirectories.Add(dataDirectory); } } optionalHeader.EnsureDataDirectoryCount(16); if (!context.ImportDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)1, (ISegment)(object)context.ImportDirectory); optionalHeader.SetDataDirectory((DataDirectoryIndex)12, (ISegment)(object)context.ImportDirectory.ImportAddressDirectory); } if (!context.ExportDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)0, (ISegment)(object)context.ExportDirectory); } if (!context.DebugDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)6, (ISegment)(object)context.DebugDirectory); } if (!context.ResourceDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)2, (ISegment)(object)context.ResourceDirectory); } if (context.Image.DotNetDirectory != null) { optionalHeader.SetDataDirectory((DataDirectoryIndex)14, (ISegment)(object)context.Image.DotNetDirectory); } if (context.Image.TlsDirectory != null) { optionalHeader.SetDataDirectory((DataDirectoryIndex)9, (ISegment)(object)context.Image.TlsDirectory); } if (!context.RelocationsDirectory.IsEmpty) { optionalHeader.SetDataDirectory((DataDirectoryIndex)5, (ISegment)(object)context.RelocationsDirectory); } } protected virtual PESection? CreateAuxTextSection(BuilderContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown SegmentBuilder val = new SegmentBuilder(); if (TrampolineImports && !context.ImportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ImportDirectory.ImportAddressDirectory); } ISegment val2 = CreateAuxDotNetSegment(context); if (val2 != null) { val.Add(val2); } if (TrampolineImports && !context.ImportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ImportDirectory); } if (!context.ExportDirectory.IsEmpty) { val.Add((ISegment)(object)context.ExportDirectory); } if (!context.DebugDirectory.IsEmpty) { if (!TryPatchDataDirectory(context, (ISegment?)(object)context.DebugDirectory, (DataDirectoryIndex)6)) { val.Add((ISegment)(object)context.DebugDirectory); } val.Add(context.DebugDirectory.ContentsTable); } if (context.ClrBootstrapper.HasValue) { val.Add(context.ClrBootstrapper.Value.Segment); } if (TrampolineImports) { val.Add((ISegment)(object)context.ImportTrampolines); context.ImportTrampolines.ApplyPatches((IList)context.ClonedSections); } ExportDirectory exports = context.Image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { for (int i = 0; i < entries.Count; i++) { ExportedSymbol exportedSymbol = entries[i]; if (exportedSymbol.Address.IsBounded) { ISegment segment = exportedSymbol.Address.GetSegment(); if (segment != null) { val.Add(segment, (uint)context.Platform.PointerSize); } } } } } if (val.Count == 0) { return null; } return new PESection(Utf8String.op_Implicit(".auxtext"), (SectionFlags)1610612768, (ISegment)(object)val); } private ISegment? CreateAuxDotNetSegment(BuilderContext context) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown BuilderContext context2 = context; DotNetDirectory dotNetDirectory = context2.Image.DotNetDirectory; if (dotNetDirectory == null) { return null; } SegmentBuilder result = new SegmentBuilder(); AddOrPatch((ISegment?)(object)dotNetDirectory, (ISegment?)(object)context2.BaseImage?.DotNetDirectory); if (!context2.FieldRvaTable.IsEmpty) { result.Add((ISegment)(object)context2.FieldRvaTable); } if (!context2.MethodBodyTable.IsEmpty) { result.Add((ISegment)(object)context2.MethodBodyTable); } AddOrPatch((ISegment?)(object)dotNetDirectory.Metadata, (ISegment?)(object)context2.BaseImage?.DotNetDirectory?.Metadata); AddOrPatch((ISegment?)(object)dotNetDirectory.DotNetResources, (ISegment?)(object)context2.BaseImage?.DotNetDirectory?.DotNetResources); AddOrPatch((ISegment?)(object)dotNetDirectory.StrongName, (ISegment?)(object)context2.BaseImage?.DotNetDirectory?.StrongName); if (TrampolineVTableFixups) { VTableFixupsDirectory? vTableFixups = dotNetDirectory.VTableFixups; if (vTableFixups != null && vTableFixups.Count > 0) { result.Add((ISegment)(object)dotNetDirectory.VTableFixups); result.Add((ISegment)(object)context2.VTableTrampolines); context2.VTableTrampolines.ApplyPatches((IList)context2.ClonedSections); } } AddOrPatch((ISegment?)(object)dotNetDirectory.ExportAddressTable, (ISegment?)(object)context2.BaseImage?.DotNetDirectory?.ExportAddressTable); AddOrPatch((ISegment?)dotNetDirectory.ManagedNativeHeader, (ISegment?)context2.BaseImage?.DotNetDirectory?.ManagedNativeHeader); if (result.Count <= 0) { return null; } return (ISegment?)(object)result; void AddOrPatch(ISegment? segment, ISegment? originalSegment) { if (segment != null && !TryPatchSegment(context2, segment, originalSegment)) { result.Add(segment, (uint)context2.Platform.PointerSize); } } } protected virtual PESection? CreateAuxRDataSection(BuilderContext context) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown BuilderContext context2 = context; PEImage image = context2.Image; SegmentBuilder contents = new SegmentBuilder(); TlsDirectory tlsDirectory = image.TlsDirectory; if (tlsDirectory != null) { TlsDirectory tlsDirectory2 = context2.BaseImage?.TlsDirectory; AddOrPatch((ISegment?)(object)tlsDirectory, (ISegment?)(object)tlsDirectory2); if (tlsDirectory.TemplateData != null) { AddOrPatch((ISegment?)(object)tlsDirectory.TemplateData, (ISegment?)(object)tlsDirectory2?.TemplateData); } if (((Collection)(object)tlsDirectory.CallbackFunctions).Count > 0) { AddOrPatch((ISegment?)(object)tlsDirectory.CallbackFunctions, (ISegment?)(object)tlsDirectory2?.CallbackFunctions); } } if (contents.Count == 0) { return null; } return new PESection(Utf8String.op_Implicit(".rdata"), (SectionFlags)1073741888, (ISegment)(object)contents); void AddOrPatch(ISegment? newSegment, ISegment? originalSegment) { if (newSegment != null && (originalSegment == null || !TryPatchSegment(context2, originalSegment, newSegment))) { contents.Add(newSegment, (uint)context2.Platform.PointerSize); } } } protected virtual PESection? CreateAuxDataSection(BuilderContext context) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown PEImage image = context.Image; SegmentBuilder val = new SegmentBuilder(); if (TrampolineVTableFixups) { VTableFixupsDirectory vTableFixupsDirectory = image.DotNetDirectory?.VTableFixups; if (vTableFixupsDirectory != null) { for (int i = 0; i < vTableFixupsDirectory.Count; i++) { val.Add((ISegment)(object)vTableFixupsDirectory[i].Tokens, (uint)context.Platform.PointerSize); } } } ExportDirectory exports = image.Exports; if (exports != null) { IList entries = exports.Entries; if (entries != null && entries.Count > 0) { val.Add((ISegment)(object)context.ExportDirectory, (uint)context.Platform.PointerSize); } } TlsDirectory tlsDirectory = image.TlsDirectory; if (tlsDirectory != null && !(tlsDirectory.Index is PESegmentReference) && tlsDirectory.Index.IsBounded) { ISegment segment = tlsDirectory.Index.GetSegment(); if (segment != null) { ISegmentReference val2 = context.BaseImage?.TlsDirectory?.Index; if (val2 == null || !TryPatchSegment(context, segment, ((IOffsetProvider)val2).Rva, 4u)) { val.Add(segment); } } } if (val.Count == 0) { return null; } return new PESection(Utf8String.op_Implicit(".auxdata"), (SectionFlags)(-1073741760), (ISegment)(object)val); } protected virtual PESection? CreateAuxRsrcSection(BuilderContext context) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (context.ResourceDirectory.IsEmpty) { return null; } if (TryPatchDataDirectory(context, (ISegment?)(object)context.ResourceDirectory, (DataDirectoryIndex)2)) { return null; } return new PESection(Utf8String.op_Implicit(".auxrsrc"), (SectionFlags)1073741888, (ISegment)(object)context.ResourceDirectory); } protected virtual PESection? CreateAuxRelocSection(BuilderContext context) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (context.RelocationsDirectory.IsEmpty) { return null; } if (TryPatchDataDirectory(context, (ISegment?)(object)context.RelocationsDirectory, (DataDirectoryIndex)5)) { return null; } return new PESection(Utf8String.op_Implicit(".reloc"), (SectionFlags)1107296320, (ISegment)(object)context.RelocationsDirectory); } protected override void CreateDataDirectoryBuffers(BuilderContext context) { CreateDotNetDirectories(context); base.CreateDataDirectoryBuffers(context); } protected override void CreateImportDirectory(BuilderContext context) { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown BuilderContext context2 = context; if (!TrampolineImports) { return; } IList list = context2.BaseImage?.Imports; if (list == null) { return; } IList newDirectory = context2.Image.Imports; if (newDirectory == null) { return; } foreach (ImportedModule item in list) { foreach (ImportedSymbol symbol in item.Symbols) { ImportedSymbol importedSymbol = FindNewImportedSymbol(symbol); if (importedSymbol == null) { continue; } switch (ImportedSymbolClassifier.Classify(importedSymbol)) { case ImportedSymbolType.Function: context2.ImportTrampolines.AddFunctionTableSlotTrampoline((ISymbol)(object)symbol, (ISymbol)(object)importedSymbol); break; case ImportedSymbolType.Data: { TrampolineTableBuffer importTrampolines = context2.ImportTrampolines; if (importTrampolines.VirtualProtect == null) { ImportedSymbol importedSymbol3 = (importTrampolines.VirtualProtect = GetOrCreateVirtualProtect()); } context2.ImportTrampolines.AddDataSlotInitializer((ISymbol)(object)symbol, (ISymbol)(object)importedSymbol); break; } default: throw new ArgumentOutOfRangeException(); } } } ISymbol dataInitializerSymbol = context2.ImportTrampolines.DataInitializerSymbol; if (dataInitializerSymbol != null) { PEImage image = context2.Image; TlsDirectory tlsDirectory2 = image.TlsDirectory ?? (image.TlsDirectory = new TlsDirectory()); RelocationParameters val = new RelocationParameters(0uL, 0uL, 0u, context2.Platform.Is32Bit); ((SegmentBase)tlsDirectory2).UpdateOffsets(ref val); if (tlsDirectory2.Index == SegmentReference.Null) { tlsDirectory2.Index = Extensions.ToReference((ISegment)new ZeroesSegment(8u)); } ((Collection)(object)tlsDirectory2.CallbackFunctions).Insert(0, dataInitializerSymbol.GetReference()); } base.CreateImportDirectory(context2); ImportedSymbol? FindNewImportedSymbol(ImportedSymbol symbol) { foreach (ImportedModule item2 in newDirectory) { if (!(symbol.DeclaringModule.Name != item2.Name)) { foreach (ImportedSymbol symbol2 in item2.Symbols) { if (symbol.IsImportByName && symbol2.IsImportByName && symbol2.Name == symbol.Name) { return symbol2; } if (symbol.IsImportByOrdinal && symbol2.IsImportByOrdinal && symbol2.Ordinal == symbol.Ordinal) { return symbol2; } } } } return null; } ImportedSymbol GetOrCreateVirtualProtect() { bool flag = false; ImportedModule importedModule = context2.Image.Imports.FirstOrDefault((ImportedModule x) => x.Name?.Equals("kernel32.dll", StringComparison.OrdinalIgnoreCase) ?? false); if (importedModule == null) { importedModule = new ImportedModule("KERNEL32.dll"); flag = true; } ImportedSymbol importedSymbol4 = importedModule.Symbols.FirstOrDefault((ImportedSymbol x) => x.Name == "VirtualProtect"); if (importedSymbol4 == null) { importedSymbol4 = new ImportedSymbol(0, "VirtualProtect"); importedModule.Symbols.Add(importedSymbol4); } if (flag) { context2.ImportDirectory.AddModule(importedModule); } return importedSymbol4; } } protected override void CreateRelocationsDirectory(BuilderContext context) { base.CreateRelocationsDirectory(context); foreach (BaseRelocation requiredBaseRelocation in context.ImportTrampolines.GetRequiredBaseRelocations()) { context.RelocationsDirectory.Add(requiredBaseRelocation); } foreach (BaseRelocation requiredBaseRelocation2 in context.VTableTrampolines.GetRequiredBaseRelocations()) { context.RelocationsDirectory.Add(requiredBaseRelocation2); } TlsDirectory tlsDirectory = context.Image.TlsDirectory; if (tlsDirectory == null) { return; } foreach (BaseRelocation requiredBaseRelocation3 in tlsDirectory.GetRequiredBaseRelocations()) { context.RelocationsDirectory.Add(requiredBaseRelocation3); } } private void CreateDotNetDirectories(BuilderContext context) { ProcessRvasInMetadataTables(context); AddVTableFixupTrampolines(context); } private void ProcessRvasInMetadataTables(BuilderContext context) { TablesStream tablesStream = context.Image.DotNetDirectory?.Metadata?.GetStream(); if (tablesStream != null) { AddMethodBodiesToTable(context, tablesStream); AddFieldRvasToTable(context, tablesStream); } } private void AddMethodBodiesToTable(BuilderContext context, TablesStream tablesStream) { MetadataTable table = tablesStream.GetTable(); for (uint num = 1u; num <= table.Count; num++) { ref MethodDefinitionRow rowRef = ref table.GetRowRef(num); ISegment methodBodySegment = GetMethodBodySegment(rowRef); if (methodBodySegment is CilRawMethodBody body) { context.MethodBodyTable.AddCilBody(body); } else { if (methodBodySegment == null) { continue; } context.MethodBodyTable.AddNativeBody(methodBodySegment, (uint)context.Platform.PointerSize); } rowRef.Body = Extensions.ToReference(methodBodySegment); } } private static ISegment? GetMethodBodySegment(MethodDefinitionRow methodRow) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) ISegmentReference body = methodRow.Body; if (body.IsBounded) { return body.GetSegment(); } if (body.CanRead && (methodRow.ImplAttributes & AsmResolver.PE.DotNet.Metadata.Tables.MethodImplAttributes.Runtime) == 0) { BinaryStreamReader reader = body.CreateReader(); return (ISegment?)(object)CilRawMethodBody.FromReader((IErrorListener)(object)ThrowErrorListener.Instance, ref reader); } return null; } private void AddFieldRvasToTable(BuilderContext context, TablesStream tablesStream) { DotNetDirectory dotNetDirectory = context.Image.DotNetDirectory; MetadataTable table = tablesStream.GetTable(TableIndex.FieldRva); if (table.Count == 0) { return; } SegmentBuilder fieldRvaTable = context.FieldRvaTable; IFieldRvaDataReader fieldRvaDataReader = context.FieldRvaDataReader; for (uint num = 1u; num <= table.Count; num++) { ref FieldRvaRow rowRef = ref table.GetRowRef(num); if (!(rowRef.Data is PESegmentReference)) { ISegment val = fieldRvaDataReader.ResolveFieldData(ErrorListener, context.Platform, dotNetDirectory, in rowRef); if (val != null) { fieldRvaTable.Add(val); rowRef.Data = Extensions.ToReference(val); } } } } private void AddVTableFixupTrampolines(BuilderContext context) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (!TrampolineVTableFixups) { return; } VTableFixupsDirectory vTableFixupsDirectory = context.BaseImage?.DotNetDirectory?.VTableFixups; if (vTableFixupsDirectory == null) { return; } VTableFixupsDirectory newDirectory = context.Image.DotNetDirectory?.VTableFixups; if (newDirectory == null) { return; } foreach (VTableFixup item in vTableFixupsDirectory) { for (int i = 0; i < item.Tokens.Count; i++) { ISymbol val = FindNewTokenSlot(item.Tokens[i]); if (val != null) { Symbol functionTableSlot = new Symbol(item.Tokens.GetReferenceToIndex(i)); context.VTableTrampolines.AddFunctionTableSlotTrampoline((ISymbol)(object)functionTableSlot, val); } } } ISymbol? FindNewTokenSlot(MetadataToken token) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown foreach (VTableFixup item2 in newDirectory) { for (int j = 0; j < item2.Tokens.Count; j++) { if (item2.Tokens[j] == token) { return (ISymbol?)new Symbol(item2.Tokens.GetReferenceToIndex(j)); } } } return null; } } private static bool TryPatchDataDirectory(BuilderContext context, ISegment? segment, DataDirectoryIndex directoryIndex) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (segment != null) { PEFile val = context.BaseImage?.PEFile; if (val != null) { DataDirectory dataDirectory = val.OptionalHeader.GetDataDirectory(directoryIndex); return TryPatchSegment(context, segment, ((DataDirectory)(ref dataDirectory)).VirtualAddress, ((DataDirectory)(ref dataDirectory)).Size); } } return false; } private static bool TryPatchSegment(BuilderContext context, ISegment? segment, ISegment? originalSegment) { if (segment == null || originalSegment == null) { return false; } return TryPatchSegment(context, segment, ((IOffsetProvider)originalSegment).Rva, ((IWritable)originalSegment).GetPhysicalSize()); } private static bool TryPatchSegment(BuilderContext context, ISegment? segment, uint rva, uint size) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (segment != null) { PEFile val = context.BaseImage?.PEFile; if (val != null) { RelocationParameters val2 = new RelocationParameters(context.Image.ImageBase, val.RvaToFileOffset(rva), rva, context.Platform.Is32Bit); segment.UpdateOffsets(ref val2); if (((IWritable)segment).GetPhysicalSize() <= size && context.TryGetSectionContainingRva(rva, out PESection section) && section.Contents != null) { uint num = rva - section.Rva; section.Contents = (ISegment)(object)Extensions.AsPatchedSegment(section.Contents).Patch(num, segment); return true; } return false; } } return false; } } }