Esempio n. 1
0
        public static CilExtraSection FromReader(IBinaryStreamReader reader)
        {
            var section = new CilExtraSection
            {
                Attributes = (CilExtraSectionAttributes)reader.ReadByte()
            };

            if (!section.IsExceptionHandler)
            {
                throw new NotSupportedException("Invalid or unsupported extra section.");
            }

            int dataSize;

            if (section.IsFat)
            {
                dataSize = reader.ReadByte() |
                           (reader.ReadByte() << 0x08) |
                           (reader.ReadByte() << 0x10);
            }
            else
            {
                dataSize = reader.ReadByte();
                reader.ReadUInt16();
            }
            section.Data = reader.ReadBytes(dataSize);

            return(section);
        }
Esempio n. 2
0
        /// <summary>
        /// Reads a DOS header structure at the current position of the provided input stream.
        /// </summary>
        /// <param name="reader">The input stream to read from.</param>
        /// <returns>The read DOS header.</returns>
        /// <exception cref="BadImageFormatException">Occurs when the input stream does not point to a valid DOS header.</exception>
        public static DosHeader FromReader(IBinaryStreamReader reader)
        {
            ulong offset = reader.Offset;
            uint  rva    = reader.Rva;

            var stub = new byte[DefaultNewHeaderOffset];

            ushort magic = reader.ReadUInt16();

            if (magic != ValidPEMagic)
            {
                throw new BadImageFormatException();
            }

            reader.Offset += NextHeaderFieldOffset - 2;
            uint nextHeaderOffset = reader.ReadUInt32();

            if (nextHeaderOffset != DefaultNewHeaderOffset)
            {
                Array.Resize(ref stub, (int)nextHeaderOffset);
            }

            reader.Offset -= NextHeaderFieldOffset + 4;
            reader.ReadBytes(stub, 0, stub.Length);

            return(new DosHeader(stub)
            {
                Offset = offset,
                Rva = rva,
                NextHeaderOffset = nextHeaderOffset
            });
        }
Esempio n. 3
0
        /// <summary>
        /// Reads a single extra section from the provided input stream.
        /// </summary>
        /// <param name="reader">The input stream to read from.</param>
        /// <returns>The extra section that was read.</returns>
        public static CilExtraSection FromReader(IBinaryStreamReader reader)
        {
            var section = new CilExtraSection
            {
                Attributes = (CilExtraSectionAttributes)reader.ReadByte()
            };

            int dataSize;

            if (section.IsFat)
            {
                dataSize = reader.ReadByte() |
                           (reader.ReadByte() << 0x08) |
                           (reader.ReadByte() << 0x10);
            }
            else
            {
                dataSize = reader.ReadByte();
                reader.ReadUInt16();
            }

            section.Data = new byte[dataSize];
            reader.ReadBytes(section.Data, 0, dataSize);

            return(section);
        }
Esempio n. 4
0
        public new static CilRawFatMethodBody FromReader(IBinaryStreamReader reader)
        {
            var body = new CilRawFatMethodBody
            {
                _header  = reader.ReadUInt16(),
                MaxStack = reader.ReadUInt16()
            };

            int codeSize = reader.ReadInt32();

            body.LocalVarSigToken = reader.ReadUInt32();

            body.Code = reader.ReadBytes(codeSize);

            if (body.HasSections)
            {
                reader.Align(4);

                CilExtraSection section;
                do
                {
                    section = CilExtraSection.FromReader(reader);
                    body.ExtraSections.Add(section);
                } while (section.HasMoreSections);
            }

            return(body);
        }
Esempio n. 5
0
        protected string ReadString(IBinaryStreamReader reader)
        {
            var offset = (uint)(reader.Position - reader.StartPosition);

            string value;

            if (_cachedStrings.TryGetValue(offset, out value))
            {
                reader.Position += 1 + Encoding.Unicode.GetByteCount(value) + 1;
            }
            else
            {
                var length = reader.ReadCompressedUInt32();
                if (length <= 0)
                {
                    return(string.Empty);
                }

                value = Encoding.Unicode.GetString(reader.ReadBytes((int)length - 1));
                reader.Position++;

                _cachedStrings.Add(offset, value);
            }

            return(value);
        }
