Beispiel #1
0
        internal void Load(Stream s)
        {
            s.AssumeNotNull();
            Reserved0 = s.ReadUIntLE();
            MajorVersion = s.ReadByteOrThrow();
            MinorVersion = s.ReadByteOrThrow();
            m_heapSizes = s.ReadByteOrThrow();
            Reserved1 = s.ReadByteOrThrow();
            ValidTables = s.ReadULongLE();

            Util.Assume(
                (ValidTables & ~s_validTableMask) == 0,
                "Unknown table specified in ValidTables mask"
            );

            SortedTables = s.ReadULongLE();

            var numberOfTables = ValidTables.NumberOfSetBits();

            Util.Assume((ValidTables & ~((1UL << (int)TableID.MAX_TABLE_ID) - 1)) == 0UL, "Unrecogonized meta-data table detected");
            Util.Assume(numberOfTables >= 1, "Too fiew meta-data tables");

            var rowCounts = new uint[numberOfTables];

            for (int i = 0; i < numberOfTables; ++i)
            {
                rowCounts[i] = s.ReadUIntLE();
            }

            RowCounts = new ReadOnlyCollection<uint>(rowCounts);
        }
Beispiel #2
0
        private void VerifyPESignature(Stream s)
        {
            s.AssumeNotNull();

            var signatureOffset = ReadSignatureOffset(s);
            s.Seek(signatureOffset);
            s.ReadBytes(4).AssumeEquals(
                s_peSignature,
                "Couldn't verify PE signature"
            );
        }
Beispiel #3
0
 public void ParseTable(Stream s, uint rowCount, TableID id)
 {
     s.AssumeNotNull();
     switch (id)
     {
         case TableID.Module:
             ParseModuleTable(s, rowCount);
             break;
         case TableID.TypeRef:
             ParseTypeRefTable(s, rowCount);
             break;
         case TableID.TypeDef:
             ParseTypeDefTable(s, rowCount);
             break;
         case TableID.Field:
             ParseFieldTable(s, rowCount);
             break;
         case TableID.MethodDef:
             ParseMethodDefTable(s, rowCount);
             break;
         case TableID.Param:
             ParseParamTable(s, rowCount);
             break;
         case TableID.InterfaceImpl:
             ParseInterfaceImplTable(s, rowCount);
             break;
         case TableID.MemberRef:
             ParseMemberRefTable(s, rowCount);
             break;
         case TableID.CustomAttribute:
             ParseCustomAttributeTable(s, rowCount);
             break;
         case TableID.FieldMarshal:
             ParseFieldMarshalTable(s, rowCount);
             break;
         case TableID.DeclSecurty:
             ParseDeclSecurityTable(s, rowCount);
             break;
         case TableID.ClassLayout:
             ParseClassLayoutTable(s, rowCount);
             break;
         case TableID.FieldLayout:
             ParseFieldLayoutTable(s, rowCount);
             break;
         case TableID.StandAloneSig:
             ParseStandAloneSigTable(s, rowCount);
             break;
         case TableID.EventMap:
             ParseEventMapTable(s, rowCount);
             break;
         case TableID.Event:
             ParseEventTable(s, rowCount);
             break;
         case TableID.PropertyMap:
             ParsePropertyMapTable(s, rowCount);
             break;
         case TableID.Property:
             ParsePRopertyTable(s, rowCount);
             break;
         case TableID.MethodSemantics:
             ParseMethodSemanticsTable(s, rowCount);
             break;
         case TableID.MethodImp:
             ParseMethodImplTable(s, rowCount);
             break;
         case TableID.ModuleRef:
             ParseModuleRefTable(s, rowCount);
             break;
         case TableID.TypeSpec:
             ParseTypeSpecTable(s, rowCount);
             break;
         case TableID.ImplMap:
             ParseImplMapTabble(s, rowCount);
             break;
         case TableID.FieldRVA:
             ParseFieldRVATable(s, rowCount);
             break;
         case TableID.Assembly:
             ParseAssemblyTable(s, rowCount);
             break;
         case TableID.AssemblyProcessor:
             ParseAssemblyProcessorTable(s, rowCount);
             break;
         case TableID.AssemblyOS:
             ParseAssemblyOSTable(s, rowCount);
             break;
         case TableID.AssemblyRef:
             ParseAssemblyRefTable(s, rowCount);
             break;
         case TableID.AssemblyRefProcessor:
             ParseAssemblyRefProcessorTable(s, rowCount);
             break;
         case TableID.AssemblyRefOS:
             ParseAssemblyRefOsTable(s, rowCount);
             break;
         case TableID.File:
             ParseAssemblyFileTable(s, rowCount);
             break;
         case TableID.ExportedType:
             ParseExportedTypeTable(s, rowCount);
             break;
         case TableID.ManifestResource:
             ParseMainfestResourceTable(s, rowCount);
             break;
         case TableID.NestedClass:
             ParseNestedClassTable(s, rowCount);
             break;
         case TableID.GenericParam:
             ParseGenericParamTable(s, rowCount);
             break;
         case TableID.MethodSpec:
             ParseMethodSpecTable(s, rowCount);
             break;
         case TableID.GenericParamConstraint:
             ParseGenericParamConstraintTable(s, rowCount);
             break;
         default:
             throw new InternalErrorException("Unknown table id");
     }
 }
