Example #1
0
        public void Dispose()
        {
            if(this.memmap != null)
                this.memmap.Dispose();

            this.memmap = null;

            //this.cursor = null;
            this.sectionHeaders = null;
            this.identifierStringHeap = null;
            this.generalStringHeap = null;
            this.blobHeap = null;
            this.guidHeap = null;
            this.tables = null;
            this.tablesHeader = null;
            this.targetRuntimeVersion = null;
            this.tableSize = null;
            this.tableRefSize = null;
            this.tableOffset = null;
            this.HashValue = null;
        }
Example #2
0
        private void ReadHeader()
        { //TODO: break up this method
            MemoryCursor c = this.cursor;
            c.Position = 0;

            ReadDOSHeader(c);
            NTHeader ntHeader = ReadNTHeader(c);
            this.linkerMajorVersion = ntHeader.majorLinkerVersion;
            this.linkerMinorVersion = ntHeader.minorLinkerVersion;
            this.fileAlignment = ntHeader.fileAlignment;
            if ((ntHeader.characteristics & 0x2000) != 0)
                this.moduleKind = ModuleKind.DynamicallyLinkedLibrary;
            else
                this.moduleKind = ntHeader.subsystem == 0x3 ? ModuleKind.ConsoleApplication : ModuleKind.WindowsApplication;

            int sectionCount = ntHeader.numberOfSections;
            SectionHeader[] sectionHeaders = this.sectionHeaders = new SectionHeader[sectionCount];
            int resourceSectionIndex = -1;
            for (int i = 0; i < sectionCount; i++)
            {
                sectionHeaders[i] = ReadSectionHeader(c);
                if (sectionHeaders[i].name == ".rsrc") resourceSectionIndex = i;
            }
            if (resourceSectionIndex >= 0)
                this.win32ResourcesOffset = sectionHeaders[resourceSectionIndex].pointerToRawData;
            else
                this.win32ResourcesOffset = -1;

            DirectoryEntry de = ntHeader.cliHeaderTable;
            int cliHeaderOffset = this.RvaToOffset(de.virtualAddress);
            c.Position = cliHeaderOffset;

            CLIHeader cliHeader = ReadCLIHeader(c);
            this.entryPointToken = cliHeader.entryPointToken;
            if ((cliHeader.flags & 1) != 0)
                this.peKind = PEKindFlags.ILonly;
            if ((cliHeader.flags & 0x10) != 0)
                this.entryPointToken = 0; //Native entry point. Ignore.
            switch (ntHeader.machine)
            {
                case 0x0200:
                    this.peKind |= PEKindFlags.Requires64bits;
                    break;
                case 0x8664:
                    this.peKind |= PEKindFlags.Requires64bits | PEKindFlags.AMD;
                    break;
                default:
                    if (ntHeader.magic == 0x20B) //Optional header magic for PE32+
                        this.peKind |= PEKindFlags.Requires64bits;
                    else if ((cliHeader.flags & 2) != 0)
                        this.peKind |= PEKindFlags.Requires32bits;
                    break;
            }
            this.TrackDebugData = (cliHeader.flags & 0x10000) != 0;
            if (cliHeader.resources.size > 0)
                this.resourcesOffset = this.RvaToOffset(cliHeader.resources.virtualAddress);

            int snSize = cliHeader.strongNameSignature.size;
            if (snSize > 0)
            {
                long hashOffset = this.RvaToOffset(cliHeader.strongNameSignature.virtualAddress);
                c.Position = (int)hashOffset;
                this.HashValue = c.ReadBytes(snSize);
                bool zeroHash = true;
                for (int i = 0; i < snSize; i++) if (this.HashValue[i] != 0) zeroHash = false;
                if (zeroHash) this.HashValue = null; //partially signed assembly
            }

            long mdOffset = this.mdOffset = this.RvaToOffset(cliHeader.metaData.virtualAddress);
            c.Position = (int)mdOffset;
            MetadataHeader mdHeader = ReadMetadataHeader(c);
            this.targetRuntimeVersion = mdHeader.versionString;

            foreach (StreamHeader sheader in mdHeader.streamHeaders)
            {
                //^ assume sheader != null;
                switch (sheader.name)
                {
                    case "#Strings": this.identifierStringHeap = sheader; continue;
                    case "#US": this.generalStringHeap = sheader; continue;
                    case "#Blob": this.blobHeap = sheader; continue;
                    case "#GUID": this.guidHeap = sheader; continue;
                    case "#~": this.tables = sheader; continue;
                    case "#-": this.tables = sheader; continue;
                    default: continue;
                }
            }
            if (this.tables == null) throw new InvalidMetadataException(ExceptionStrings.NoMetadataStream);
            c.Position = (int)(mdOffset + this.tables.offset);
            TablesHeader tablesHeader = this.tablesHeader = ReadTablesHeader(c);
            this.metadataFormatMajorVersion = tablesHeader.majorVersion;
            this.metadataFormatMinorVersion = tablesHeader.minorVersion;

            int[] tableSize = this.tableSize = new int[(int)TableIndices.Count];
            int[] tableRefSize = this.tableRefSize = new int[(int)TableIndices.Count];
            long valid = tablesHeader.maskValid;
            int[] countArray = tablesHeader.countArray;
            //^ assume countArray != null;
            for (int i = 0, j = 0; i < (int)TableIndices.Count; i++)
            {
                if (valid % 2 == 1)
                {
                    int m = tableSize[i] = countArray[j++];
                    tableRefSize[i] = m < 0x10000 ? 2 : 4;
                }
                else
                    tableRefSize[i] = 2;
                valid /= 2;
            }
            int blobRefSize = this.blobRefSize = ((tablesHeader.heapSizes & 0x04) == 0 ? 2 : 4);
            int constantParentRefSize = this.constantParentRefSize =
              tableSize[(int)TableIndices.Param] < 0x4000 &&
              tableSize[(int)TableIndices.Field] < 0x4000 &&
              tableSize[(int)TableIndices.Property] < 0x4000 ? 2 : 4;
            int customAttributeParentRefSize = 0;
            if (this.metadataFormatMajorVersion > 1 || this.metadataFormatMinorVersion > 0)
            {
                customAttributeParentRefSize = this.customAttributeParentRefSize =
                  tableSize[(int)TableIndices.Method] < 0x0800 &&
                  tableSize[(int)TableIndices.Field] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeRef] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeDef] < 0x0800 &&
                  tableSize[(int)TableIndices.Param] < 0x0800 &&
                  tableSize[(int)TableIndices.InterfaceImpl] < 0x0800 &&
                  tableSize[(int)TableIndices.MemberRef] < 0x0800 &&
                  tableSize[(int)TableIndices.Module] < 0x0800 &&
                  tableSize[(int)TableIndices.DeclSecurity] < 0x0800 &&
                  tableSize[(int)TableIndices.Property] < 0x0800 &&
                  tableSize[(int)TableIndices.Event] < 0x0800 &&
                  tableSize[(int)TableIndices.StandAloneSig] < 0x0800 &&
                  tableSize[(int)TableIndices.ModuleRef] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeSpec] < 0x0800 &&
                  tableSize[(int)TableIndices.Assembly] < 0x0800 &&
                  tableSize[(int)TableIndices.File] < 0x0800 &&
                  tableSize[(int)TableIndices.ExportedType] < 0x0800 &&
                  tableSize[(int)TableIndices.ManifestResource] < 0x0800 &&
                  tableSize[(int)TableIndices.GenericParam] < 0x0800 &&
                  tableSize[(int)TableIndices.MethodSpec] < 0x0800 &&
                  tableSize[(int)TableIndices.GenericParamConstraint] < 0x0800 ? 2 : 4;
            }
            else
            {
                customAttributeParentRefSize = this.customAttributeParentRefSize =
                  tableSize[(int)TableIndices.Method] < 0x0800 &&
                  tableSize[(int)TableIndices.Field] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeRef] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeDef] < 0x0800 &&
                  tableSize[(int)TableIndices.Param] < 0x0800 &&
                  tableSize[(int)TableIndices.InterfaceImpl] < 0x0800 &&
                  tableSize[(int)TableIndices.MemberRef] < 0x0800 &&
                  tableSize[(int)TableIndices.Module] < 0x0800 &&
                  tableSize[(int)TableIndices.DeclSecurity] < 0x0800 &&
                  tableSize[(int)TableIndices.Property] < 0x0800 &&
                  tableSize[(int)TableIndices.Event] < 0x0800 &&
                  tableSize[(int)TableIndices.StandAloneSig] < 0x0800 &&
                  tableSize[(int)TableIndices.ModuleRef] < 0x0800 &&
                  tableSize[(int)TableIndices.TypeSpec] < 0x0800 &&
                  tableSize[(int)TableIndices.Assembly] < 0x0800 &&
                  tableSize[(int)TableIndices.File] < 0x0800 &&
                  tableSize[(int)TableIndices.ExportedType] < 0x0800 &&
                  tableSize[(int)TableIndices.ManifestResource] < 0x0800 ? 2 : 4;
            }
            int customAttributeConstructorRefSize = this.customAttributeConstructorRefSize =
              tableSize[(int)TableIndices.Method] < 0x2000 &&
              tableSize[(int)TableIndices.MemberRef] < 0x2000 ? 2 : 4;
            int declSecurityParentRefSize = this.declSecurityParentRefSize =
              tableSize[(int)TableIndices.TypeDef] < 0x4000 &&
              tableSize[(int)TableIndices.Method] < 0x4000 &&
              tableSize[(int)TableIndices.Assembly] < 0x4000 ? 2 : 4;
            int fieldMarshalParentRefSize = this.fieldMarshalParentRefSize =
              tableSize[(int)TableIndices.Field] < 0x8000 &&
              tableSize[(int)TableIndices.Param] < 0x8000 ? 2 : 4;
            int guidRefSize = this.guidRefSize = ((tablesHeader.heapSizes & 0x02) == 0 ? 2 : 4);
            int hasSemanticRefSize = this.hasSemanticRefSize =
              tableSize[(int)TableIndices.Event] < 0x8000 &&
              tableSize[(int)TableIndices.Property] < 0x8000 ? 2 : 4;
            int implementationRefSize = this.implementationRefSize =
              tableSize[(int)TableIndices.File] < 0x4000 &&
              tableSize[(int)TableIndices.AssemblyRef] < 0x4000 &&
              tableSize[(int)TableIndices.ExportedType] < 0x4000 ? 2 : 4;
            int methodDefOrRefSize = this.methodDefOrRefSize =
              tableSize[(int)TableIndices.Method] < 0x8000 &&
              tableSize[(int)TableIndices.MemberRef] < 0x8000 ? 2 : 4;
            int memberRefParentSize = this.memberRefParentSize =
              tableSize[(int)TableIndices.TypeDef] < 0x2000 &&
              tableSize[(int)TableIndices.TypeRef] < 0x2000 &&
              tableSize[(int)TableIndices.ModuleRef] < 0x2000 &&
              tableSize[(int)TableIndices.Method] < 0x2000 &&
              tableSize[(int)TableIndices.TypeSpec] < 0x2000 ? 2 : 4;
            int memberForwardedRefSize = this.memberForwardedRefSize =
              tableSize[(int)TableIndices.Field] < 0x8000 &&
              tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4;
            int typeDefOrMethodDefSize = this.typeDefOrMethodDefSize =
              tableSize[(int)TableIndices.TypeDef] < 0x8000 &&
              tableSize[(int)TableIndices.Method] < 0x8000 ? 2 : 4;
            int typeDefOrRefOrSpecSize = this.typeDefOrRefOrSpecSize =
              tableSize[(int)TableIndices.TypeDef] < 0x4000 &&
              tableSize[(int)TableIndices.TypeRef] < 0x4000 &&
              tableSize[(int)TableIndices.TypeSpec] < 0x4000 ? 2 : 4;
            int resolutionScopeRefSize = this.resolutionScopeRefSize =
              tableSize[(int)TableIndices.Module] < 0x4000 &&
              tableSize[(int)TableIndices.ModuleRef] < 0x4000 &&
              tableSize[(int)TableIndices.AssemblyRef] < 0x4000 &&
              tableSize[(int)TableIndices.TypeRef] < 0x4000 ? 2 : 4;
            int stringRefSize = this.stringRefSize = ((tablesHeader.heapSizes & 0x01) == 0 ? 2 : 4);

            int[] tableOffset = this.tableOffset = new int[(int)TableIndices.Count];
            int offset = this.mdOffset + this.tables.offset + 24 + countArray.Length * 4;
            for (int i = 0; i < (int)TableIndices.Count; i++)
            {
                int m = tableSize[i];
                if (m == 0) continue;
                tableOffset[i] = offset;
                switch ((TableIndices)i)
                {
                    case TableIndices.Module: offset += m * (2 + stringRefSize + 3 * guidRefSize); break;
                    case TableIndices.TypeRef: offset += m * (resolutionScopeRefSize + 2 * stringRefSize); break;
                    case TableIndices.TypeDef: offset += m * (4 + 2 * stringRefSize + typeDefOrRefOrSpecSize + tableRefSize[(int)TableIndices.Field] + tableRefSize[(int)TableIndices.Method]); break;
                    case TableIndices.FieldPtr: offset += m * (tableRefSize[(int)TableIndices.Field]); break;
                    case TableIndices.Field: offset += m * (2 + stringRefSize + blobRefSize); break;
                    case TableIndices.MethodPtr: offset += m * (tableRefSize[(int)TableIndices.Method]); break;
                    case TableIndices.Method: offset += m * (8 + stringRefSize + blobRefSize + tableRefSize[(int)TableIndices.Param]); break;
                    case TableIndices.ParamPtr: offset += m * (tableRefSize[(int)TableIndices.Param]); break;
                    case TableIndices.Param: offset += m * (4 + stringRefSize); break;
                    case TableIndices.InterfaceImpl: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + typeDefOrRefOrSpecSize); break;
                    case TableIndices.MemberRef: offset += m * (memberRefParentSize + stringRefSize + blobRefSize); break;
                    case TableIndices.Constant: offset += m * (2 + constantParentRefSize + blobRefSize); break;
                    case TableIndices.CustomAttribute: offset += m * (customAttributeParentRefSize + customAttributeConstructorRefSize + blobRefSize); break;
                    case TableIndices.FieldMarshal: offset += m * (fieldMarshalParentRefSize + blobRefSize); break;
                    case TableIndices.DeclSecurity: offset += m * (2 + declSecurityParentRefSize + blobRefSize); break;
                    case TableIndices.ClassLayout: offset += m * (6 + tableRefSize[(int)TableIndices.TypeDef]); break;
                    case TableIndices.FieldLayout: offset += m * (4 + tableRefSize[(int)TableIndices.Field]); break;
                    case TableIndices.StandAloneSig: offset += m * (blobRefSize); break;
                    case TableIndices.EventMap: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Event]); break;
                    case TableIndices.EventPtr: offset += m * (tableRefSize[(int)TableIndices.Event]); break;
                    case TableIndices.Event: offset += m * (2 + stringRefSize + typeDefOrRefOrSpecSize); break;
                    case TableIndices.PropertyMap: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + tableRefSize[(int)TableIndices.Property]); break;
                    case TableIndices.PropertyPtr: offset += m * (tableRefSize[(int)TableIndices.Property]); break;
                    case TableIndices.Property: offset += m * (2 + stringRefSize + blobRefSize); break;
                    case TableIndices.MethodSemantics: offset += m * (2 + tableRefSize[(int)TableIndices.Method] + hasSemanticRefSize); break;
                    case TableIndices.MethodImpl: offset += m * (tableRefSize[(int)TableIndices.TypeDef] + 2 * methodDefOrRefSize); break;
                    case TableIndices.ModuleRef: offset += m * (stringRefSize); break;
                    case TableIndices.TypeSpec: offset += m * (blobRefSize); break;
                    case TableIndices.ImplMap: offset += m * (2 + memberForwardedRefSize + stringRefSize + tableRefSize[(int)TableIndices.ModuleRef]); break;
                    case TableIndices.FieldRva: offset += m * (4 + tableRefSize[(int)TableIndices.Field]); break;
                    case TableIndices.EncLog: throw new InvalidMetadataException(ExceptionStrings.ENCLogTableEncountered);
                    case TableIndices.EncMap: throw new InvalidMetadataException(ExceptionStrings.ENCMapTableEncountered);
                    case TableIndices.Assembly: offset += m * (16 + blobRefSize + 2 * stringRefSize); break;
                    case TableIndices.AssemblyProcessor: offset += m * (4); break;
                    case TableIndices.AssemblyOS: offset += m * (12); break;
                    case TableIndices.AssemblyRef: offset += m * (12 + 2 * blobRefSize + 2 * stringRefSize); break;
                    case TableIndices.AssemblyRefProcessor: offset += m * (4 + tableRefSize[(int)TableIndices.AssemblyRef]); break;
                    case TableIndices.AssemblyRefOS: offset += m * (12 + tableRefSize[(int)TableIndices.AssemblyRef]); break;
                    case TableIndices.File: offset += m * (4 + stringRefSize + blobRefSize); break;
                    case TableIndices.ExportedType: offset += m * (8 + 2 * stringRefSize + implementationRefSize); break;
                    case TableIndices.ManifestResource: offset += m * (8 + stringRefSize + implementationRefSize); break;
                    case TableIndices.NestedClass: offset += m * (2 * tableRefSize[(int)TableIndices.TypeDef]); break;
                    case TableIndices.GenericParam:
                        if (this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 0)
                            offset += m * (6 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize);
                        else if (this.metadataFormatMajorVersion == 1 && this.metadataFormatMinorVersion == 1)
                            offset += m * (4 + typeDefOrMethodDefSize + stringRefSize + typeDefOrRefOrSpecSize);
                        else
                            offset += m * (4 + typeDefOrMethodDefSize + stringRefSize);
                        break;
                    case TableIndices.MethodSpec: offset += m * (methodDefOrRefSize + blobRefSize); break;
                    case TableIndices.GenericParamConstraint: offset += m * (tableRefSize[(int)TableIndices.GenericParam] + typeDefOrRefOrSpecSize); break;
                    default: throw new InvalidMetadataException(ExceptionStrings.UnsupportedTableEncountered);
                }
            }
        }
Example #3
0
 private static TablesHeader/*!*/ ReadTablesHeader(MemoryCursor/*!*/ c)
 {
     TablesHeader header = new TablesHeader();
     header.reserved = c.ReadInt32(); // Must be zero
     header.majorVersion = c.ReadByte();  // Must be one
     header.minorVersion = c.ReadByte();  // Must be zero
     header.heapSizes = c.ReadByte();  // Bits for heap sizes
     header.rowId = c.ReadByte();  // log-base-2 of largest rowId
     header.maskValid = c.ReadInt64(); // Present table counts
     header.maskSorted = c.ReadInt64(); // Sorted tables
     int n = 0;
     ulong mask = (ulong)header.maskValid;
     while (mask != 0)
     {
         if (mask % 2 == 1) n++;
         mask /= 2;
     }
     int[] countArray = header.countArray = new int[n];
     for (int i = 0; i < n; i++)
         countArray[i] = c.ReadInt32();
     return header;
 }