添加Elf64 Plus模式支持

This commit is contained in:
Perfare 2018-06-21 07:20:55 +08:00
parent 1de56f63fc
commit 3919c7045f
9 changed files with 400 additions and 65 deletions

View file

@ -27,17 +27,17 @@ namespace Il2CppDumper
else
Search = Searchv21;
elf_header = new Elf32_Ehdr();
elf_header.m_dwFormat = ReadUInt32();
elf_header.m_arch = ReadByte();
if (elf_header.m_arch == 2)//64
elf_header.ei_mag = ReadUInt32();
elf_header.ei_class = ReadByte();
if (elf_header.ei_class == 2)//64
{
throw new Exception("ERROR: 64 bit not supported.");
}
elf_header.m_endian = ReadByte();
elf_header.m_version = ReadByte();
elf_header.m_osabi = ReadByte();
elf_header.m_osabi_ver = ReadByte();
elf_header.e_pad = ReadBytes(7);
elf_header.ei_data = ReadByte();
elf_header.ei_version = ReadByte();
elf_header.ei_osabi = ReadByte();
elf_header.ei_abiversion = ReadByte();
elf_header.ei_pad = ReadBytes(7);
elf_header.e_type = ReadUInt16();
elf_header.e_machine = ReadUInt16();
if (elf_header.e_machine != 0x28 && elf_header.e_machine != 0x3)
@ -342,7 +342,7 @@ namespace Il2CppDumper
var position = Position;
var dynamic_symbol = dynamic_symbol_table[index];
writer.BaseStream.Position = offset;
writer.Write(dynamic_symbol.sym_value);
writer.Write(dynamic_symbol.st_value);
Position = position;
break;
}
@ -351,14 +351,14 @@ namespace Il2CppDumper
{
var position = Position;
var dynamic_symbol = dynamic_symbol_table[index];
var name = ReadStringToNull(symbol_name_block_off + dynamic_symbol.sym_name);
var name = ReadStringToNull(symbol_name_block_off + dynamic_symbol.st_name);
switch (name)
{
case "g_CodeRegistration":
codeRegistration = dynamic_symbol.sym_value;
codeRegistration = dynamic_symbol.st_value;
break;
case "g_MetadataRegistration":
metadataRegistration = dynamic_symbol.sym_value;
metadataRegistration = dynamic_symbol.st_value;
break;
}
Position = position;
@ -443,7 +443,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}
@ -488,7 +488,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}

282
Il2CppDumper/Elf64.cs Normal file
View file

