diff --git a/Il2CppInspector.Common/FileFormatReaders/ElfReader.cs b/Il2CppInspector.Common/FileFormatReaders/ElfReader.cs index c4c1597..2809a5b 100644 --- a/Il2CppInspector.Common/FileFormatReaders/ElfReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/ElfReader.cs @@ -1,6 +1,6 @@ /* Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper - Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty All rights reserved. */ @@ -110,6 +110,7 @@ namespace Il2CppInspector private elf_dynamic[] dynamic_table; private elf_header elf_header; private Dictionary> sectionByName = new Dictionary>(); + private List<(uint Start, uint End)> reverseMapExclusions = new List<(uint Start, uint End)>(); public ElfReader(Stream stream) : base(stream) { } @@ -177,28 +178,38 @@ namespace Il2CppInspector StatusUpdate("Processing relocations"); // Two types: add value from offset in image, and add value from specified addend - foreach (var relSection in getSections(Elf.SHT_REL)) + foreach (var relSection in getSections(Elf.SHT_REL)) { + reverseMapExclusions.Add(((uint) conv.Int(relSection.sh_offset), (uint) (conv.Int(relSection.sh_offset) + conv.Int(relSection.sh_size) - 1))); rels.UnionWith( from rel in ReadArray>(conv.Long(relSection.sh_offset), conv.Int(conv.Div(relSection.sh_size, relSection.sh_entsize))) select new ElfReloc(rel, section_header_table[relSection.sh_link].sh_offset)); - - foreach (var relaSection in getSections(Elf.SHT_RELA)) + } + + foreach (var relaSection in getSections(Elf.SHT_RELA)) { + reverseMapExclusions.Add(((uint) conv.Int(relaSection.sh_offset), (uint) (conv.Int(relaSection.sh_offset) + conv.Int(relaSection.sh_size) - 1))); rels.UnionWith( from rela in ReadArray>(conv.Long(relaSection.sh_offset), conv.Int(conv.Div(relaSection.sh_size, relaSection.sh_entsize))) select new ElfReloc(rela, section_header_table[relaSection.sh_link].sh_offset)); + } // Relocations in dynamic section if (getDynamic(Elf.DT_REL) is elf_dynamic dt_rel) { - var dt_rel_count = conv.Div(getDynamic(Elf.DT_RELSZ).d_un, getDynamic(Elf.DT_RELENT).d_un); - var dt_rel_list = ReadArray>(MapVATR(conv.ULong(dt_rel.d_un)), conv.Int(dt_rel_count)); + var dt_rel_count = conv.Int(conv.Div(getDynamic(Elf.DT_RELSZ).d_un, getDynamic(Elf.DT_RELENT).d_un)); + var dt_item_size = Sizeof(typeof(elf_rel)); + var dt_start = MapVATR(conv.ULong(dt_rel.d_un)); + var dt_rel_list = ReadArray>(dt_start, dt_rel_count); var dt_symtab = getDynamic(Elf.DT_SYMTAB).d_un; + reverseMapExclusions.Add((dt_start, (uint) (dt_start + dt_rel_count * dt_item_size - 1))); rels.UnionWith(from rel in dt_rel_list select new ElfReloc(rel, dt_symtab)); } if (getDynamic(Elf.DT_RELA) is elf_dynamic dt_rela) { - var dt_rela_count = conv.Div(getDynamic(Elf.DT_RELASZ).d_un, getDynamic(Elf.DT_RELAENT).d_un); - var dt_rela_list = ReadArray>(MapVATR(conv.ULong(dt_rela.d_un)), conv.Int(dt_rela_count)); + var dt_rela_count = conv.Int(conv.Div(getDynamic(Elf.DT_RELASZ).d_un, getDynamic(Elf.DT_RELAENT).d_un)); + var dt_item_size = Sizeof(typeof(elf_rela)); + var dt_start = MapVATR(conv.ULong(dt_rela.d_un)); + var dt_rela_list = ReadArray>(dt_start, dt_rela_count); var dt_symtab = getDynamic(Elf.DT_SYMTAB).d_un; + reverseMapExclusions.Add((dt_start, (uint) (dt_start + dt_rela_count * dt_item_size - 1))); rels.UnionWith(from rela in dt_rela_list select new ElfReloc(rela, dt_symtab)); } @@ -391,6 +402,15 @@ namespace Il2CppInspector var program_header_table = this.program_header_table.First(x => uiAddr >= conv.ULong(x.p_vaddr) && uiAddr <= conv.ULong(conv.Add(x.p_vaddr, x.p_filesz))); return (uint) (uiAddr - conv.ULong(conv.Sub(program_header_table.p_vaddr, program_header_table.p_offset))); } + + public override ulong MapFileOffsetToVA(uint offset) { + // Exclude relocation areas + if (reverseMapExclusions.Any(r => offset >= r.Start && offset <= r.End)) + throw new InvalidOperationException("Attempt to map to a relocation address"); + + var section = program_header_table.First(x => offset >= conv.Int(x.p_offset) && offset < conv.Int(x.p_offset) + conv.Int(x.p_filesz)); + return conv.ULong(section.p_vaddr) + offset - conv.ULong(section.p_offset); + } // Get the address of the procedure linkage table (.got.plt) which is needed for some disassemblies public uint GetPLTAddress() => (uint) conv.ULong(getDynamic(Elf.DT_PLTGOT).d_un); diff --git a/Il2CppInspector.Common/FileFormatReaders/FileFormatReader.cs b/Il2CppInspector.Common/FileFormatReaders/FileFormatReader.cs index 3eda596..399acf6 100644 --- a/Il2CppInspector.Common/FileFormatReaders/FileFormatReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/FileFormatReader.cs @@ -35,6 +35,8 @@ namespace Il2CppInspector long[] ReadMappedWordArray(ulong uiAddr, int count); uint MapVATR(ulong uiAddr); bool TryMapVATR(ulong uiAddr, out uint fileOffset); + ulong MapFileOffsetToVA(uint offset); + bool TryMapFileOffsetToVA(uint offset, out ulong va); byte[] ReadBytes(int count); ulong ReadUInt64(); @@ -159,6 +161,22 @@ namespace Il2CppInspector } } + // Map an offset into the file image to an RVA + // No mapping by default + public virtual ulong MapFileOffsetToVA(uint offset) => offset; + + // Try to map an offset into the file image to an RVA + public bool TryMapFileOffsetToVA(uint offset, out ulong va) { + try { + va = MapFileOffsetToVA(offset); + return true; + } + catch (InvalidOperationException) { + va = 0; + return false; + } + } + // Read a file format dependent word (32 or 64 bits) // The primitive mappings in Bin2Object will automatically read a uint if the file is 32-bit public long ReadWord() => ReadObject(); diff --git a/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/Elf.cs b/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/Elf.cs index 22b53c5..0ee44a1 100644 --- a/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/Elf.cs +++ b/Il2CppInspector.Common/FileFormatReaders/FormatLayouts/Elf.cs @@ -1,6 +1,6 @@ /* Copyright 2017 Perfare - https://github.com/Perfare/Il2CppDumper - Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty All rights reserved. */ @@ -30,6 +30,7 @@ namespace Il2CppInspector ET_EXEC = 2, // PHTs + PT_LOAD = 1, PT_DYNAMIC = 2, DT_PLTGOT = 3, diff --git a/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs b/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs index 3bb52c0..6507b4c 100644 --- a/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/MachOReader.cs @@ -27,6 +27,11 @@ namespace Il2CppInspector var section = sections.First(x => uiAddr >= x.Address && uiAddr <= x.Address + x.Size); return (uint) uiAddr - (section.Address - section.ImageOffset); } + + public override ulong MapFileOffsetToVA(uint offset) { + var section = sections.First(x => offset >= x.ImageOffset && offset < x.ImageOffset + x.Size); + return section.Address + offset - section.ImageOffset; + } } internal class MachOReader64 : MachOReader @@ -44,6 +49,11 @@ namespace Il2CppInspector var section = sections.First(x => uiAddr >= x.Address && uiAddr <= x.Address + x.Size); return (uint) (uiAddr - (section.Address - section.ImageOffset)); } + + public override ulong MapFileOffsetToVA(uint offset) { + var section = sections.First(x => offset >= x.ImageOffset && offset < x.ImageOffset + x.Size); + return section.Address + offset - section.ImageOffset; + } } // We need this convoluted generic TReader declaration so that "static T FileFormatReader.Load(Stream)" diff --git a/Il2CppInspector.Common/FileFormatReaders/PEReader.cs b/Il2CppInspector.Common/FileFormatReaders/PEReader.cs index 257b95f..10c7349 100644 --- a/Il2CppInspector.Common/FileFormatReaders/PEReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/PEReader.cs @@ -1,5 +1,5 @@ /* - Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty All rights reserved. */ @@ -150,5 +150,11 @@ namespace Il2CppInspector uiAddr - pe.ImageBase < x.VirtualAddress + x.SizeOfRawData); return (uint) (uiAddr - section.VirtualAddress - pe.ImageBase + section.PointerToRawData); } + + public override ulong MapFileOffsetToVA(uint offset) { + var section = sections.First(x => offset >= x.PointerToRawData && offset < x.PointerToRawData + x.SizeOfRawData); + + return pe.ImageBase + section.VirtualAddress + offset - section.PointerToRawData; + } } } diff --git a/Il2CppInspector.Common/FileFormatReaders/SElfReader.cs b/Il2CppInspector.Common/FileFormatReaders/SElfReader.cs index 0c0fd4f..63442f6 100644 --- a/Il2CppInspector.Common/FileFormatReaders/SElfReader.cs +++ b/Il2CppInspector.Common/FileFormatReaders/SElfReader.cs @@ -1,5 +1,5 @@ /* - Copyright 2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty All rights reserved. */ @@ -119,5 +119,10 @@ namespace Il2CppInspector var program_header_table = pht.First(x => uiAddr >= x.p_vaddr && uiAddr <= x.p_vaddr + x.p_filesz); return (uint) (uiAddr - (program_header_table.p_vaddr - program_header_table.p_offset)); } + + public override ulong MapFileOffsetToVA(uint offset) { + var segment = pht.First(x => offset >= x.p_offset && offset < x.p_offset + x.p_filesz); + return segment.p_vaddr + offset - segment.p_offset; + } } } \ No newline at end of file