Esempio n. 6
0
 public static DataBlobSignature FromReader(IBinaryStreamReader reader)
 {
     long position = reader.Position;
     return new DataBlobSignature(reader.ReadBytes((int) reader.Length))
     {
         StartOffset = position
     };
 }
Esempio n. 7
0
        /// <summary>
        /// Reads a raw method body from the given binary input stream using the fat method body format.
        /// </summary>
        /// <param name="errorListener">The object responsible for recording parser errors.</param>
        /// <param name="reader">The binary input stream to read from.</param>
        /// <returns>The raw method body.</returns>
        /// <exception cref="FormatException">Occurs when the method header indicates an method body that is not in the
        /// fat format.</exception>
        public new static CilRawFatMethodBody FromReader(IErrorListener errorListener, IBinaryStreamReader reader)
        {
            ulong fileOffset = reader.Offset;
            uint  rva        = reader.Rva;

            // Read flags.
            ushort header     = reader.ReadUInt16();
            var    flags      = (CilMethodBodyAttributes)(header & 0xFFF);
            int    headerSize = (header >> 12) * sizeof(uint);

            // Verify this is a fat method body.
            if ((flags & CilMethodBodyAttributes.Fat) != CilMethodBodyAttributes.Fat)
            {
                errorListener.BadImage("Invalid fat CIL method body header.");
                return(null);
            }

            // Read remaining header.
            ushort maxStack         = reader.ReadUInt16();
            uint   codeSize         = reader.ReadUInt32();
            uint   localVarSigToken = reader.ReadUInt32();

            // Move to code.
            reader.Offset = fileOffset + (ulong)headerSize;

            // Verify code size.
            if (reader.Offset + codeSize > reader.StartOffset + reader.Length)
            {
                errorListener.BadImage("Invalid fat CIL method body code size.");
                return(null);
            }

            // Read code.
            var code = new byte[codeSize];

            reader.ReadBytes(code, 0, code.Length);

            // Create body.
            var body = new CilRawFatMethodBody(flags, maxStack, localVarSigToken, code);

            body.UpdateOffsets(fileOffset, rva);

            // Read any extra sections.
            if (body.HasSections)
            {
                reader.Align(4);

                CilExtraSection section;
                do
                {
                    section = CilExtraSection.FromReader(reader);
                    body.ExtraSections.Add(section);
                } while (section.HasMoreSections);
            }

            return(body);
        }
Esempio n. 8
0
        public new static CilRawSmallMethodBody FromReader(IBinaryStreamReader reader)
        {
            int codeSize = reader.ReadByte() >> 2;

            return(new CilRawSmallMethodBody
            {
                Code = reader.ReadBytes(codeSize)
            });
        }
Esempio n. 9
0
 public ImageSection(ImageSectionHeader header, IBinaryStreamReader reader)
 {
     if (header == null)
     {
         throw new ArgumentNullException("header");
     }
     Header = header;
     Segments.Add(new DataSegment(reader.ReadBytes((int)reader.Length)));
 }
Esempio n. 10
0
        public static DataBlobSignature FromReader(IBinaryStreamReader reader)
        {
            long position = reader.Position;

            return(new DataBlobSignature(reader.ReadBytes((int)reader.Length))
            {
                StartOffset = position
            });
        }
        /// <summary>
        /// Reads all remaining data from the input stream.
        /// </summary>
        /// <param name="reader">The input stream.</param>
        /// <returns>The remaining bytes of the input stream.</returns>
        public static byte[] ReadToEnd(this IBinaryStreamReader reader)
        {
            int remainingByteCount = (int)(reader.Length - (reader.FileOffset - reader.StartPosition));
            var buffer             = new byte[remainingByteCount];
            int read = reader.ReadBytes(buffer, 0, remainingByteCount);

            if (read != remainingByteCount)
            {
                Array.Resize(ref buffer, read);
            }
            return(buffer);
        }