@ -0,0 +1,282 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Il2CppDumper
{
public sealed class Elf64 : Il2Cpp
{
private Elf64_Ehdr elf_header;
private Elf64_Phdr[] program_table_element;
private Dictionary<string, Elf64_Shdr> sectionWithName = new Dictionary<string, Elf64_Shdr>();
private ulong codeRegistration;
private ulong metadataRegistration;
public Elf64(Stream stream, int version, long maxmetadataUsages) : base(stream)
{
this.version = version;
this.maxmetadataUsages = maxmetadataUsages;
Search = SearchObsolete;
elf_header = new Elf64_Ehdr();
elf_header.ei_mag = ReadUInt32();
elf_header.ei_class = ReadByte();
elf_header.ei_data = ReadByte();
elf_header.ei_version = ReadByte();
elf_header.ei_osabi = ReadByte();
elf_header.ei_abiversion = ReadByte();
elf_header.ei_pad = ReadBytes(7);
elf_header.e_type = ReadUInt16();
elf_header.e_machine = ReadUInt16();
elf_header.e_version = ReadUInt32();
elf_header.e_entry = ReadUInt64();
elf_header.e_phoff = ReadUInt64();
elf_header.e_shoff = ReadUInt64();
elf_header.e_flags = ReadUInt32();
elf_header.e_ehsize = ReadUInt16();
elf_header.e_phentsize = ReadUInt16();
elf_header.e_phnum = ReadUInt16();
elf_header.e_shentsize = ReadUInt16();
elf_header.e_shnum = ReadUInt16();
elf_header.e_shtrndx = ReadUInt16();
program_table_element = ReadClassArray<Elf64_Phdr>(elf_header.e_phoff, elf_header.e_phnum);
GetSectionWithName();
RelocationProcessing();
}
private void GetSectionWithName()
{
try
{
var section_name_off = elf_header.e_shoff + (ulong)elf_header.e_shentsize * elf_header.e_shtrndx;
Position = section_name_off + 2 * 4 + 8 + 8;//2 * sizeof(Elf64_Word) + sizeof(Elf64_Xword) + sizeof(Elf64_Addr)
var section_name_block_off = ReadUInt32();
for (int i = 0; i < elf_header.e_shnum; i++)
{
var section = ReadClass<Elf64_Shdr>(elf_header.e_shoff + elf_header.e_shentsize * (ulong)i);
sectionWithName.Add(ReadStringToNull(section_name_block_off + section.sh_name), section);
}
}
catch
{
Console.WriteLine("ERROR: Unable to get section.");
}
}
private void RelocationProcessing()
{
//TODO
/*if (sectionWithName.ContainsKey(".dynsym") && sectionWithName.ContainsKey(".dynstr") && sectionWithName.ContainsKey(".rela.dyn"))
{
Console.WriteLine("Applying relocations...");
var dynsym = sectionWithName[".dynsym"];
var symbol_name_block_off = sectionWithName[".dynstr"].sh_offset;
var rela_dyn = sectionWithName[".rela.dyn"];
var dynamic_symbol_table = ReadClassArray<Elf64_Sym>(dynsym.sh_offset, (long)dynsym.sh_size / 24);
var rel_dynend = rela_dyn.sh_offset + rela_dyn.sh_size;
Position = rela_dyn.sh_offset;
var writer = new BinaryWriter(BaseStream);
while ((ulong)Position < rel_dynend)
{
//Elf64_Rela
var r_offset = ReadUInt64();
//r_info
var type = ReadUInt32();
var index = ReadUInt32();
var r_addend = ReadUInt64();
switch (type)
{
case 257: //R_AARCH64_ABS64
//case 1027: //R_AARCH64_RELATIVE
{
var position = Position;
var dynamic_symbol = dynamic_symbol_table[index];
writer.BaseStream.Position = (long)r_offset;
writer.Write(dynamic_symbol.st_value);
Position = position;
break;
}
case 1025: //R_AARCH64_GLOB_DAT
{
var position = Position;
var dynamic_symbol = dynamic_symbol_table[index];
var name = ReadStringToNull(symbol_name_block_off + dynamic_symbol.st_name);
switch (name)
{
case "g_CodeRegistration":
codeRegistration = dynamic_symbol.st_value;
break;
case "g_MetadataRegistration":
metadataRegistration = dynamic_symbol.st_value;
break;
}
Position = position;
break;
}
}
}
}*/
}
public override dynamic MapVATR(dynamic uiAddr)
{
var program_header_table = program_table_element.First(x => uiAddr >= x.p_vaddr && uiAddr <= x.p_vaddr + x.p_memsz);
return uiAddr - (program_header_table.p_vaddr - program_header_table.p_offset);
}
public override long GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType, int fieldIndex)
{
if (isNew21)
{
var ptr = fieldOffsets[typeIndex];
if (ptr >= 0)
{
Position = MapVATR((ulong)ptr) + 4ul * (ulong)fieldIndexInType;
return ReadInt32();
}
return 0;
}
return fieldOffsets[fieldIndex];
}
public override ulong[] GetPointers(ulong pointer, long count)
{
var pointers = MapVATR<ulong>(pointer, count);
return pointers;
}
private bool SearchObsolete()
{
Console.WriteLine("ERROR: This mode not supported Elf64.");
return false;
}
public override bool AdvancedSearch(int methodCount)
{
Console.WriteLine("ERROR: This mode not supported Elf64.");
return false;
}
public override bool PlusSearch(int methodCount, int typeDefinitionsCount)
{
if (sectionWithName.ContainsKey(".data") && sectionWithName.ContainsKey(".text") && sectionWithName.ContainsKey(".bss"))
{
var datarelro = sectionWithName[".data"];
var text = sectionWithName[".text"];
var bss = sectionWithName[".bss"];
codeRegistration = FindCodeRegistration(methodCount, datarelro, null, text);
metadataRegistration = FindMetadataRegistration(typeDefinitionsCount, datarelro, null, bss);
if (codeRegistration != 0 && metadataRegistration != 0)
{
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init64(codeRegistration, metadataRegistration);
return true;
}
}
else
{
Console.WriteLine("ERROR: The necessary section is missing.");
}
return false;
}
private ulong FindCodeRegistration(int count, Elf64_Shdr search, Elf64_Shdr search2, Elf64_Shdr range)
{
var searchend = search.sh_offset + search.sh_size;
var rangeend = range.sh_addr + range.sh_size;
var search2end = search2 == null ? 0 : search2.sh_offset + search2.sh_size;
Position = search.sh_offset;
while ((ulong)Position < searchend)
{
var add = Position;
if (ReadUInt64() == (ulong)count)
{
try
{
ulong pointers = MapVATR(ReadUInt64());
if (pointers >= search.sh_offset && pointers <= searchend)
{
var np = Position;
var temp = ReadClassArray<ulong>(pointers, count);
var r = Array.FindIndex(temp, x => x < range.sh_addr || x > rangeend);
if (r == -1)
{
return (ulong)add - search.sh_offset + search.sh_addr;//MapRATV
}
Position = np;
}
else if (search2 != null && pointers >= search2.sh_offset && pointers <= search2end)
{
var np = Position;
var temp = ReadClassArray<ulong>(pointers, count);
var r = Array.FindIndex(temp, x => x < range.sh_addr || x > rangeend);
if (r == -1)
{
return (ulong)add - search.sh_offset + search.sh_addr;//MapRATV
}
Position = np;
}
}
catch
{
// ignored
}
}
}
return 0;
}
private ulong FindMetadataRegistration(int typeDefinitionsCount, Elf64_Shdr search, Elf64_Shdr search2, Elf64_Shdr range)
{
var searchend = search.sh_offset + search.sh_size;
var rangeend = range.sh_addr + range.sh_size;
var search2end = search2 == null ? 0 : search2.sh_offset + search2.sh_size;
Position = search.sh_offset;
while ((ulong)Position < searchend)
{
var add = Position;
if (ReadUInt64() == (ulong)typeDefinitionsCount)
{
try
{
var np = Position;
Position += 16;
ulong pointers = MapVATR(ReadUInt64());
if (pointers >= search.sh_offset && pointers <= searchend)
{
var temp = ReadClassArray<ulong>(pointers, maxmetadataUsages);
var r = Array.FindIndex(temp, x => x < range.sh_addr || x > rangeend);
if (r == -1)
{
return (ulong)add - 96ul - search.sh_offset + search.sh_addr;//MapRATV
}
}
else if (search2 != null && pointers >= search2.sh_offset && pointers <= search2end)
{
var temp = ReadClassArray<ulong>(pointers, maxmetadataUsages);
var r = Array.FindIndex(temp, x => x < range.sh_addr || x > rangeend);
if (r == -1)
{
return (ulong)add - 96ul - search.sh_offset + search.sh_addr;//MapRATV
}
}
Position = np;
}
catch
{
// ignored
}
}
}
return 0;
}
public bool DetectedSymbol()
{
Console.WriteLine("ERROR: This mode not supported Elf64.");
return false;
}
}
}

