Example #1
0
        /// <summary>
        /// Try to read program header.
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        /// Thrown if the stream was disposed.
        /// </exception>
        /// <exception cref="IOException">
        /// Thrown in case of any problems during reading.
        /// </exception>
        /// <param name="reader">Input stream reader.</param>
        /// <param name="result">Read header or empty header.</param>
        /// <returns>
        /// True if program header was successfully read and false otherwise.
        /// </returns>
        public static bool TryRead(BinaryReader reader, out ProgramHeader result)
        {
            result = EmptyHeader;
            if (!HeadersReadingUtils.IsEnoughBytes(reader, Size))
            {
                return(false);
            }

            var typeValue = reader.ReadUInt32();
            var flags     = reader.ReadUInt32();
            var offset    = reader.ReadUInt64();
            var vaddr     = reader.ReadUInt64();
            var paddr     = reader.ReadUInt64();
            var filesz    = reader.ReadUInt64();
            var memsz     = reader.ReadUInt64();
            var align     = reader.ReadUInt64();

            if (!Enum.TryParse(typeValue.ToString(), out Type type) ||
                !Enum.IsDefined(typeof(Type), type))
            {
                type = Type.Other;
            }

            result = new ProgramHeader(type, offset, vaddr, filesz);
            return(true);
        }
Example #2
0
        /// <summary>
        /// Read all note sections until the end of stream and parse file indexes from them.
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        /// Thrown if the stream was disposed.
        /// </exception>
        /// <exception cref="IOException">
        /// Thrown in case of any problems during reading.
        /// </exception>
        /// <param name="reader">Input stream reader.</param>
        /// <param name="size">Expected note section size from program header.</param>
        /// <returns>Core module files sections.</returns>
        public static IEnumerable <FileSection> ReadModuleSections(BinaryReader reader, int size)
        {
            var result = new List <FileSection>();

            foreach (NoteSection note in ReadNotes(reader, size))
            {
                if (note._name != Name.Core || note._type != Type.File)
                {
                    continue;
                }

                var noteStream = new MemoryStream(note._data);
                using (var noteReader = new BinaryReader(noteStream))
                {
                    if (!HeadersReadingUtils.IsEnoughBytes(noteReader, MinNtFileIndexSize))
                    {
                        continue;
                    }

                    int   count    = (int)noteReader.ReadUInt64();
                    ulong pageSize = noteReader.ReadUInt64();

                    int locationsSize = FileLocationSize * count;
                    if (!HeadersReadingUtils.IsEnoughBytes(noteReader, locationsSize))
                    {
                        continue;
                    }

                    var starts  = new ulong[count];
                    var ends    = new ulong[count];
                    var offsets = new ulong[count];
                    for (int i = 0; i < count; i++)
                    {
                        starts[i]  = noteReader.ReadUInt64();
                        ends[i]    = noteReader.ReadUInt64();
                        offsets[i] = noteReader.ReadUInt64();
                    }

                    for (int i = 0; i < count; i++)
                    {
                        string path = ReadUtf8String(noteReader);

                        // We assume the build id lives in the first location.
                        if (offsets[i] == 0)
                        {
                            result.Add(new FileSection(path, starts[i], ends[i]));
                        }
                    }
                }
            }

            return(result);
        }
