From 982b4b168d4f516f40cd0fc89421e8c393c308e1 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Mon, 21 Oct 2019 00:12:51 +0200 Subject: [PATCH] Tidy up ElfReader --- .../FileFormatReaders/ElfReader.cs | 84 +++++++------------ 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/Il2CppInspector/FileFormatReaders/ElfReader.cs b/Il2CppInspector/FileFormatReaders/ElfReader.cs index 91ea5fd..bfe8bb9 100644 --- a/Il2CppInspector/FileFormatReaders/ElfReader.cs +++ b/Il2CppInspector/FileFormatReaders/ElfReader.cs @@ -7,17 +7,16 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Net.Sockets; namespace Il2CppInspector { internal class ElfReader : FileFormatReader { - private program_header_table[] program_table_element; + private program_header_table[] program_header_table; private elf_32_shdr[] section_header_table; + private elf_32_dynamic[] dynamic_table; private elf_header elf_header; public ElfReader(Stream stream) : base(stream) { } @@ -47,8 +46,19 @@ namespace Il2CppInspector // 64-bit not supported return false; } - program_table_element = ReadArray(elf_header.e_phoff, elf_header.e_phnum); + + program_header_table = ReadArray(elf_header.e_phoff, elf_header.e_phnum); section_header_table = ReadArray(elf_header.e_shoff, elf_header.e_shnum); + + if (program_header_table.FirstOrDefault(x => x.p_type == 2) is program_header_table PT_DYNAMIC) // PT_DYNAMIC = 2 + dynamic_table = ReadArray(PT_DYNAMIC.p_offset, (int) PT_DYNAMIC.p_filesz / 8 /* sizeof(elf_32_dynamic) */); + + // Get global offset table + var _GLOBAL_OFFSET_TABLE_ = dynamic_table.First(x => x.d_tag == 3).d_un; // DT_PLTGOT + if (_GLOBAL_OFFSET_TABLE_ == 0) + throw new InvalidOperationException("Unable to get GLOBAL_OFFSET_TABLE from PT_DYNAMIC"); + GlobalOffset = _GLOBAL_OFFSET_TABLE_; + return true; } @@ -61,32 +71,27 @@ namespace Il2CppInspector if (SHT_STRTAB != null) { // Section header shared object symbol table (.symtab) - if (section_header_table.FirstOrDefault(x => x.sh_type == 2u) is elf_32_shdr SHT_SYMTAB) // SHT_SYMTAB = 2 + if (section_header_table.FirstOrDefault(x => x.sh_type == 2) is elf_32_shdr SHT_SYMTAB) // SHT_SYMTAB = 2 pTables.Add((SHT_SYMTAB.sh_offset, SHT_SYMTAB.sh_size / SHT_SYMTAB.sh_entsize, SHT_STRTAB.sh_offset)); // Section header executable symbol table (.dynsym) - if (section_header_table.FirstOrDefault(x => x.sh_type == 11u) is elf_32_shdr SHT_DYNSYM) // SHT_DYNSUM = 11 + if (section_header_table.FirstOrDefault(x => x.sh_type == 11) is elf_32_shdr SHT_DYNSYM) // SHT_DYNSUM = 11 pTables.Add((SHT_DYNSYM.sh_offset, SHT_DYNSYM.sh_size / SHT_DYNSYM.sh_entsize, SHT_STRTAB.sh_offset)); } // Symbol table in dynamic section (DT_SYMTAB) // Normally the same as .dynsym except that .dynsym may be removed in stripped binaries - if (program_table_element.FirstOrDefault(x => x.p_type == 2u) is program_header_table PT_DYNAMIC) // PT_DYNAMIC = 2 - { - // Get the dynamic table - var dynamic_table = ReadArray(PT_DYNAMIC.p_offset, (int) PT_DYNAMIC.p_filesz / 8 /* sizeof(elf_32_dynamic) */); - // Dynamic string table - var DT_STRTAB = dynamic_table.FirstOrDefault(x => x.d_tag == 5u); // DT_STRTAB = 5 + // Dynamic string table + var DT_STRTAB = dynamic_table?.FirstOrDefault(x => x.d_tag == 5); // DT_STRTAB = 5 - if (DT_STRTAB != null) { - if (dynamic_table.FirstOrDefault(x => x.d_tag == 6u) is elf_32_dynamic DT_SYMTAB) { // DT_SYMTAB = 6 - // Find the next pointer in the dynamic table to calculate the length of the symbol table - var end = (from x in dynamic_table where x.d_un > DT_SYMTAB.d_un orderby x.d_un select x).First().d_un; + if (DT_STRTAB != null) { + if (dynamic_table.FirstOrDefault(x => x.d_tag == 6) is elf_32_dynamic DT_SYMTAB) { // DT_SYMTAB = 6 + // Find the next pointer in the dynamic table to calculate the length of the symbol table + var end = (from x in dynamic_table where x.d_un > DT_SYMTAB.d_un orderby x.d_un select x).First().d_un; - // Dynamic symbol table - pTables.Add((DT_SYMTAB.d_un, (end - DT_SYMTAB.d_un) / 16 /* sizeof(elf_32_sym) */, DT_STRTAB.d_un)); - } + // Dynamic symbol table + pTables.Add((DT_SYMTAB.d_un, (end - DT_SYMTAB.d_un) / 16 /* sizeof(elf_32_sym) */, DT_STRTAB.d_un)); } } @@ -108,40 +113,13 @@ namespace Il2CppInspector } public override uint[] GetFunctionTable() { - // Find dynamic section - var dynamic = new elf_32_shdr(); - var PT_DYNAMIC = program_table_element.First(x => x.p_type == 2u); - dynamic.sh_offset = PT_DYNAMIC.p_offset; - dynamic.sh_size = PT_DYNAMIC.p_filesz; + // INIT_ARRAY contains a list of pointers to initialization functions (not all functions in the binary) + // INIT_ARRAYSZ contains the size of INIT_ARRAY - // We need GOT, INIT_ARRAY and INIT_ARRAYSZ - uint _GLOBAL_OFFSET_TABLE_ = 0; - var init_array = new elf_32_shdr(); - Position = dynamic.sh_offset; - var dynamicend = dynamic.sh_offset + dynamic.sh_size; - while (Position < dynamicend) { - var tag = ReadInt32(); - if (tag == 3) //DT_PLTGOT - { - _GLOBAL_OFFSET_TABLE_ = ReadUInt32(); - continue; - } - else if (tag == 25) //DT_INIT_ARRAY - { - init_array.sh_offset = MapVATR(ReadUInt32()); - continue; - } - else if (tag == 27) //DT_INIT_ARRAYSZ - { - init_array.sh_size = ReadUInt32(); - continue; - } - Position += 4; - } - if (_GLOBAL_OFFSET_TABLE_ == 0) - throw new InvalidOperationException("Unable to get GLOBAL_OFFSET_TABLE from PT_DYNAMIC"); - GlobalOffset = _GLOBAL_OFFSET_TABLE_; - return ReadArray(init_array.sh_offset, (int) init_array.sh_size / 4); + var init = MapVATR(dynamic_table.First(x => x.d_tag == 25).d_un); // DT_INIT_ARRAY + var size = dynamic_table.First(x => x.d_tag == 27).d_un; // DT_INIT_ARRAYSZ + + return ReadArray(init, (int) size / 4); } // Map a virtual address to an offset into the image file. Throws an exception if the virtual address is not mapped into the file. @@ -149,7 +127,7 @@ namespace Il2CppInspector // an exception will be thrown. This area of memory is assumed to contain all zeroes. public override uint MapVATR(uint uiAddr) { - var program_header_table = program_table_element.First(x => uiAddr >= x.p_vaddr && uiAddr <= (x.p_vaddr + x.p_filesz)); + var program_header_table = this.program_header_table.First(x => uiAddr >= x.p_vaddr && uiAddr <= (x.p_vaddr + x.p_filesz)); return uiAddr - (program_header_table.p_vaddr - program_header_table.p_offset); } }