Beispiel #4
0
        private void ParseSectionMap(Stream s)
        {
            //NOTE: We loose the ordering sections were specified in the file
            //here. That's OK for now, because we have a read-only structure.
            //If we ever need to use this code for round-tripping PE files,
            //then this needs to be modified to also track section order.

            s.AssumeNotNull();
            m_header.AssumeNotNull();

            m_sections =
                new RegionMap<SectionHeader>(
                    x => x.SectionRVA,
                    x => x.VirtualSize
                );

            for (int i = 0; i < m_header.NumberOfSections; ++i)
            {
                var section = new SectionHeader();
                section.Load(s);
                m_sections.Add(section);
            }
        }
Beispiel #5
0
 private void ParsePEHeader(Stream s)
 {
     s.AssumeNotNull();
     m_header = new PEHeader();
     m_header.Load(s);
 }
Beispiel #6
0
        private void ParseMetadaRoot(Stream s)
        {
            s.AssumeNotNull();
            var rootPointer =
                m_clrHeader.AssumeNotNull("Missing CLR Header")
                .MetaDataPointer.AssumeNotNull("Missing meta-data Root");

            rootPointer.RVA.AssumeGt(0, "Missing meta-data root");
            rootPointer.Size.AssumeGt(0, "Missing meta-data root");

            SectionHeader section;

            m_sections.TryGetValue(
                rootPointer.RVA,
                out section
            ).AssumeTrue("Invalid meta-data root.");

            section.AssumeNotNull();
            section.IsInitializedData(rootPointer).AssumeTrue("Invalid meta-data root.");

            s.Seek(
                section.PointerToRawData +
                (rootPointer.RVA - section.SectionRVA).AssumeGte(0)
            );

            m_metadataRoot = new ClrMetadataRoot();
            m_metadataRoot.Load(s, rootPointer.Size);
        }
Beispiel #7
0
        private void ParseClrHeader(Stream s)
        {
            s.AssumeNotNull();
            m_sections.AssumeNotNull();
            m_header.AssumeNotNull();

            var sectionIndex = (int) DataDirectoryName.CLRRuntimeHeader;

            if (
                m_header.DataDirectories != null
                && sectionIndex < m_header.DataDirectories.Count
                && sectionIndex >=0
            )
            {
                var dd = m_header.DataDirectories[sectionIndex];

                //find the section containing the RVA of the data directory.
                //For C# code this will almost always end up being the
                //".rdata" section, but the CLR Ecma spec does not require
                //this, and we are likely to find our selfs dissasembling
                //mixed-mode assemblies at some point in time anyways
                //(which can do arbitrarily weird things with executable
                //layout). This also makes us somewhat future proof.
                var section = m_sections[dd.RVA];

                if (section == null || dd.Size <= 0 || dd.RVA <= 0)
                {
                    return;
                }

                if (!section.IsInitializedData(dd))
                {
                    //If we reach here, it means that the CIL header is (at
                    //least partially) located in uinitialized data, or crosses
                    //section boundaries. Neither is likely to happen in
                    //practice. The Ecma-335 spec (4th edition)
                    //says that the CIL header should be in a "read only,
                    //shared section of the image".
                    //
                    //If we see something like this, chances are we
                    //screwed up somewhere along the way during parsing, or
                    //the image we are reading is bad. However, it is also
                    //possible that someone is trying to do something clever,
                    //by initializing CLR meta-data in native code before
                    //invoking the CLR's native entry point (_CorExeMain /
                    // _CorDllMain). In either case, this means we can't
                    //dissasemble this managed executable (because we don't
                    //know what the meta-data is), so we throw an exception.
                    //
                    //It is technically possible to handle the cross-section
                    //case, if the initialized data from the first section
                    //terminates neatly on a page boundary (or the presence
                    //of zero padding still yields a valid header), and the
                    //"second" section contains initialized data. However,
                    //such cases are not likely to be produced by a real
                    //compiler, and likely come from either a bad image,
                    //from a hand crafted edge case, or from a user with
                    //malicious intent. In any case, it's best to throw here.
                    throw new InternalErrorException(
                        "Refusing to read non standard clr header."
                    );
                }

                s.Seek(
                    section.PointerToRawData
                    + (dd.RVA - section.SectionRVA).AssumeGte(0)
                );

                m_clrHeader = new ClrHeader();
                m_clrHeader.Load(s);
            }
        }
Beispiel #8
0
        private SubStream GetSubStream(Stream s, string streamName, string errorMessage)
        {
            s.AssumeNotNull();
            m_metadataRoot.AssumeNotNull();
            m_clrHeader.AssumeNotNull();
            m_clrHeader.MetaDataPointer.AssumeNotNull();
            streamName.AssumeNotNull();
            errorMessage.AssumeNotNull();

            var streamHeader = m_metadataRoot.StreamHeaders[streamName];

            if (streamHeader != null && streamHeader.Size > 0)
            {
                var streamRVA =
                    m_clrHeader.MetaDataPointer.RVA
                    + streamHeader.Offset;

                var section = m_sections[streamRVA];

                section.IsInitializedData(streamRVA, streamHeader.Size)
                    .AssumeTrue(
                        "Invalid metadata stream"
                    );

                s.Seek(
                    section.PointerToRawData
                    + (streamRVA - section.SectionRVA).AssumeGte(0)
                );

                return new SubStream(s, streamHeader.Size, errorMessage);
            }

            return null;
        }