Example #3
0
        static List <NoteSection> ReadNotes(BinaryReader reader, int size)
        {
            var notes = new List <NoteSection>();

            if (!HeadersReadingUtils.IsEnoughBytes(reader, Math.Max(size, MinNoteSize)))
            {
                return(notes);
            }

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                if (!HeadersReadingUtils.IsEnoughBytes(reader, MinNoteSize))
                {
                    break;
                }

                int  nameSize        = reader.ReadInt32();
                int  descriptionSize = reader.ReadInt32();
                uint typeValue       = reader.ReadUInt32();

                int namePadding = HeadersReadingUtils.GetInt32ValuePadding(nameSize);
                int dataPadding = HeadersReadingUtils.GetInt32ValuePadding(descriptionSize);
                int noteSize    = nameSize + namePadding + descriptionSize + dataPadding;
                if (!HeadersReadingUtils.IsEnoughBytes(reader, noteSize))
                {
                    break;
                }

                byte[] nameBytes = reader.ReadBytes(nameSize);
                reader.ReadBytes(namePadding);

                byte[] desc = reader.ReadBytes(descriptionSize);

                reader.ReadBytes(dataPadding);

                string nameString = Encoding.UTF8.GetString(nameBytes, 0, nameBytes.Length - 1);

                Type type;
                switch (typeValue)
                {
                case NtFileType:
                    type = Type.File;
                    break;

                case NtGnuBuildIdType:
                    type = Type.BuildId;
                    break;

                default:
                    type = Type.Other;
                    break;
                }

                Name name;
                switch (nameString)
                {
                case GnuName:
                    name = Name.Gnu;
                    break;

                case CoreName:
                    name = Name.Core;
                    break;

                default:
                    name = Name.Other;
                    break;
                }

                notes.Add(new NoteSection(type, name, desc));
            }

            return(notes);
        }
Example #4
0
        /// <summary>
        /// Try to read elf header.
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        /// Thrown if the stream was disposed.
        /// </exception>
        /// <exception cref="IOException">
        /// Thrown in case of any problems during reading.
        /// </exception>
        /// <param name="reader">Input stream reader.</param>
        /// <param name="result">Read header or empty header.</param>
        /// <returns>
        /// True if x64 elf header with little endianness and correct elf version was successfully
        /// read and false otherwise.
        /// </returns>
        public static bool TryRead(BinaryReader reader, out ElfHeader result)
        {
            result = EmptyHeader;
            if (!HeadersReadingUtils.IsEnoughBytes(reader, Size))
            {
                return(false);
            }

            var ei_magic       = reader.ReadInt32();
            var ei_bitness     = reader.ReadByte();
            var ei_endianness  = reader.ReadByte();
            var ei_version     = reader.ReadByte();
            var ei_abi         = reader.ReadByte();
            var ei_abi_version = reader.ReadByte();
            var ei_padding     = reader.ReadBytes(PaddingSize);
            var e_type         = reader.ReadInt16();
            var e_machine      = reader.ReadInt16();
            var e_version      = reader.ReadInt32();
            var e_entry        = reader.ReadInt64();

            // Points to the start of the program header table.
            var e_phoff  = reader.ReadUInt64();
            var e_shoff  = reader.ReadUInt64();
            var e_flags  = reader.ReadInt32();
            var e_ehsize = reader.ReadUInt16();

            // Contains the size of a program header table entry.
            var e_phentsize = reader.ReadUInt16();

            // Contains the number of entries in the program header table.
            var e_phnum     = reader.ReadUInt16();
            var e_shentsize = reader.ReadUInt16();
            var e_shnum     = reader.ReadUInt16();
            var e_shstrndx  = reader.ReadUInt16();

            if (ei_magic != ElfMagicNumber)
            {
                Trace.WriteLine($"Invalid ELF magic {ElfMagicNumber} expected {ei_magic}.");
                return(false);
            }

            if (ei_bitness != (byte)Bitness.x64)
            {
                Trace.WriteLine("Only 64-bit elf supported.");
                return(false);
            }

            if (ei_endianness != (byte)Endianness.Little)
            {
                Trace.WriteLine("Only little endian supported.");
                return(false);
            }

            if (ei_version != CurrentElfVersion)
            {
                Trace.WriteLine($"Invalid elf version: {ei_version} expected: " +
                                $"{CurrentElfVersion}.");
                return(false);
            }

            result = new ElfHeader(e_phoff, e_phentsize, e_phnum, e_type == (byte)Type.Executable);
            return(true);
        }