View file

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Il2CppDumper
{
public class Elf64_Ehdr
{
public uint ei_mag;
public byte ei_class;
public byte ei_data;
public byte ei_version;
public byte ei_osabi;
public byte ei_abiversion;
public byte[] ei_pad;
public ushort e_type;
public ushort e_machine;
public uint e_version;
public ulong e_entry;
public ulong e_phoff;
public ulong 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 class Elf64_Phdr
{
public uint p_type;
public uint p_flags;
public ulong p_offset;
public ulong p_vaddr;
public ulong p_paddr;
public ulong p_filesz;
public ulong p_memsz;
public ulong p_align;
}
public class Elf64_Shdr
{
public uint sh_name;
public uint sh_type;
public ulong sh_flags;
public ulong sh_addr;
public ulong sh_offset;
public ulong sh_size;
public uint sh_link;
public uint sh_info;
public ulong sh_addralign;
public ulong sh_entsize;
}
public class Elf64_Sym
{
public uint st_name;
public byte st_info;
public byte st_other;
public ushort st_shndx;
public ulong st_value;
public ulong st_size;
}
}

View file

@ -8,40 +8,16 @@ namespace Il2CppDumper
{
public class Elf32_Ehdr
{
// 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
public byte[] e_pad;//byte[7]
// 1 - relocatable
// 2 - executable
// 3 - shared
// 4 - core
public uint ei_mag;
public byte ei_class;
public byte ei_data;
public byte ei_version;
public byte ei_osabi;
public byte ei_abiversion;
public byte[] ei_pad;
public ushort e_type;
// refer to isa enum
public ushort e_machine;
public uint e_version;
public uint e_entry;
public uint e_phoff;
public uint e_shoff;
@ -82,11 +58,11 @@ namespace Il2CppDumper
public class Elf32_Sym
{
public uint sym_name;
public uint sym_value;
public uint sym_size;
public byte sym_info;
public byte sym_other;
public ushort sym_shndx;
public uint st_name;
public uint st_value;
public uint st_size;
public byte st_info;
public byte st_other;
public ushort st_shndx;
}
}

View file

@ -51,6 +51,8 @@
<Compile Include="Config.cs" />
<Compile Include="DummyAssemblyCreator.cs" />
<Compile Include="Elf.cs" />
<Compile Include="Elf64.cs" />
<Compile Include="Elf64Class.cs" />
<Compile Include="Il2CppClass.cs" />
<Compile Include="Il2Cpp.cs" />
<Compile Include="Macho.cs" />

View file

@ -347,7 +347,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}
@ -392,7 +392,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}

