ELF: More stringent SHT validity testing for PHT fallback
This commit is contained in:
@@ -112,6 +112,8 @@ namespace Il2CppInspector
|
|||||||
private elf_header<TWord> elf_header;
|
private elf_header<TWord> elf_header;
|
||||||
private Dictionary<string, elf_shdr<TWord>> sectionByName = new Dictionary<string, elf_shdr<TWord>>();
|
private Dictionary<string, elf_shdr<TWord>> sectionByName = new Dictionary<string, elf_shdr<TWord>>();
|
||||||
private List<(uint Start, uint End)> reverseMapExclusions = new List<(uint Start, uint End)>();
|
private List<(uint Start, uint End)> reverseMapExclusions = new List<(uint Start, uint End)>();
|
||||||
|
private bool preferPHT = false;
|
||||||
|
private bool isDumpedImage = false;
|
||||||
|
|
||||||
public ElfReader(Stream stream) : base(stream) { }
|
public ElfReader(Stream stream) : base(stream) { }
|
||||||
|
|
||||||
@@ -156,6 +158,45 @@ namespace Il2CppInspector
|
|||||||
program_header_table = ReadArray<TPHdr>(conv.Long(elf_header.e_phoff), elf_header.e_phnum);
|
program_header_table = ReadArray<TPHdr>(conv.Long(elf_header.e_phoff), elf_header.e_phnum);
|
||||||
section_header_table = ReadArray<elf_shdr<TWord>>(conv.Long(elf_header.e_shoff), elf_header.e_shnum);
|
section_header_table = ReadArray<elf_shdr<TWord>>(conv.Long(elf_header.e_shoff), elf_header.e_shnum);
|
||||||
|
|
||||||
|
// Determine if SHT is valid
|
||||||
|
|
||||||
|
// These can happen as a result of conversions from other formats to ELF,
|
||||||
|
// or if the SHT has been deliberately stripped
|
||||||
|
if (!section_header_table.Any()) {
|
||||||
|
Console.WriteLine("ELF binary has no SHT - reverting to PHT");
|
||||||
|
preferPHT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (section_header_table.All(s => conv.ULong(s.sh_addr) == 0ul)) {
|
||||||
|
Console.WriteLine("ELF binary SHT is all-zero - reverting to PHT");
|
||||||
|
preferPHT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for overlaps in sections that are memory-allocated on load
|
||||||
|
else {
|
||||||
|
var shtShouldBeOrdered = section_header_table
|
||||||
|
.Where(s => ((Elf) conv.Int(s.sh_flags) & Elf.SHF_ALLOC) == Elf.SHF_ALLOC)
|
||||||
|
.OrderBy(s => s.sh_addr)
|
||||||
|
.Select(s => new[] { conv.ULong(s.sh_addr), conv.ULong(s.sh_addr) + conv.ULong(s.sh_size) })
|
||||||
|
.SelectMany(s => s);
|
||||||
|
|
||||||
|
// No sections that map into memory - this is probably a dumped image
|
||||||
|
if (!shtShouldBeOrdered.Any()) {
|
||||||
|
Console.WriteLine("ELF binary appears to be a dumped memory image");
|
||||||
|
isDumpedImage = true;
|
||||||
|
preferPHT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sections overlap - this can happen if the ELF has been improperly generated or processed by another tool
|
||||||
|
else {
|
||||||
|
var shtOverlap = shtShouldBeOrdered.Aggregate((x, y) => x <= y? y : ulong.MaxValue) == ulong.MaxValue;
|
||||||
|
if (shtOverlap) {
|
||||||
|
Console.WriteLine("ELF binary SHT contains invalid ranges - reverting to PHT");
|
||||||
|
preferPHT = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get section name mappings if there are any
|
// Get section name mappings if there are any
|
||||||
// This is currently only used to defeat the XOR obfuscation handled below
|
// This is currently only used to defeat the XOR obfuscation handled below
|
||||||
// Note: There can be more than one section with the same name, or unnamed; we take the first section with a given name
|
// Note: There can be more than one section with the same name, or unnamed; we take the first section with a given name
|
||||||
@@ -577,7 +618,7 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
public override IEnumerable<Section> GetSections() {
|
public override IEnumerable<Section> GetSections() {
|
||||||
// If the sections have been stripped, use the segment list from the PHT instead
|
// If the sections have been stripped, use the segment list from the PHT instead
|
||||||
if (section_header_table.All(s => conv.Int(s.sh_offset) == 0)) {
|
if (preferPHT)
|
||||||
return program_header_table.Select(p => new Section {
|
return program_header_table.Select(p => new Section {
|
||||||
VirtualStart = conv.ULong(p.p_vaddr),
|
VirtualStart = conv.ULong(p.p_vaddr),
|
||||||
VirtualEnd = conv.ULong(p.p_vaddr) + conv.ULong(p.p_memsz) - 1,
|
VirtualEnd = conv.ULong(p.p_vaddr) + conv.ULong(p.p_memsz) - 1,
|
||||||
@@ -591,7 +632,6 @@ namespace Il2CppInspector
|
|||||||
|
|
||||||
Name = string.Empty
|
Name = string.Empty
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Return sections list
|
// Return sections list
|
||||||
return section_header_table.Select(s => new Section {
|
return section_header_table.Select(s => new Section {
|
||||||
|
|||||||
Reference in New Issue
Block a user