Esempio n. 12
0
        /// <summary>
        /// Reads an icon resource entry from an input stream.
        /// </summary>
        /// <param name="reader">The input stream.</param>
        /// <returns>The parsed icon resource entry.</returns>
        public static IconEntry FromReader(IBinaryStreamReader reader)
        {
            var result = new IconEntry
            {
                Offset  = reader.Offset,
                Rva     = reader.Rva,
                RawIcon = new byte[reader.Length]
            };

            reader.ReadBytes(result.RawIcon, 0, (int)reader.Length);

            return(result);
        }
Esempio n. 13
0
        /// <summary>
        /// Reads a serialized UTF8 string from the steram.
        /// </summary>
        /// <param name="reader">The reader to use for reading the data.</param>
        /// <returns>The string that was read from the stream.</returns>
        public static string ReadSerString(this IBinaryStreamReader reader)
        {
            if (reader.ReadByte() == 0xFF)
            {
                return(null);
            }
            reader.Position--;
            uint length;

            if (!reader.TryReadCompressedUInt32(out length))
            {
                return(null);
            }
            return(Encoding.UTF8.GetString(reader.ReadBytes((int)length)));
        }
Esempio n. 14
0
        /// <summary>
        /// Reads a single data segment at the current position of the provided input stream.
        /// </summary>
        /// <param name="reader">The input stream to read from.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The read data segment.</returns>
        public static DataSegment FromReader(IBinaryStreamReader reader, int count)
        {
            ulong position = reader.Offset;
            uint  rva      = reader.Rva;

            var buffer = new byte[count];

            reader.ReadBytes(buffer, 0, count);

            return(new DataSegment(buffer)
            {
                Offset = position,
                Rva = rva
            });
        }
Esempio n. 15
0
        /// <summary>
        /// Reads a metadata directory from an input stream.
        /// </summary>
        /// <param name="context">The reader context.</param>
        /// <param name="directoryReader">The input stream containing the metadata directory.</param>
        /// <exception cref="ArgumentNullException">Occurs when any of the arguments are <c>null</c>.</exception>
        /// <exception cref="NotSupportedException">Occurs when an unsupported metadata directory format was encountered.</exception>
        /// <exception cref="BadImageFormatException">Occurs when the metadata directory header is invalid.</exception>
        public SerializedMetadata(PEReaderContext context, IBinaryStreamReader directoryReader)
        {
            if (directoryReader == null)
            {
                throw new ArgumentNullException(nameof(directoryReader));
            }
            _context = context ?? throw new ArgumentNullException(nameof(context));

            _streamContentsReader = directoryReader.Fork();

            var signature = (MetadataSignature)directoryReader.ReadUInt32();

            switch (signature)
            {
            case MetadataSignature.Bsjb:
                // BSJB header is the default header.
                break;

            case MetadataSignature.Moc:
                _context.NotSupported("Old +MOC metadata header format is not supported.");
                return;

            default:
                _context.BadImage($"Invalid metadata header ({(uint) signature:X8}).");
                return;
            }

            MajorVersion = directoryReader.ReadUInt16();
            MinorVersion = directoryReader.ReadUInt16();
            Reserved     = directoryReader.ReadUInt32();

            int versionLength = directoryReader.ReadInt32();

            if (!directoryReader.CanRead(versionLength))
            {
                _context.BadImage($"Invalid version length in metadata header ({versionLength.ToString()} characters).");
                return;
            }

            var versionBytes = new byte[versionLength];

            directoryReader.ReadBytes(versionBytes, 0, versionBytes.Length);
            VersionString = Encoding.ASCII.GetString(versionBytes);

            Flags                = directoryReader.ReadUInt16();
            _numberOfStreams     = directoryReader.ReadInt16();
            _streamEntriesReader = directoryReader.Fork();
        }
        /// <summary>
        /// Reads a serialized UTF8 string from the stream.
        /// </summary>
        /// <param name="reader">The reader to use for reading the data.</param>
        /// <returns>The string that was read from the stream.</returns>
        public static string ReadSerString(this IBinaryStreamReader reader)
        {
            if (!reader.CanRead(1) || reader.ReadByte() == 0xFF)
            {
                return(null);
            }
            reader.FileOffset--;
            if (!reader.TryReadCompressedUInt32(out uint length))
            {
                return(null);
            }
            var data = new byte[length];

            length = (uint)reader.ReadBytes(data, 0, (int)length);
            return(Encoding.UTF8.GetString(data, 0, (int)length));
        }