View file

@ -348,7 +348,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}
@ -393,7 +393,7 @@ namespace Il2CppDumper
}
catch
{
// ignored
}
}
}

View file

@ -19,14 +19,14 @@ namespace Il2CppDumper
private Il2CppFieldDefaultValue[] fieldDefaultValues;
private Il2CppParameterDefaultValue[] parameterDefaultValues;
public Il2CppPropertyDefinition[] propertyDefs;
public Il2CppCustomAttributeTypeRange[] attributesInfos;
public Il2CppCustomAttributeTypeRange[] attributeTypeRanges;
private Il2CppStringLiteral[] stringLiterals;
private Il2CppMetadataUsageList[] metadataUsageLists;
private Il2CppMetadataUsagePair[] metadataUsagePairs;
public int[] attributeTypes;
public int[] interfaceIndices;
public SortedDictionary<uint, string> stringLiteralsdic;
public long maxmetadataUsages;
public long maxMetadataUsages;
public int[] nestedTypeIndices;
public Il2CppEventDefinition[] eventDefs;
public Il2CppGenericContainer[] genericContainers;
@ -90,7 +90,7 @@ namespace Il2CppDumper
if (version > 20)
{
//CustomAttributeTypeRange
attributesInfos = ReadClassArray<Il2CppCustomAttributeTypeRange>(pMetadataHdr.attributesInfoOffset, pMetadataHdr.attributesInfoCount / MySizeOf(typeof(Il2CppCustomAttributeTypeRange)));
attributeTypeRanges = ReadClassArray<Il2CppCustomAttributeTypeRange>(pMetadataHdr.attributesInfoOffset, pMetadataHdr.attributesInfoCount / MySizeOf(typeof(Il2CppCustomAttributeTypeRange)));
//AttributeTypes
attributeTypes = ReadClassArray<int>(pMetadataHdr.attributeTypesOffset, pMetadataHdr.attributeTypesCount / 4);
}
@ -140,7 +140,7 @@ namespace Il2CppDumper
}
}
}
maxmetadataUsages = stringLiteralsdic.Last().Key + 1;
maxMetadataUsages = stringLiteralsdic.Last().Key + 1;
}

View file

@ -43,6 +43,10 @@ namespace Il2CppDumper
throw new Exception("ERROR: il2cpp file not supported.");
case 0x464c457f://ELF
isElf = true;
if (il2cppfile[4] == 2)
{
goto case 0xFEEDFACF;//ELF64
}
goto case 0xFEEDFACE;
case 0xCAFEBABE://FAT header
case 0xBEBAFECA:
@ -76,11 +80,14 @@ namespace Il2CppDumper
var version = config.ForceIl2CppVersion ? config.ForceVersion : metadata.version;
Console.WriteLine("Initializing il2cpp file...");
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
if (is64bit)
il2cpp = new Elf64(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
else
il2cpp = new Elf(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
else if (is64bit)
il2cpp = new Macho64(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
il2cpp = new Macho64(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
else
il2cpp = new Macho(new MemoryStream(il2cppfile), version, metadata.maxmetadataUsages);
il2cpp = new Macho(new MemoryStream(il2cppfile), version, metadata.maxMetadataUsages);
switch (key.KeyChar)
{
case '2':
@ -91,7 +98,7 @@ namespace Il2CppDumper
{
if (key.KeyChar == '5')
{
var elf = (Elf)il2cpp;
dynamic elf = il2cpp;
if (!elf.DetectedSymbol())
{
throw new Exception();
@ -108,8 +115,9 @@ namespace Il2CppDumper
throw new Exception();
}
}
catch
catch (Exception e)
{
Console.WriteLine($"{e.Message}\r\n{e.StackTrace}\r\n");
throw new Exception("ERROR: Can't use this mode to process file, try another mode.");
}
break;
@ -529,7 +537,7 @@ namespace Il2CppDumper
{
if (!config.DumpAttribute || il2cpp.version < 21)
return "";
var attributeTypeRange = metadata.attributesInfos[index];
var attributeTypeRange = metadata.attributeTypeRanges[index];
var sb = new StringBuilder();
for (var i = 0; i < attributeTypeRange.count; i++)
{