/// <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); }
/// <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); }
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); }
/// <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); }