示例#1
0
        //Construct the binary assembly instance
        public PEFile(string fileName)
        {
            this.FileName = fileName;

            //Open the assembly's binary file in shared-read mode and copy it into a buffer so we can close the file post haste.
            FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

            byte[] streamBuffer = new byte[fileStream.Length];
            fileStream.Read(streamBuffer, 0, (int)fileStream.Length);
            fileStream.Close();

            //Push the buffer into a memory stream and then access it through a binary reader
            this.streamReader = new BinaryReader(new MemoryStream(streamBuffer));

            // The rest of the code moves through the loaded assemebly as follows:
            // 1) DOS header points to the PE header.
            // 2) PE header contains a the CLI directory that points to the The CLI header.
            // 3) In order to work out the RVAs, we need the "Sections" of the file.
            // 4) CLI header in turn contains the RVA to MetaData directory.
            // 5) Metadata header points to the metadata root.
            // 6) metadata root lists the metadata stream headers.
            // 7) metadata stream headers contain the offsets to the metadata stream.  Hooray!

            // We only need certain elements of the file. Those elements we
            // need are stored in structs/classes, the elements we don't need
            // are parsed by methods whose purpose is:
            // a) to move the stream position to where we need it,
            // b) to be substituted with classes as the scope of requirements increases.


            ParseMsDosHeader(this.streamReader);
            this.peFileHeader = new PEFileHeader(this.streamReader);
            ParsePeOptionalHeader(this.streamReader);
            BuildSections(this.streamReader);

            // Now we have the sections we can work out where RVAs lie,
            // so we can get the CLI Header, which in turn allows us to get the
            // metadata directory.
            ParseCliHeader(this.streamReader);
            this.metaDataDirectory = new Directory(this.streamReader);

            this.streamReader.BaseStream.Position = GetOffsetFromRVA(this.metaDataDirectory.Rva);
            this.metaDataRoot = new MetaDataRoot(this.streamReader);

            // now we have the metadataroot complete with the metadata stream headers,
            // we can build the metadata streams.
            BuildMetaDataStreams(this.streamReader);

            // the following builds the descriptive structure found at the start of the #~ stream
            // first off, move to the correct point in the file as the previous step will have left
            // us in the wrong place
            this.streamReader.BaseStream.Position = this.tablesStream.StartPositionInFile;
            this.tablesHeader = new TablesHeader(this.streamReader, this.stringHeap);

            // now we have the tables header, we can build the tables
            this.tables = new Tables(this.tablesHeader, this.stringHeap, this.streamReader);
        }
        public Tables(TablesHeader tablesHeader, MetaDataStream stringHeap, BinaryReader reader)
        {
            this.tablesHeader       = tablesHeader;
            this.stringHeap         = stringHeap;
            this.reader             = reader;
            this.indexSizeIndicator = tablesHeader.HeapSizes;
            this.RowsPerTable       = tablesHeader.NumberOfRows;

            // set up a table of coded index information
            // the first figure in the array is the number of bits needed to encode
            // which table the index is pointing to.  Note, some indexes use more bits
            // than are necessary, for example CustomAttributeType uses 3 bits even though
            // it only points to 2 tables, so in theory could be encoded in 1 bit.

            this.CodedIndexInformation = new object[12];
            CodedIndexInformation[(int)Tables.CodedIndexType.TypeDefOrRef]       = new int[] { 2, (int)Tables.TableName.TypeDef, (int)Tables.TableName.TypeRef, (int)Tables.TableName.TypeSpec };
            CodedIndexInformation[(int)Tables.CodedIndexType.HasConstant]        = new int[] { 2, (int)Tables.TableName.Field, (int)Tables.TableName.Param, (int)Tables.TableName.Property };
            CodedIndexInformation[(int)Tables.CodedIndexType.HasCustomAttribute] = new int[] { 5, (int)Tables.TableName.MethodDef,
                                                                                               (int)Tables.TableName.Field,
                                                                                               (int)Tables.TableName.TypeRef,
                                                                                               (int)Tables.TableName.TypeDef,
                                                                                               (int)Tables.TableName.Param,
                                                                                               (int)Tables.TableName.InterfaceImpl,
                                                                                               (int)Tables.TableName.MemberRef,
                                                                                               (int)Tables.TableName.Module,
                                                                                               (int)Tables.TableName.DeclSecurity,
                                                                                               (int)Tables.TableName.Property,
                                                                                               (int)Tables.TableName.EventX,
                                                                                               (int)Tables.TableName.StandAloneSig,
                                                                                               (int)Tables.TableName.ModuleRef,
                                                                                               (int)Tables.TableName.TypeSpec,
                                                                                               (int)Tables.TableName.Assembly,
                                                                                               (int)Tables.TableName.AssemblyRef,
                                                                                               (int)Tables.TableName.File,
                                                                                               (int)Tables.TableName.ExportedType,
                                                                                               (int)Tables.TableName.ManifestResource };
            CodedIndexInformation[(int)Tables.CodedIndexType.HasFieldMarshal]     = new int[] { 1, (int)Tables.TableName.Field, (int)Tables.TableName.Param };
            CodedIndexInformation[(int)Tables.CodedIndexType.HasDeclSecurity]     = new int[] { 2, (int)Tables.TableName.TypeDef, (int)Tables.TableName.MethodDef, (int)Tables.TableName.Assembly };
            CodedIndexInformation[(int)Tables.CodedIndexType.MemberRefParent]     = new int[] { 3, (int)Tables.TableName.TypeRef, (int)Tables.TableName.ModuleRef, (int)Tables.TableName.MethodDef, (int)Tables.TableName.TypeSpec };
            CodedIndexInformation[(int)Tables.CodedIndexType.HasSemantics]        = new int[] { 1, (int)Tables.TableName.EventX, (int)Tables.TableName.Property };
            CodedIndexInformation[(int)Tables.CodedIndexType.MethodDefOrRef]      = new int[] { 1, (int)Tables.TableName.MethodDef, (int)Tables.TableName.MemberRef };
            CodedIndexInformation[(int)Tables.CodedIndexType.MemberForwarded]     = new int[] { 1, (int)Tables.TableName.Field, (int)Tables.TableName.MethodDef };
            CodedIndexInformation[(int)Tables.CodedIndexType.Implementation]      = new int[] { 2, (int)Tables.TableName.File, (int)Tables.TableName.AssemblyRef, (int)Tables.TableName.ExportedType };
            CodedIndexInformation[(int)Tables.CodedIndexType.CustomAttributeType] = new int[] { 3, (int)Tables.TableName.MethodDef, (int)Tables.TableName.MemberRef };
            CodedIndexInformation[(int)Tables.CodedIndexType.ResolutionScope]     = new int[] { 2, (int)Tables.TableName.Module, (int)Tables.TableName.ModuleRef, (int)Tables.TableName.AssemblyRef, (int)Tables.TableName.TypeRef };

            this.Module          = new Module(Tables.TableName.Module, this);
            this.TypeRef         = new TypeRef(Tables.TableName.TypeRef, this);
            this.TypeDef         = new TypeDef(Tables.TableName.TypeDef, this);
            this.Field           = new Field(Tables.TableName.Field, this);
            this.MethodDef       = new MethodDef(Tables.TableName.MethodDef, this);
            this.Param           = new Param(Tables.TableName.Param, this);
            this.InterfaceImpl   = new InterfaceImpl(Tables.TableName.InterfaceImpl, this);
            this.MemberRef       = new MemberRef(Tables.TableName.MemberRef, this);
            this.Constant        = new Constant(Tables.TableName.Constant, this);
            this.CustomAttribute = new CustomAttribute(Tables.TableName.CustomAttribute, this);
            this.FieldMarshal    = new FieldMarshal(Tables.TableName.FieldMarshal, this);
            this.DeclSecurity    = new DeclSecurity(Tables.TableName.DeclSecurity, this);
            this.ClassLayout     = new ClassLayout(Tables.TableName.ClassLayout, this);
            this.FieldLayout     = new FieldLayout(Tables.TableName.FieldLayout, this);
            this.StandAloneSig   = new StandAloneSig(Tables.TableName.StandAloneSig, this);
            this.EventMap        = new EventMap(Tables.TableName.EventMap, this);
            this.EventX          = new EventX(Tables.TableName.EventX, this);
            this.PropertyMap     = new PropertyMap(Tables.TableName.PropertyMap, this);
            this.Property        = new Property(Tables.TableName.Property, this);
            this.MethodSemantics = new MethodSemantics(Tables.TableName.MethodSemantics, this);
            this.MethodImpl      = new MethodImpl(Tables.TableName.MethodImpl, this);
            this.ModuleRef       = new ModuleRef(Tables.TableName.ModuleRef, this);
            this.TypeSpec        = new TypeSpec(Tables.TableName.TypeSpec, this);
            this.ImplMap         = new ImplMap(Tables.TableName.ImplMap, this);
        }