Esempio n. 17
0
        private Guid ReadGuid(IBinaryStreamReader reader)
        {
            Guid guid;
            var  offset = (uint)(reader.Position - reader.StartPosition) + 1;

            if (!_cachedGuids.TryGetValue(offset, out guid))
            {
                _cachedGuids.Add(offset, guid = new Guid(reader.ReadBytes(16)));
            }
            else
            {
                reader.Position += 16;
            }

            return(guid);
        }
Esempio n. 18
0
        /// <summary>
        /// Initializes a new instance of <see cref="RsdsDataSegment"/>
        /// </summary>
        /// <param name="context">Context for the reader</param>
        /// <param name="reader">The input stream to read from.</param>
        /// <returns></returns>
        public new static RsdsDataSegment FromReader(PEReaderContext context, IBinaryStreamReader reader)
        {
            if (reader.Length < RsdsExpectedDataSize)
            {
                context.BadImage("RSDS Data was shorter than the minimal expected length");
                return(null);
            }
            var result = new RsdsDataSegment();

            byte[] buffer = new byte[16];
            reader.ReadBytes(buffer, 0, 16);
            result.Guid = new Guid(buffer);
            result.Age  = reader.ReadUInt32();
            result.Path = Encoding.UTF8.GetString(reader.ReadBytesUntil(0x00));

            return(result);
        }
Esempio n. 19
0
        /// <summary>
        /// Reads a metadata directory from an input stream.
        /// </summary>
        /// <param name="reader">The input stream.</param>
        /// <param name="metadataStreamReader"></param>
        /// <exception cref="ArgumentNullException">Occurs when any of the arguments are <c>null</c>.</exception>
        /// <exception cref="NotSupportedException">Occurs when an unsupported metadata directory format was encountered.</exception>
        /// <exception cref="BadImageFormatException">Occurs when the metadata directory header is invalid.</exception>
        public SerializedMetadata(IBinaryStreamReader reader, IMetadataStreamReader metadataStreamReader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }
            _metadataStreamReader = metadataStreamReader;

            _streamContentsReader = reader.Fork();

            var signature = (MetadataSignature)reader.ReadUInt32();

            switch (signature)
            {
            case MetadataSignature.Bsjb:
                // BSJB header is the default header.
                break;

            case MetadataSignature.Moc:
                throw new NotSupportedException("Old +MOC metadata header format is not supported.");

            default:
                throw new BadImageFormatException($"Invalid metadata header ({(uint) signature:X8}).");
            }

            MajorVersion = reader.ReadUInt16();
            MinorVersion = reader.ReadUInt16();
            Reserved     = reader.ReadUInt32();

            int versionLength = reader.ReadInt32();

            if (!reader.CanRead(versionLength))
            {
                throw new BadImageFormatException($"Invalid version length in metadata header ({versionLength} characters).");
            }

            var versionBytes = new byte[versionLength];

            reader.ReadBytes(versionBytes, 0, versionBytes.Length);
            VersionString = Encoding.ASCII.GetString(versionBytes);

            Flags                = reader.ReadUInt16();
            _numberOfStreams     = reader.ReadInt16();
            _streamEntriesReader = reader.Fork();
        }
