From 7b03b939a03561f9b10b98b75febe84a198575af Mon Sep 17 00:00:00 2001 From: LukeFZ <17146677+LukeFZ@users.noreply.github.com> Date: Sat, 9 Dec 2023 14:01:54 +0100 Subject: [PATCH] Fix some issues loading ELFs with invalid SHTs and broken symbol entries --- .../FileFormatStreams/ElfReader.cs | 49 +- .../FileFormatStreams/FormatLayouts/Elf.cs | 565 +++++++++--------- 2 files changed, 312 insertions(+), 302 deletions(-) diff --git a/Il2CppInspector.Common/FileFormatStreams/ElfReader.cs b/Il2CppInspector.Common/FileFormatStreams/ElfReader.cs index b43eefed..cab3c399 100644 --- a/Il2CppInspector.Common/FileFormatStreams/ElfReader.cs +++ b/Il2CppInspector.Common/FileFormatStreams/ElfReader.cs @@ -7,11 +7,8 @@ All rights reserved. using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; -using System.Text; -using NoisyCowStudios.Bin2Object; namespace Il2CppInspector { @@ -156,7 +153,17 @@ protected override bool Init() { // Get PHT and SHT PHT = ReadArray(conv.Long(ElfHeader.e_phoff), ElfHeader.e_phnum); - SHT = ReadArray>(conv.Long(ElfHeader.e_shoff), ElfHeader.e_shnum); + + try + { + SHT = ReadArray>(conv.Long(ElfHeader.e_shoff), ElfHeader.e_shnum); + } + catch (Exception ex) + { + Console.WriteLine($"Got exception {ex} while parsing SHT - reverting to PHT"); + preferPHT = true; + SHT = []; + } // Determine if SHT is valid @@ -385,7 +392,7 @@ private void processSymbols() { StatusUpdate("Processing symbols"); // Three possible symbol tables in ELF files - var pTables = new List<(TWord offset, TWord count, TWord strings)>(); + var pTables = new List<(TWord offset, TWord count, TWord strings, TWord stringsCount)>(); // String table (a sequence of null-terminated strings, total length in sh_size var SHT_STRTAB = GetSection(Elf.SHT_STRTAB); @@ -393,32 +400,34 @@ private void processSymbols() { if (SHT_STRTAB != null) { // Section header shared object symbol table (.symtab) if (GetSection(Elf.SHT_SYMTAB) is elf_shdr SHT_SYMTAB) - pTables.Add((SHT_SYMTAB.sh_offset, conv.Div(SHT_SYMTAB.sh_size, SHT_SYMTAB.sh_entsize), SHT_STRTAB.sh_offset)); + pTables.Add((SHT_SYMTAB.sh_offset, conv.Div(SHT_SYMTAB.sh_size, SHT_SYMTAB.sh_entsize), SHT_STRTAB.sh_offset, SHT_STRTAB.sh_size)); // Section header executable symbol table (.dynsym) if (GetSection(Elf.SHT_DYNSYM) is elf_shdr SHT_DYNSYM) - pTables.Add((SHT_DYNSYM.sh_offset, conv.Div(SHT_DYNSYM.sh_size, SHT_DYNSYM.sh_entsize), SHT_STRTAB.sh_offset)); + pTables.Add((SHT_DYNSYM.sh_offset, conv.Div(SHT_DYNSYM.sh_size, SHT_DYNSYM.sh_entsize), SHT_STRTAB.sh_offset, SHT_STRTAB.sh_size)); } - var maxStrtabAddr = conv.Add(SHT_STRTAB.sh_offset, SHT_STRTAB.sh_size); - // Symbol table in dynamic section (DT_SYMTAB) // Normally the same as .dynsym except that .dynsym may be removed in stripped binaries // Dynamic string table if (GetDynamicEntry(Elf.DT_STRTAB) is elf_dynamic DT_STRTAB) { if (GetDynamicEntry(Elf.DT_SYMTAB) is elf_dynamic DT_SYMTAB) { - // Find the next pointer in the dynamic table to calculate the length of the symbol table - var orderedTable = (from x in DynamicTable where conv.Gt(x.d_un, DT_SYMTAB.d_un) orderby x.d_un select x).ToList(); - if (orderedTable.Count != 0) + if (GetDynamicEntry(Elf.DT_STRSZ) is elf_dynamic DT_STRSZ) { - var end = orderedTable.First().d_un; - // Dynamic symbol table - pTables.Add(( - conv.FromUInt(MapVATR(conv.ULong(DT_SYMTAB.d_un))), - conv.Div(conv.Sub(end, DT_SYMTAB.d_un), Sizeof(typeof(TSym))), - DT_STRTAB.d_un - )); + // Find the next pointer in the dynamic table to calculate the length of the symbol table + var orderedTable = (from x in DynamicTable where conv.Gt(x.d_un, DT_SYMTAB.d_un) orderby x.d_un select x).ToList(); + if (orderedTable.Count != 0) + { + var end = orderedTable.First().d_un; + // Dynamic symbol table + pTables.Add(( + conv.FromUInt(MapVATR(conv.ULong(DT_SYMTAB.d_un))), + conv.Div(conv.Sub(end, DT_SYMTAB.d_un), Sizeof(typeof(TSym))), + DT_STRTAB.d_un, + DT_STRSZ.d_un + )); + } } } } @@ -432,7 +441,7 @@ private void processSymbols() { foreach (var symbol in symbol_table) { - if (conv.Gt(conv.FromUInt(symbol.st_name), maxStrtabAddr)) + if (conv.Gt(conv.FromUInt(symbol.st_name), pTab.stringsCount)) break; // Skip invalid symbol table indices, since we might read past it on obfuscated binaries string name = string.Empty; diff --git a/Il2CppInspector.Common/FileFormatStreams/FormatLayouts/Elf.cs b/Il2CppInspector.Common/FileFormatStreams/FormatLayouts/Elf.cs index 703d6e4c..63d71e51 100644 --- a/Il2CppInspector.Common/FileFormatStreams/FormatLayouts/Elf.cs +++ b/Il2CppInspector.Common/FileFormatStreams/FormatLayouts/Elf.cs @@ -1,282 +1,283 @@ -/* - Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper - Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty - - All rights reserved. -*/ - -using System; -using NoisyCowStudios.Bin2Object; - -namespace Il2CppInspector -{ - [Flags] - public enum Elf : uint - { - // elf_header.m_dwFormat - ELFMAG = 0x464c457f, // "\177ELF" - - // elf_header.e_machine - EM_386 = 0x03, - EM_ARM = 0x28, - EM_X86_64 = 0x3E, - EM_AARCH64 = 0xB7, - - // elf_header.m_arch - ELFCLASS32 = 1, - ELFCLASS64 = 2, - - // elf_header.e_Type - ET_EXEC = 2, - - // PHTs - PT_LOAD = 1, - PT_DYNAMIC = 2, - - PF_X = 1, - PF_W = 2, - PF_R = 4, - - // SHTs - SHT_PROGBITS = 1, - SHT_SYMTAB = 2, - SHT_STRTAB = 3, - SHT_RELA = 4, - SHT_NOBITS = 8, - SHT_REL = 9, - SHT_DYNSYM = 11, - - // SHNs - SHN_UNDEF = 0, - - // STTs - STT_NOTYPE = 0, - STT_OBJECT = 1, - STT_FUNC = 2, - STT_SECTION = 3, - STT_FILE = 4, - STT_COMMON = 5, - STT_LOOS = 10, - STT_HIOS = 12, - STT_LOPROC = 13, - STT_SPARC_REGISTER = 13, - STT_HIPROC = 15, - - // SHFs - SHF_ALLOC = 2, - SHF_EXECINSTR = 4, - - // dynamic sections - DT_PLTGOT = 3, - DT_HASH = 4, - DT_STRTAB = 5, - DT_SYMTAB = 6, - DT_RELA = 7, - DT_RELASZ = 8, - DT_RELAENT = 9, - DT_INIT = 12, - DT_FINI = 13, - DT_REL = 17, - DT_RELSZ = 18, - DT_RELENT = 19, - DT_JMPREL = 23, - DT_INIT_ARRAY = 25, - DT_FINI_ARRAY = 26, - DT_INIT_ARRAYSZ = 27, - DT_PREINIT_ARRAY = 32, - DT_MOVETAB = 0x6ffffefe, - DT_VERDEF = 0x6ffffffc, - DT_VERNEED = 0x6ffffffe, - DT_SYMINFO = 0x6ffffeff, - - // relocation types - R_ARM_ABS32 = 2, - R_ARM_REL32 = 3, - R_ARM_COPY = 20, - - R_AARCH64_ABS64 = 0x101, - R_AARCH64_PREL64 = 0x104, - R_AARCH64_GLOB_DAT = 0x401, - R_AARCH64_JUMP_SLOT = 0x402, - R_AARCH64_RELATIVE = 0x403, - - R_386_32 = 1, - R_386_PC32 = 2, - R_386_GLOB_DAT = 6, - R_386_JMP_SLOT = 7, - - R_AMD64_64 = 1 - } - -#pragma warning disable CS0649 - public class elf_header where TWord : struct - { - // 0x7f followed by ELF in ascii - public uint m_dwFormat; - - // 1 - 32 bit - // 2 - 64 bit - public byte m_arch; - - // 1 - little endian - // 2 - big endian - public byte m_endian; - - // 1 is original elf format - public byte m_version; - - // set based on OS, refer to OSABI enum - public byte m_osabi; - - // refer to elf documentation - public byte m_osabi_ver; - - // unused - [ArrayLength(FixedSize=7)] - public byte[] e_pad;//byte[7] - - // 1 - relocatable - // 2 - executable - // 3 - shared - // 4 - core - public ushort e_type; - - // refer to isa enum - public ushort e_machine; - - public uint e_version; - - public TWord e_entry; - public TWord e_phoff; - public TWord e_shoff; - public uint e_flags; - public ushort e_ehsize; - public ushort e_phentsize; - public ushort e_phnum; - public ushort e_shentsize; - public ushort e_shnum; - public ushort e_shtrndx; - } - - public interface Ielf_phdr where TWord : struct - { - uint p_type { get; } - TWord p_offset { get; set; } - TWord p_filesz { get; set; } - TWord p_memsz { get; } - TWord p_vaddr { get; set; } - uint p_flags { get; } - } - - public class elf_32_phdr : Ielf_phdr { - public uint p_type => f_p_type; - public uint p_offset { get => f_p_offset; set => f_p_offset = value; } - public uint p_filesz { get => f_p_filesz; set => f_p_filesz = value; } - public uint p_vaddr { get => f_p_vaddr; set => f_p_vaddr = value; } - public uint p_flags => f_p_flags; - public uint p_memsz => f_p_memsz; - - public uint f_p_type; - public uint f_p_offset; - public uint f_p_vaddr; - public uint p_paddr; - public uint f_p_filesz; - public uint f_p_memsz; - public uint f_p_flags; - public uint p_align; - } - - public class elf_64_phdr : Ielf_phdr - { - public uint p_type => f_p_type; - public ulong p_offset { get => f_p_offset; set => f_p_offset = value; } - public ulong p_filesz { get => f_p_filesz; set => f_p_filesz = value; } - public ulong p_memsz => f_p_memsz; - public ulong p_vaddr { get => f_p_vaddr; set => f_p_vaddr = value; } - public uint p_flags => f_p_flags; - - public uint f_p_type; - public uint f_p_flags; - public ulong f_p_offset; - public ulong f_p_vaddr; - public ulong p_paddr; - public ulong f_p_filesz; - public ulong f_p_memsz; - public ulong p_align; - } - - public class elf_shdr where TWord : struct - { - public uint sh_name; - public uint sh_type; - public TWord sh_flags; - public TWord sh_addr; - public TWord sh_offset; - public TWord sh_size; - public uint sh_link; - public uint sh_info; - public TWord sh_addralign; - public TWord sh_entsize; - } - - public interface Ielf_sym where TWord : struct - { - uint st_name { get; } - TWord st_value { get; } - ushort st_shndx { get; } - Elf st_info { get; } - Elf type { get; } - } - - public class elf_32_sym : Ielf_sym - { - public uint st_name => f_st_name; - public uint st_value => f_st_value; - public ushort st_shndx => f_st_shndx; - public Elf st_info => (Elf) f_st_info; - public Elf type => (Elf) (f_st_info & 0xf); - - public uint f_st_name; - public uint f_st_value; - public uint st_size; - public byte f_st_info; - public byte st_other; - public ushort f_st_shndx; - } - - public class elf_64_sym : Ielf_sym - { - public uint st_name => f_st_name; - public ulong st_value => f_st_value; - public ushort st_shndx => f_st_shndx; - public Elf st_info => (Elf) f_st_info; - public Elf type => (Elf) (f_st_info & 0xf); - - public uint f_st_name; - public byte f_st_info; - public byte st_other; - public ushort f_st_shndx; - public ulong f_st_value; - public ulong st_size; - } - - public class elf_dynamic where TWord : struct - { - public TWord d_tag; - public TWord d_un; - } - - public class elf_rel where TWord : struct - { - public TWord r_offset; - public TWord r_info; - } - - public class elf_rela where TWord : struct - { - public TWord r_offset; - public TWord r_info; - public TWord r_addend; - } -#pragma warning restore CS0649 -} +/* + Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper + Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty + + All rights reserved. +*/ + +using System; +using NoisyCowStudios.Bin2Object; + +namespace Il2CppInspector +{ + [Flags] + public enum Elf : uint + { + // elf_header.m_dwFormat + ELFMAG = 0x464c457f, // "\177ELF" + + // elf_header.e_machine + EM_386 = 0x03, + EM_ARM = 0x28, + EM_X86_64 = 0x3E, + EM_AARCH64 = 0xB7, + + // elf_header.m_arch + ELFCLASS32 = 1, + ELFCLASS64 = 2, + + // elf_header.e_Type + ET_EXEC = 2, + + // PHTs + PT_LOAD = 1, + PT_DYNAMIC = 2, + + PF_X = 1, + PF_W = 2, + PF_R = 4, + + // SHTs + SHT_PROGBITS = 1, + SHT_SYMTAB = 2, + SHT_STRTAB = 3, + SHT_RELA = 4, + SHT_NOBITS = 8, + SHT_REL = 9, + SHT_DYNSYM = 11, + + // SHNs + SHN_UNDEF = 0, + + // STTs + STT_NOTYPE = 0, + STT_OBJECT = 1, + STT_FUNC = 2, + STT_SECTION = 3, + STT_FILE = 4, + STT_COMMON = 5, + STT_LOOS = 10, + STT_HIOS = 12, + STT_LOPROC = 13, + STT_SPARC_REGISTER = 13, + STT_HIPROC = 15, + + // SHFs + SHF_ALLOC = 2, + SHF_EXECINSTR = 4, + + // dynamic sections + DT_PLTGOT = 3, + DT_HASH = 4, + DT_STRTAB = 5, + DT_SYMTAB = 6, + DT_RELA = 7, + DT_RELASZ = 8, + DT_RELAENT = 9, + DT_STRSZ = 10, + DT_INIT = 12, + DT_FINI = 13, + DT_REL = 17, + DT_RELSZ = 18, + DT_RELENT = 19, + DT_JMPREL = 23, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_PREINIT_ARRAY = 32, + DT_MOVETAB = 0x6ffffefe, + DT_VERDEF = 0x6ffffffc, + DT_VERNEED = 0x6ffffffe, + DT_SYMINFO = 0x6ffffeff, + + // relocation types + R_ARM_ABS32 = 2, + R_ARM_REL32 = 3, + R_ARM_COPY = 20, + + R_AARCH64_ABS64 = 0x101, + R_AARCH64_PREL64 = 0x104, + R_AARCH64_GLOB_DAT = 0x401, + R_AARCH64_JUMP_SLOT = 0x402, + R_AARCH64_RELATIVE = 0x403, + + R_386_32 = 1, + R_386_PC32 = 2, + R_386_GLOB_DAT = 6, + R_386_JMP_SLOT = 7, + + R_AMD64_64 = 1 + } + +#pragma warning disable CS0649 + public class elf_header where TWord : struct + { + // 0x7f followed by ELF in ascii + public uint m_dwFormat; + + // 1 - 32 bit + // 2 - 64 bit + public byte m_arch; + + // 1 - little endian + // 2 - big endian + public byte m_endian; + + // 1 is original elf format + public byte m_version; + + // set based on OS, refer to OSABI enum + public byte m_osabi; + + // refer to elf documentation + public byte m_osabi_ver; + + // unused + [ArrayLength(FixedSize=7)] + public byte[] e_pad;//byte[7] + + // 1 - relocatable + // 2 - executable + // 3 - shared + // 4 - core + public ushort e_type; + + // refer to isa enum + public ushort e_machine; + + public uint e_version; + + public TWord e_entry; + public TWord e_phoff; + public TWord e_shoff; + public uint e_flags; + public ushort e_ehsize; + public ushort e_phentsize; + public ushort e_phnum; + public ushort e_shentsize; + public ushort e_shnum; + public ushort e_shtrndx; + } + + public interface Ielf_phdr where TWord : struct + { + uint p_type { get; } + TWord p_offset { get; set; } + TWord p_filesz { get; set; } + TWord p_memsz { get; } + TWord p_vaddr { get; set; } + uint p_flags { get; } + } + + public class elf_32_phdr : Ielf_phdr { + public uint p_type => f_p_type; + public uint p_offset { get => f_p_offset; set => f_p_offset = value; } + public uint p_filesz { get => f_p_filesz; set => f_p_filesz = value; } + public uint p_vaddr { get => f_p_vaddr; set => f_p_vaddr = value; } + public uint p_flags => f_p_flags; + public uint p_memsz => f_p_memsz; + + public uint f_p_type; + public uint f_p_offset; + public uint f_p_vaddr; + public uint p_paddr; + public uint f_p_filesz; + public uint f_p_memsz; + public uint f_p_flags; + public uint p_align; + } + + public class elf_64_phdr : Ielf_phdr + { + public uint p_type => f_p_type; + public ulong p_offset { get => f_p_offset; set => f_p_offset = value; } + public ulong p_filesz { get => f_p_filesz; set => f_p_filesz = value; } + public ulong p_memsz => f_p_memsz; + public ulong p_vaddr { get => f_p_vaddr; set => f_p_vaddr = value; } + public uint p_flags => f_p_flags; + + public uint f_p_type; + public uint f_p_flags; + public ulong f_p_offset; + public ulong f_p_vaddr; + public ulong p_paddr; + public ulong f_p_filesz; + public ulong f_p_memsz; + public ulong p_align; + } + + public class elf_shdr where TWord : struct + { + public uint sh_name; + public uint sh_type; + public TWord sh_flags; + public TWord sh_addr; + public TWord sh_offset; + public TWord sh_size; + public uint sh_link; + public uint sh_info; + public TWord sh_addralign; + public TWord sh_entsize; + } + + public interface Ielf_sym where TWord : struct + { + uint st_name { get; } + TWord st_value { get; } + ushort st_shndx { get; } + Elf st_info { get; } + Elf type { get; } + } + + public class elf_32_sym : Ielf_sym + { + public uint st_name => f_st_name; + public uint st_value => f_st_value; + public ushort st_shndx => f_st_shndx; + public Elf st_info => (Elf) f_st_info; + public Elf type => (Elf) (f_st_info & 0xf); + + public uint f_st_name; + public uint f_st_value; + public uint st_size; + public byte f_st_info; + public byte st_other; + public ushort f_st_shndx; + } + + public class elf_64_sym : Ielf_sym + { + public uint st_name => f_st_name; + public ulong st_value => f_st_value; + public ushort st_shndx => f_st_shndx; + public Elf st_info => (Elf) f_st_info; + public Elf type => (Elf) (f_st_info & 0xf); + + public uint f_st_name; + public byte f_st_info; + public byte st_other; + public ushort f_st_shndx; + public ulong f_st_value; + public ulong st_size; + } + + public class elf_dynamic where TWord : struct + { + public TWord d_tag; + public TWord d_un; + } + + public class elf_rel where TWord : struct + { + public TWord r_offset; + public TWord r_info; + } + + public class elf_rela where TWord : struct + { + public TWord r_offset; + public TWord r_info; + public TWord r_addend; + } +#pragma warning restore CS0649 +}