Esempio n. 20
0
        /// <summary>
        /// Reads a private key from an input stream.
        /// </summary>
        /// <param name="reader">The input stream.</param>
        /// <returns>The private key.</returns>
        /// <exception cref="FormatException">Occurs when the input stream is not in the correct format.</exception>
        /// <exception cref="NotSupportedException">Occurs when an invalid or unsupported algorithm is specified.</exception>
        public new static StrongNamePrivateKey FromReader(IBinaryStreamReader reader)
        {
            // Read BLOBHEADER
            ReadBlobHeader(reader, StrongNameKeyStructureType.PrivateKeyBlob, 2, SignatureAlgorithm.RsaSign);

            // Read RSAPUBKEY
            if ((RsaPublicKeyMagic)reader.ReadUInt32() != RsaPublicKeyMagic.Rsa2)
            {
                throw new FormatException("Input stream does not contain a valid RSA private key header magic.");
            }

            uint bitLength = reader.ReadUInt32();
            uint length8   = bitLength / 8;
            uint length16  = bitLength / 16;

            var result = new StrongNamePrivateKey
            {
                PublicExponent = reader.ReadUInt32(),
                Modulus        = new byte[length8],
                P               = new byte[length16],
                Q               = new byte[length16],
                DP              = new byte[length16],
                DQ              = new byte[length16],
                InverseQ        = new byte[length16],
                PrivateExponent = new byte[length8]
            };

            reader.ReadBytes(result.Modulus, 0, result.Modulus.Length);

            // Read private data.
            reader.ReadBytes(result.P, 0, result.P.Length);
            reader.ReadBytes(result.Q, 0, result.Q.Length);
            reader.ReadBytes(result.DP, 0, result.DP.Length);
            reader.ReadBytes(result.DQ, 0, result.DQ.Length);
            reader.ReadBytes(result.InverseQ, 0, result.InverseQ.Length);
            reader.ReadBytes(result.PrivateExponent, 0, result.PrivateExponent.Length);

            Array.Reverse(result.Modulus);
            Array.Reverse(result.P);
            Array.Reverse(result.Q);
            Array.Reverse(result.DP);
            Array.Reverse(result.DQ);
            Array.Reverse(result.InverseQ);
            Array.Reverse(result.PrivateExponent);

            return(result);
        }
Esempio n. 21
0
        /// <summary>
        /// Reads a single section header at the current position of the provided input stream.
        /// </summary>
        /// <param name="reader">The input stream to read from.</param>
        /// <returns>The section header that was read.</returns>
        public static SectionHeader FromReader(IBinaryStreamReader reader)
        {
            uint offset = reader.FileOffset;

            var nameBytes = new byte[8];

            reader.ReadBytes(nameBytes, 0, nameBytes.Length);

            return(new SectionHeader(Encoding.UTF8.GetString(nameBytes).Replace("\0", ""), 0)
            {
                _fileOffset = offset,
                VirtualSize = reader.ReadUInt32(),
                VirtualAddress = reader.ReadUInt32(),
                SizeOfRawData = reader.ReadUInt32(),
                PointerToRawData = reader.ReadUInt32(),
                PointerToRelocations = reader.ReadUInt32(),
                PointerToLineNumbers = reader.ReadUInt32(),
                NumberOfRelocations = reader.ReadUInt16(),
                NumberOfLineNumbers = reader.ReadUInt16(),
                Characteristics = (SectionFlags)reader.ReadUInt32()
            });
        }
Esempio n. 22
0
        private static KeyValuePair <string, string> ReadEntry(IBinaryStreamReader reader)
        {
            uint start = reader.FileOffset;

            // Read header.
            var header = VersionTableEntryHeader.FromReader(reader);

            reader.Align(4);

            // Read value.
            var data  = new byte[header.ValueLength * sizeof(char)];
            int count = reader.ReadBytes(data, 0, data.Length);

            // Exclude zero terminator.
            count = Math.Max(count - 2, 0);
            string value = Encoding.Unicode.GetString(data, 0, count);

            // Skip any unprocessed bytes.
            reader.FileOffset = start + header.Length;

            return(new KeyValuePair <string, string>(header.Key, value));
        }
        /// <summary>
        /// Reads a raw method body from the given binary input stream using the tiny method body format.
        /// </summary>
        /// <param name="reader">The binary input stream to read from.</param>
        /// <returns>The raw method body.</returns>
        /// <exception cref="FormatException">Occurs when the method header indicates an method body that is not in the
        /// tiny format.</exception>
        public new static CilRawTinyMethodBody FromReader(IBinaryStreamReader reader)
        {
            ulong fileOffset = reader.Offset;
            uint  rva        = reader.Rva;

            var flag = (CilMethodBodyAttributes)reader.ReadByte();

            if ((flag & CilMethodBodyAttributes.Tiny) != CilMethodBodyAttributes.Tiny)
            {
                throw new FormatException("Invalid tiny CIL method body header.");
            }

            int codeSize = (byte)flag >> 2;
            var code     = new byte[codeSize];

            reader.ReadBytes(code, 0, codeSize);

            var methodBody = new CilRawTinyMethodBody(code);

            methodBody.UpdateOffsets(fileOffset, rva);
            return(methodBody);
        }
Esempio n. 24
0
        /// <summary>
        /// Reads a private key from an input stream.
        /// </summary>
        /// <param name="reader">The input stream.</param>
        /// <returns>The private key.</returns>
        /// <exception cref="FormatException">Occurs when the input stream is not in the correct format.</exception>
        /// <exception cref="NotSupportedException">Occurs when an invalid or unsupported algorithm is specified.</exception>
        public static StrongNamePublicKey FromReader(IBinaryStreamReader reader)
        {
            // Read BLOBHEADER
            ReadBlobHeader(reader, StrongNameKeyStructureType.PublicKeyBlob, 2, SignatureAlgorithm.RsaSign);

            // Read RSAPUBKEY
            if ((RsaPublicKeyMagic)reader.ReadUInt32() != RsaPublicKeyMagic.Rsa1)
            {
                throw new FormatException("Input stream does not contain a valid RSA public key header magic.");
            }

            uint bitLength = reader.ReadUInt32();

            var result = new StrongNamePublicKey
            {
                PublicExponent = reader.ReadUInt32(),
                Modulus        = new byte[bitLength / 8]
            };

            reader.ReadBytes(result.Modulus, 0, result.Modulus.Length);

            return(result);
        }
Esempio n. 25
0
 /// <summary>
 /// Aligns the reader to a specified boundary.
 /// </summary>
 /// <param name="reader">The reader to align.</param>
 /// <param name="align">The boundary to use.</param>
 public static void Align(this IBinaryStreamReader reader, int align)
 {
     align--;
     reader.ReadBytes((((int)reader.Position + align) & ~align) - (int)reader.Position);
 }
Esempio n. 26
0
 public static DataSegment FromReader(IBinaryStreamReader reader)
 {
     return(new DataSegment(reader.ReadBytes(
                                (int)(reader.Length - (reader.Position - reader.StartPosition)))));
 }
Esempio n. 27
0
 public static DataBlobSignature FromReader(IBinaryStreamReader reader)
 {
     return(new DataBlobSignature(reader.ReadBytes((int)reader.Length)));
 }
Esempio n. 28
0
 public static byte[] ReadToEnd(this IBinaryStreamReader reader)
 {
     return(reader.ReadBytes((int)(reader.Length - (reader.Position - reader.StartPosition))));
 }