支持metadata v23版本

This commit is contained in:
Perfare 2017-04-05 15:40:43 +08:00
parent a953d2f966
commit f693a41d5b
8 changed files with 1159 additions and 284 deletions

View file

@ -55,7 +55,12 @@
<Compile Include="MyBinaryReader.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="v23\Dump.cs" />
<Compile Include="v23\Elf.cs" />
<Compile Include="v23\Il2Cpp.cs" />
<Compile Include="v23\Il2CppClass.cs" />
<Compile Include="v23\Macho.cs" />
<Compile Include="v23\Metadata.cs" />
<Compile Include="v23\MetadataClass.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -22,14 +22,6 @@ namespace Il2CppDumper
public Metadata(Stream stream) : base(stream)
{
pMetadataHdr = ReadClass<Il2CppGlobalMetadataHeader>();
if (pMetadataHdr.sanity != 0xFAB11BAF)
{
throw new Exception("ERROR: Metadata file supplied is not valid metadata file.");
}
if (pMetadataHdr.version != 21 && pMetadataHdr.version != 22)
{
throw new Exception($"ERROR: Metadata file supplied is not a supported version[{pMetadataHdr.version}].");
}
uiImageCount = pMetadataHdr.imagesCount / MySizeOf(typeof(Il2CppImageDefinition));
uiNumTypes = pMetadataHdr.typeDefinitionsCount / MySizeOf(typeof(Il2CppTypeDefinition));
imageDefs = ReadClassArray<Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount);

View file

@ -25,294 +25,338 @@ namespace Il2CppDumper
{
try
{
//判断magic
var macig = BitConverter.ToUInt32(il2cppfile, 0);
var isElf = false;
if (macig == 0x464c457f) //Elf
var metadatafile = File.ReadAllBytes(ofd.FileName);
//判断Metadata的magic和version
var metadatamagic = BitConverter.ToUInt32(metadatafile, 0);
if (metadatamagic != 0xFAB11BAF)
{
isElf = true;
throw new Exception("ERROR: Metadata file supplied is not valid metadata file.");
}
else if (macig == 0xCAFEBABE || macig == 0xBEBAFECA) //FAT
var metadataversion = BitConverter.ToUInt32(metadatafile, 4);
if (metadataversion == 23)
{
var fat = new MachoFat(new MemoryStream(il2cppfile));
il2cppfile = fat.GetMacho32bit();
if (il2cppfile == null)
throw new Exception("ERROR: il2cpp file not supported.");
v23.Dump.Dumpv23(il2cppfile, metadatafile);
}
else if (macig != 0xFEEDFACE) //32-bit mach object file
else if (metadataversion == 21 || metadataversion == 22)
{
throw new Exception("ERROR: il2cpp file not supported.");
}
Console.WriteLine("Select Mode: 1. Manual 2.Auto");
var key = Console.ReadKey(true);
if (key.KeyChar == '2')
{
metadata = new Metadata(new MemoryStream(File.ReadAllBytes(ofd.FileName)));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile));
else
il2cpp = new Macho(new MemoryStream(il2cppfile));
if (!il2cpp.Auto())
//判断il2cpp的magic
var il2cppmagic = BitConverter.ToUInt32(il2cppfile, 0);
var isElf = false;
if (il2cppmagic == 0x464c457f) //Elf
{
throw new Exception("ERROR: Unable to process file automatically, try to use manual mode.");
isElf = true;
}
else if (il2cppmagic == 0xCAFEBABE || il2cppmagic == 0xBEBAFECA) //FAT
{
var fat = new MachoFat(new MemoryStream(il2cppfile));
il2cppfile = fat.GetMacho32bit();
if (il2cppfile == null)
throw new Exception("ERROR: il2cpp file not supported.");
}
else if (il2cppmagic != 0xFEEDFACE) //32-bit mach object file
{
throw new Exception("ERROR: il2cpp file not supported.");
}
Console.WriteLine("Select Mode: 1. Manual 2.Auto");
var key = Console.ReadKey(true);
if (key.KeyChar == '2')
{
metadata = new Metadata(new MemoryStream(metadatafile));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile));
else
il2cpp = new Macho(new MemoryStream(il2cppfile));
if (!il2cpp.Auto())
{
throw new Exception(
"ERROR: Unable to process file automatically, try to use manual mode.");
}
}
else if (key.KeyChar == '1')
{
Console.Write("Input CodeRegistration(R0): ");
var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
Console.Write("Input MetadataRegistration(R1): ");
var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
metadata = new Metadata(new MemoryStream(metadatafile));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile), codeRegistration,
metadataRegistration);
else
il2cpp = new Macho(new MemoryStream(il2cppfile), codeRegistration,
metadataRegistration);
}
}
else if (key.KeyChar == '1')
{
Console.Write("Input CodeRegistration(R0): ");
var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
Console.Write("Input MetadataRegistration(R1): ");
var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
metadata = new Metadata(new MemoryStream(File.ReadAllBytes(ofd.FileName)));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile), codeRegistration, metadataRegistration);
else
il2cpp = new Macho(new MemoryStream(il2cppfile), codeRegistration, metadataRegistration);
{
return;
}
var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
Console.WriteLine("Dumping...");
//dump_image();
for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
{
var imageDef = metadata.imageDefs[imageIndex];
writer.Write(
$"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
}
for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
{
try
{
//dump_class(i);
var typeDef = metadata.typeDefs[idx];
writer.Write($"\n// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
if ((typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
writer.Write("[Serializable]\n");
if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) ==
TYPE_ATTRIBUTE_NOT_PUBLIC)
writer.Write("internal ");
if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
if ((typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
writer.Write("sealed ");
if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
writer.Write("interface ");
else
writer.Write("class ");
writer.Write($"{metadata.GetString(typeDef.nameIndex)}");
if (typeDef.parentIndex >= 0)
{
var parent = il2cpp.types[typeDef.parentIndex];
var parentname = get_type_name(parent);
if (parentname != "object")
writer.Write($" : {parentname}");
}
writer.Write($" // TypeDefIndex: {idx}\n{{\n");
if (typeDef.field_count > 0)
{
writer.Write("\t// Fields\n");
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
{
//dump_field(i, idx, i - typeDef.fieldStart);
var pField = metadata.fieldDefs[i];
var pType = il2cpp.types[pField.typeIndex];
var pDefault = metadata.GetFieldDefaultFromIndex(i);
writer.Write(GetCustomAttribute(pField.customAttributeIndex, "\t"));
writer.Write("\t");
if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((pType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
if ((pType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
writer.Write("readonly ");
writer.Write(
$"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
if (pDefault != null && pDefault.dataIndex != -1)
{
var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
if (pointer > 0)
{
var pTypeToUse = il2cpp.types[pDefault.typeIndex];
metadata.Position = pointer;
object multi = null;
switch (pTypeToUse.type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
multi = metadata.ReadBoolean();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
multi = metadata.ReadByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
multi = metadata.ReadSByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
multi = metadata.ReadChar();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
multi = metadata.ReadUInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
multi = metadata.ReadInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
multi = metadata.ReadUInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
multi = metadata.ReadInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
multi = metadata.ReadUInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
multi = metadata.ReadInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
multi = metadata.ReadSingle();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
multi = metadata.ReadDouble();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
var uiLen = metadata.ReadInt32();
multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
break;
}
if (multi is string)
writer.Write($" = \"{multi}\"");
else if (multi != null)
writer.Write($" = {multi}");
}
}
writer.Write("; // 0x{0:x}\n",
il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
}
writer.Write("\n");
}
if (typeDef.property_count > 0)
{
//dump_property(i);
writer.Write("\t// Properties\n");
var propertyEnd = typeDef.propertyStart + typeDef.property_count;
for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
{
var propertydef = metadata.propertyDefs[i];
writer.Write(GetCustomAttribute(propertydef.customAttributeIndex, "\t"));
writer.Write("\t");
if (propertydef.get >= 0)
{
var methodDef =
metadata.methodDefs[typeDef.methodStart + propertydef.get];
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write(
$"{get_type_name(pReturnType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
else if (propertydef.set > 0)
{
var methodDef =
metadata.methodDefs[typeDef.methodStart + propertydef.set];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
var pParam = metadata.parameterDefs[methodDef.parameterStart];
var pType = il2cpp.types[pParam.typeIndex];
writer.Write(
$"{get_type_name(pType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
if (propertydef.get >= 0)
writer.Write("get; ");
if (propertydef.set >= 0)
writer.Write("set; ");
writer.Write("}");
writer.Write("\n");
}
writer.Write("\n");
}
if (typeDef.method_count > 0)
{
writer.Write("\t// Methods\n");
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
//dump_method(i);
var methodDef = metadata.methodDefs[i];
writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
writer.Write("\t");
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write(
$"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
for (var j = 0; j < methodDef.parameterCount; ++j)
{
var pParam = metadata.parameterDefs[methodDef.parameterStart + j];
var szParamName = metadata.GetString(pParam.nameIndex);
var pType = il2cpp.types[pParam.typeIndex];
var szTypeName = get_type_name(pType);
if ((pType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
writer.Write("optional ");
if ((pType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
writer.Write("out ");
if (j != methodDef.parameterCount - 1)
{
writer.Write($"{szTypeName} {szParamName}, ");
}
else
{
writer.Write($"{szTypeName} {szParamName}");
}
}
if (methodDef.methodIndex >= 0)
writer.Write("); // {0:x}\n",
il2cpp.methodPointers[methodDef.methodIndex]);
else
writer.Write("); // 0\n");
}
}
writer.Write("}\n");
}
catch (Exception e)
{
Console.WriteLine("ERROR: Some errors in dumping");
writer.Write("/*");
writer.Write($"{e.Message}\n{e.StackTrace}\n");
writer.Write("*/\n}\n");
}
}
writer.Close();
Console.WriteLine("Done !");
}
else
{
return;
throw new Exception($"ERROR: Metadata file supplied is not a supported version[{metadataversion}].");
}
var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
Console.WriteLine("Dumping...");
//dump_image();
for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
{
var imageDef = metadata.imageDefs[imageIndex];
writer.Write($"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
}
for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
{
try
{
//dump_class(i);
var typeDef = metadata.typeDefs[idx];
writer.Write($"\n// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
if ((typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
writer.Write("[Serializable]\n");
if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NOT_PUBLIC)
writer.Write("internal ");
if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
if ((typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
writer.Write("sealed ");
if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
writer.Write("interface ");
else
writer.Write("class ");
writer.Write($"{metadata.GetString(typeDef.nameIndex)}");
if (typeDef.parentIndex >= 0)
{
var parent = il2cpp.types[typeDef.parentIndex];
var parentname = get_type_name(parent);
if (parentname != "object")
writer.Write($" : {parentname}");
}
writer.Write($" // TypeDefIndex: {idx}\n{{\n");
if (typeDef.field_count > 0)
{
writer.Write("\t// Fields\n");
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
{
//dump_field(i, idx, i - typeDef.fieldStart);
var pField = metadata.fieldDefs[i];
var pType = il2cpp.types[pField.typeIndex];
var pDefault = metadata.GetFieldDefaultFromIndex(i);
writer.Write(GetCustomAttribute(pField.customAttributeIndex, "\t"));
writer.Write("\t");
if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((pType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
if ((pType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
writer.Write("readonly ");
writer.Write($"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
if (pDefault != null && pDefault.dataIndex != -1)
{
var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
if (pointer > 0)
{
var pTypeToUse = il2cpp.types[pDefault.typeIndex];
metadata.Position = pointer;
object multi = null;
switch (pTypeToUse.type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
multi = metadata.ReadBoolean();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
multi = metadata.ReadByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
multi = metadata.ReadSByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
multi = metadata.ReadChar();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
multi = metadata.ReadUInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
multi = metadata.ReadInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
multi = metadata.ReadUInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
multi = metadata.ReadInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
multi = metadata.ReadUInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
multi = metadata.ReadInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
multi = metadata.ReadSingle();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
multi = metadata.ReadDouble();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
var uiLen = metadata.ReadInt32();
multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
break;
}
if (multi is string)
writer.Write($" = \"{multi}\"");
else if (multi != null)
writer.Write($" = {multi}");
}
}
writer.Write("; // 0x{0:x}\n", il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
}
writer.Write("\n");
}
if (typeDef.property_count > 0)
{
//dump_property(i);
writer.Write("\t// Properties\n");
var propertyEnd = typeDef.propertyStart + typeDef.property_count;
for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
{
var propertydef = metadata.propertyDefs[i];
writer.Write(GetCustomAttribute(propertydef.customAttributeIndex, "\t"));
writer.Write("\t");
if (propertydef.get >= 0)
{
var methodDef = metadata.methodDefs[typeDef.methodStart + propertydef.get];
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write($"{get_type_name(pReturnType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
else if (propertydef.set > 0)
{
var methodDef = metadata.methodDefs[typeDef.methodStart + propertydef.set];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
var pParam = metadata.parameterDefs[methodDef.parameterStart];
var pType = il2cpp.types[pParam.typeIndex];
writer.Write($"{get_type_name(pType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
if (propertydef.get >= 0)
writer.Write("get; ");
if (propertydef.set >= 0)
writer.Write("set; ");
writer.Write("}");
writer.Write("\n");
}
writer.Write("\n");
}
if (typeDef.method_count > 0)
{
writer.Write("\t// Methods\n");
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
//dump_method(i);
var methodDef = metadata.methodDefs[i];
writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
writer.Write("\t");
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write($"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
for (var j = 0; j < methodDef.parameterCount; ++j)
{
var pParam = metadata.parameterDefs[methodDef.parameterStart + j];
var szParamName = metadata.GetString(pParam.nameIndex);
var pType = il2cpp.types[pParam.typeIndex];
var szTypeName = get_type_name(pType);
if ((pType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
writer.Write("optional ");
if ((pType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
writer.Write("out ");
if (j != methodDef.parameterCount - 1)
{
writer.Write($"{szTypeName} {szParamName}, ");
}
else
{
writer.Write($"{szTypeName} {szParamName}");
}
}
if (methodDef.methodIndex >= 0)
writer.Write("); // {0:x}\n", il2cpp.methodPointers[methodDef.methodIndex]);
else
writer.Write("); // 0\n");
}
}
writer.Write("}\n");
}
catch (Exception e)
{
Console.WriteLine("ERROR: Some errors in dumping");
writer.Write("/*");
writer.Write($"{e.Message}\n{e.StackTrace}\n");
writer.Write("*/\n}\n");
}
}
writer.Close();
Console.WriteLine("Done !");
}
catch (Exception e)
{

429
Il2CppDumper/v23/Dump.cs Normal file
View file

@ -0,0 +1,429 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using static Il2CppDumper.DefineConstants;
namespace Il2CppDumper.v23
{
class Dump
{
static Metadata metadata;
static Il2Cpp il2cpp;
public static void Dumpv23(byte[] il2cppfile, byte[] metadatafile)
{
//判断il2cpp的magic
var il2cppmagic = BitConverter.ToUInt32(il2cppfile, 0);
var isElf = false;
if (il2cppmagic == 0x464c457f) //Elf
{
isElf = true;
}
else if (il2cppmagic == 0xCAFEBABE || il2cppmagic == 0xBEBAFECA) //FAT
{
var fat = new MachoFat(new MemoryStream(il2cppfile));
il2cppfile = fat.GetMacho32bit();
if (il2cppfile == null)
throw new Exception("ERROR: il2cpp file not supported.");
}
else if (il2cppmagic != 0xFEEDFACE) //32-bit mach object file
{
throw new Exception("ERROR: il2cpp file not supported.");
}
Console.WriteLine("Select Mode: 1. Manual 2.Auto");
var key = Console.ReadKey(true);
if (key.KeyChar == '2')
{
metadata = new Metadata(new MemoryStream(metadatafile));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile));
else
il2cpp = new Macho(new MemoryStream(il2cppfile));
if (!il2cpp.Auto())
{
throw new Exception(
"ERROR: Unable to process file automatically, try to use manual mode.");
}
}
else if (key.KeyChar == '1')
{
Console.Write("Input CodeRegistration(R0): ");
var codeRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
Console.Write("Input MetadataRegistration(R1): ");
var metadataRegistration = Convert.ToUInt32(Console.ReadLine(), 16);
metadata = new Metadata(new MemoryStream(metadatafile));
if (isElf)
il2cpp = new Elf(new MemoryStream(il2cppfile), codeRegistration,
metadataRegistration);
else
il2cpp = new Macho(new MemoryStream(il2cppfile), codeRegistration,
metadataRegistration);
}
else
{
return;
}
var writer = new StreamWriter(new FileStream("dump.cs", FileMode.Create));
Console.WriteLine("Dumping...");
//dump_image();
for (var imageIndex = 0; imageIndex < metadata.uiImageCount; imageIndex++)
{
var imageDef = metadata.imageDefs[imageIndex];
writer.Write(
$"// Image {imageIndex}: {metadata.GetString(imageDef.nameIndex)} - {imageDef.typeStart}\n");
}
for (var idx = 0; idx < metadata.uiNumTypes; ++idx)
{
try
{
//dump_class(i);
var typeDef = metadata.typeDefs[idx];
writer.Write($"\n// Namespace: {metadata.GetString(typeDef.namespaceIndex)}\n");
writer.Write(GetCustomAttribute(typeDef.customAttributeIndex));
if ((typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
writer.Write("[Serializable]\n");
if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) ==
TYPE_ATTRIBUTE_NOT_PUBLIC)
writer.Write("internal ");
if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
if ((typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0)
writer.Write("sealed ");
if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0)
writer.Write("interface ");
else
writer.Write("class ");
writer.Write($"{metadata.GetString(typeDef.nameIndex)}");
if (typeDef.parentIndex >= 0)
{
var parent = il2cpp.types[typeDef.parentIndex];
var parentname = get_type_name(parent);
if (parentname != "object")
writer.Write($" : {parentname}");
}
writer.Write($" // TypeDefIndex: {idx}\n{{\n");
if (typeDef.field_count > 0)
{
writer.Write("\t// Fields\n");
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
{
//dump_field(i, idx, i - typeDef.fieldStart);
var pField = metadata.fieldDefs[i];
var pType = il2cpp.types[pField.typeIndex];
var pDefault = metadata.GetFieldDefaultFromIndex(i);
writer.Write(GetCustomAttribute(pField.customAttributeIndex, "\t"));
writer.Write("\t");
if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((pType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) ==
FIELD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((pType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
if ((pType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0)
writer.Write("readonly ");
writer.Write(
$"{get_type_name(pType)} {metadata.GetString(pField.nameIndex)}");
if (pDefault != null && pDefault.dataIndex != -1)
{
var pointer = metadata.GetDefaultValueFromIndex(pDefault.dataIndex);
if (pointer > 0)
{
var pTypeToUse = il2cpp.types[pDefault.typeIndex];
metadata.Position = pointer;
object multi = null;
switch (pTypeToUse.type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
multi = metadata.ReadBoolean();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
multi = metadata.ReadByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
multi = metadata.ReadSByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
multi = metadata.ReadChar();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
multi = metadata.ReadUInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
multi = metadata.ReadInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
multi = metadata.ReadUInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
multi = metadata.ReadInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
multi = metadata.ReadUInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
multi = metadata.ReadInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
multi = metadata.ReadSingle();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
multi = metadata.ReadDouble();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
var uiLen = metadata.ReadInt32();
multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
break;
}
if (multi is string)
writer.Write($" = \"{multi}\"");
else if (multi != null)
writer.Write($" = {multi}");
}
}
writer.Write("; // 0x{0:x}\n",
il2cpp.GetFieldOffsetFromIndex(idx, i - typeDef.fieldStart));
}
writer.Write("\n");
}
if (typeDef.property_count > 0)
{
//dump_property(i);
writer.Write("\t// Properties\n");
var propertyEnd = typeDef.propertyStart + typeDef.property_count;
for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
{
var propertydef = metadata.propertyDefs[i];
writer.Write(GetCustomAttribute(propertydef.customAttributeIndex, "\t"));
writer.Write("\t");
if (propertydef.get >= 0)
{
var methodDef =
metadata.methodDefs[typeDef.methodStart + propertydef.get];
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write(
$"{get_type_name(pReturnType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
else if (propertydef.set > 0)
{
var methodDef =
metadata.methodDefs[typeDef.methodStart + propertydef.set];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
var pParam = metadata.parameterDefs[methodDef.parameterStart];
var pType = il2cpp.types[pParam.typeIndex];
writer.Write(
$"{get_type_name(pType)} {metadata.GetString(propertydef.nameIndex)} {{ ");
}
if (propertydef.get >= 0)
writer.Write("get; ");
if (propertydef.set >= 0)
writer.Write("set; ");
writer.Write("}");
writer.Write("\n");
}
writer.Write("\n");
}
if (typeDef.method_count > 0)
{
writer.Write("\t// Methods\n");
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
//dump_method(i);
var methodDef = metadata.methodDefs[i];
writer.Write(GetCustomAttribute(methodDef.customAttributeIndex, "\t"));
writer.Write("\t");
var pReturnType = il2cpp.types[methodDef.returnType];
if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PRIVATE)
writer.Write("private ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_PUBLIC)
writer.Write("public ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
METHOD_ATTRIBUTE_FAMILY)
writer.Write("protected ");
if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
writer.Write("abstract ");
else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
writer.Write("virtual ");
if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
writer.Write("static ");
writer.Write(
$"{get_type_name(pReturnType)} {metadata.GetString(methodDef.nameIndex)}(");
for (var j = 0; j < methodDef.parameterCount; ++j)
{
var pParam = metadata.parameterDefs[methodDef.parameterStart + j];
var szParamName = metadata.GetString(pParam.nameIndex);
var pType = il2cpp.types[pParam.typeIndex];
var szTypeName = get_type_name(pType);
if ((pType.attrs & PARAM_ATTRIBUTE_OPTIONAL) != 0)
writer.Write("optional ");
if ((pType.attrs & PARAM_ATTRIBUTE_OUT) != 0)
writer.Write("out ");
if (j != methodDef.parameterCount - 1)
{
writer.Write($"{szTypeName} {szParamName}, ");
}
else
{
writer.Write($"{szTypeName} {szParamName}");
}
}
if (methodDef.methodIndex >= 0)
writer.Write("); // {0:x}\n",
il2cpp.methodPointers[methodDef.methodIndex]);
else
writer.Write("); // 0\n");
}
}
writer.Write("}\n");
}
catch (Exception e)
{
Console.WriteLine("ERROR: Some errors in dumping");
writer.Write("/*");
writer.Write($"{e.Message}\n{e.StackTrace}\n");
writer.Write("*/\n}\n");
}
}
writer.Close();
Console.WriteLine("Done !");
}
private static string get_type_name(Il2CppType pType)
{
string ret;
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE)
{
var klass = metadata.typeDefs[pType.data.klassIndex];
ret = metadata.GetString(klass.nameIndex);
}
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
{
var generic_class = il2cpp.MapVATR<Il2CppGenericClass>(pType.data.generic_class);
var pMainDef = metadata.typeDefs[generic_class.typeDefinitionIndex];
ret = metadata.GetString(pMainDef.nameIndex);
var typeNames = new List<string>();
var pInst = il2cpp.MapVATR<Il2CppGenericInst>(generic_class.context.class_inst);
var pointers = il2cpp.MapVATR<uint>(pInst.type_argv, (int)pInst.type_argc);
for (var i = 0; i < pInst.type_argc; ++i)
{
var pOriType = il2cpp.MapVATR<Il2CppType>(pointers[i]);
pOriType.Init();
typeNames.Add(get_type_name(pOriType));
}
ret += $"<{string.Join(", ", typeNames)}>";
}
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY)
{
var arrayType = il2cpp.MapVATR<Il2CppArrayType>(pType.data.array);
var type = il2cpp.MapVATR<Il2CppType>(arrayType.etype);
type.Init();
ret = $"{get_type_name(type)}[]";
}
else if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY)
{
var type = il2cpp.MapVATR<Il2CppType>(pType.data.type);
type.Init();
ret = $"{get_type_name(type)}[]";
}
else
{
if ((int)pType.type >= szTypeString.Length)
ret = "unknow";
else
ret = szTypeString[(int)pType.type];
}
return ret;
}
private static string GetCustomAttribute(int index, string padding = "")
{
var attributeTypeRange = metadata.attributesInfos[index];
var sb = new StringBuilder();
for (var i = 0; i < attributeTypeRange.count; i++)
{
var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
sb.AppendFormat("{0}[{1}] // {2:x}\n", padding, get_type_name(il2cpp.types[typeIndex]),
il2cpp.customAttributeGenerators[index]);
}
return sb.ToString();
}
static string[] szTypeString =
{
"END",
"void",
"bool",
"char",
"sbyte",
"byte",
"short",
"ushort",
"int",
"uint",
"long",
"ulong",
"float",
"double",
"string",
"PTR", //eg. void*
"BYREF",
"VALUETYPE",
"CLASS",
"T",
"ARRAY",
"GENERICINST",
"TYPEDBYREF",
"None",
"IntPtr",
"UIntPtr",
"None",
"FNPTR",
"object",
"SZARRAY",
"T",
"CMOD_REQD",
"CMOD_OPT",
"INTERNAL",
};
}
}

151
Il2CppDumper/v23/Elf.cs Normal file
View file

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Il2CppDumper.v23
{
class Elf : Il2Cpp
{
private elf_header elf_header;
private program_header_table[] program_table_element;
private static byte[] ARMFeatureBytes = { 0x1c, 0x0, 0x9f, 0xe5, 0x1c, 0x10, 0x9f, 0xe5, 0x1c, 0x20, 0x9f, 0xe5 };
private static byte[] X86FeatureBytes = { 0x55, 0x89, 0xE5, 0x53, 0x83, 0xE4, 0xF0, 0x83, 0xEC, 0x20, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5B };
public Elf(Stream stream) : base(stream)
{
elf_header = new elf_header();
elf_header.m_dwFormat = ReadUInt32();
elf_header.m_arch = ReadByte();
if (elf_header.m_arch == 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.e_type = ReadUInt16();
elf_header.e_machine = ReadUInt16();
elf_header.e_version = ReadUInt32();
elf_header.e_entry = ReadUInt32();
elf_header.e_phoff = ReadUInt32();
elf_header.e_shoff = ReadUInt32();
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<program_header_table>(elf_header.e_phoff, elf_header.e_phnum);
}
public Elf(Stream stream, uint codeRegistration, uint metadataRegistration) : this(stream)
{
Init(codeRegistration, metadataRegistration);
}
protected override uint MapVATR(uint 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 bool Auto()
{
//取.dynamic
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;
//从.dynamic获取_GLOBAL_OFFSET_TABLE_和.init_array
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();
}
else if (tag == 25)//DT_INIT_ARRAY
{
init_array.sh_offset = MapVATR(ReadUInt32());
}
else if (tag == 27)//DT_INIT_ARRAYSZ
{
init_array.sh_size = ReadUInt32();
}
else
{
Position += 4;//skip
}
}
if (_GLOBAL_OFFSET_TABLE_ != 0)
{
//从.init_array获取函数
var addrs = ReadClassArray<uint>(init_array.sh_offset, (int)init_array.sh_size / 4);
foreach (var i in addrs)
{
if (i > 0)
{
Position = i;
if (elf_header.e_machine == 0x28)
{
var buff = ReadBytes(12);
if (ARMFeatureBytes.SequenceEqual(buff))
{
Position = i + 0x2c;
var subaddr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = subaddr + 0x28;
var codeRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Position = subaddr + 0x2C;
var ptr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = MapVATR(ptr);
var metadataRegistration = ReadUInt32();
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
else if (elf_header.e_machine == 0x3)
{
var buff = ReadBytes(16);
if (X86FeatureBytes.SequenceEqual(buff))
{
Position = i + 0x18;
var subaddr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = subaddr + 0x2C;
var codeRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Position = subaddr + 0x22;
var ptr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = MapVATR(ptr);
var metadataRegistration = ReadUInt32();
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
else
{
Console.WriteLine("ERROR: Automatic processing does not support this ELF file.");
}
}
}
}
else
{
Console.WriteLine("ERROR: Unable to get GOT form PT_DYNAMIC.");
}
return false;
}
}
}

View file

@ -0,0 +1,56 @@
using System.IO;
namespace Il2CppDumper.v23
{
abstract class Il2Cpp : MyBinaryReader
{
private Il2CppMetadataRegistration pMetadataRegistration;
private Il2CppCodeRegistration pCodeRegistration;
public uint[] methodPointers;
public uint[] customAttributeGenerators;
private int[] fieldOffsets;
public Il2CppType[] types;
public abstract bool Auto();
protected abstract uint MapVATR(uint uiAddr);
protected Il2Cpp(Stream stream) : base(stream) { }
protected void Init(uint codeRegistration, uint metadataRegistration)
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
methodPointers = MapVATR<uint>(pCodeRegistration.methodPointers, (int)pCodeRegistration.methodPointersCount);
customAttributeGenerators = MapVATR<uint>(pCodeRegistration.customAttributeGenerators, pCodeRegistration.customAttributeCount);
fieldOffsets = MapVATR<int>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount);
var ptypes = MapVATR<uint>(pMetadataRegistration.types, pMetadataRegistration.typesCount);
types = new Il2CppType[pMetadataRegistration.typesCount];
for (var i = 0; i < pMetadataRegistration.typesCount; ++i)
{
types[i] = MapVATR<Il2CppType>(ptypes[i]);
types[i].Init();
}
}
public int GetFieldOffsetFromIndex(int typeIndex, int fieldIndexInType)
{
var ptr = fieldOffsets[typeIndex];
if (ptr >= 0)
{
Position = MapVATR((uint)ptr) + 4 * fieldIndexInType;
return ReadInt32();
}
return 0;
}
public T MapVATR<T>(uint uiAddr) where T : new()
{
return ReadClass<T>(MapVATR(uiAddr));
}
public T[] MapVATR<T>(uint uiAddr, int count) where T : new()
{
return ReadClassArray<T>(MapVATR(uiAddr), count);
}
}
}

110
Il2CppDumper/v23/Macho.cs Normal file
View file

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Il2CppDumper.v23
{
class Macho : Il2Cpp
{
private List<MachoSection> sections = new List<MachoSection>();
private static byte[] FeatureBytes1 = { 0x0, 0x22 };//MOVS R2, #0
private static byte[] FeatureBytes2 = { 0x78, 0x44, 0x79, 0x44 };//ADD R0, PC and ADD R1, PC
public Macho(Stream stream) : base(stream)
{
Position += 16;//skip
var ncmds = ReadUInt32();
Position += 8;//skip
for (var i = 0; i < ncmds; i++)
{
var offset = Position;
var loadCommandType = ReadUInt32();
var command_size = ReadUInt32();
if (loadCommandType == 1) //SEGMENT
{
var segment_name = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
if (segment_name == "__TEXT" || segment_name == "__DATA")
{
Position += 24;//skip
var number_of_sections = ReadUInt32();
Position += 4;//skip
for (var j = 0; j < number_of_sections; j++)
{
var section_name = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0');
Position += 16;
var address = ReadUInt32();
var size = ReadUInt32();
var offset2 = ReadUInt32();
var end = address + size;
sections.Add(new MachoSection() { section_name = section_name, address = address, size = size, offset = offset2, end = end });
Position += 24;
}
}
}
Position = offset + command_size;//skip
}
}
public Macho(Stream stream, uint codeRegistration, uint metadataRegistration) : this(stream)
{
Init(codeRegistration, metadataRegistration);
}
protected override uint MapVATR(uint uiAddr)
{
var section = sections.First(x => uiAddr >= x.address && uiAddr <= x.end);
return uiAddr - (section.address - section.offset);
}
public override bool Auto()
{
var __mod_init_func = sections.First(x => x.section_name == "__mod_init_func");
var addrs = ReadClassArray<uint>(__mod_init_func.offset, (int)__mod_init_func.size / 4);
foreach (var a in addrs)
{
if (a > 0)
{
var i = a - 1;
Position = MapVATR(i);
Position += 4;
var buff = ReadBytes(2);
if (FeatureBytes1.SequenceEqual(buff))
{
Position += 12;
buff = ReadBytes(4);
if (FeatureBytes2.SequenceEqual(buff))
{
Position = MapVATR(i) + 10;
var subaddr = decodeMov(ReadBytes(8)) + i + 24u - 1u;
var rsubaddr = MapVATR(subaddr);
Position = rsubaddr;
var ptr = decodeMov(ReadBytes(8)) + subaddr + 16u;
Position = MapVATR(ptr);
var metadataRegistration = ReadUInt32();
Position = rsubaddr + 8;
buff = ReadBytes(4);
Position = rsubaddr + 14;
buff = buff.Concat(ReadBytes(4)).ToArray();
var codeRegistration = decodeMov(buff) + subaddr + 26u;
Console.WriteLine("CodeRegistration : {0:x}", codeRegistration);
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
}
}
return false;
}
private uint decodeMov(byte[] asm)
{
var low = (ushort)(asm[2] + ((asm[3] & 0x70) << 4) + ((asm[1] & 0x04) << 9) + ((asm[0] & 0x0f) << 12));
var high = (ushort)(asm[6] + ((asm[7] & 0x70) << 4) + ((asm[5] & 0x04) << 9) + ((asm[4] & 0x0f) << 12));
return (uint)((high << 16) + low);
}
}
}

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Il2CppDumper.v23
{
class Metadata : MyBinaryReader
{
private Il2CppGlobalMetadataHeader pMetadataHdr;
public int uiImageCount;
public int uiNumTypes;
public Il2CppImageDefinition[] imageDefs;
public Il2CppTypeDefinition[] typeDefs;
public Il2CppMethodDefinition[] methodDefs;
public Il2CppParameterDefinition[] parameterDefs;
public Il2CppFieldDefinition[] fieldDefs;
private Il2CppFieldDefaultValue[] fieldDefaultValues;
public Il2CppPropertyDefinition[] propertyDefs;
public Il2CppCustomAttributeTypeRange[] attributesInfos;
public int[] attributeTypes;
public Metadata(Stream stream) : base(stream)
{
pMetadataHdr = ReadClass<Il2CppGlobalMetadataHeader>();
uiImageCount = pMetadataHdr.imagesCount / MySizeOf(typeof(Il2CppImageDefinition));
uiNumTypes = pMetadataHdr.typeDefinitionsCount / MySizeOf(typeof(Il2CppTypeDefinition));
imageDefs = ReadClassArray<Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount);
//GetTypeDefFromIndex
typeDefs = ReadClassArray<Il2CppTypeDefinition>(pMetadataHdr.typeDefinitionsOffset, uiNumTypes);
//GetMethodDefinition
methodDefs = ReadClassArray<Il2CppMethodDefinition>(pMetadataHdr.methodsOffset, pMetadataHdr.methodsCount / MySizeOf(typeof(Il2CppMethodDefinition)));
//GetParameterFromIndex
parameterDefs = ReadClassArray<Il2CppParameterDefinition>(pMetadataHdr.parametersOffset, pMetadataHdr.parametersCount / MySizeOf(typeof(Il2CppParameterDefinition)));
//GetFieldDefFromIndex
fieldDefs = ReadClassArray<Il2CppFieldDefinition>(pMetadataHdr.fieldsOffset, pMetadataHdr.fieldsCount / MySizeOf(typeof(Il2CppFieldDefinition)));
//GetFieldDefaultValuesFromIndex
fieldDefaultValues = ReadClassArray<Il2CppFieldDefaultValue>(pMetadataHdr.fieldDefaultValuesOffset, pMetadataHdr.fieldDefaultValuesCount / MySizeOf(typeof(Il2CppFieldDefaultValue)));
//GetPropertyDefinitionFromIndex
propertyDefs = ReadClassArray<Il2CppPropertyDefinition>(pMetadataHdr.propertiesOffset, pMetadataHdr.propertiesCount / MySizeOf(typeof(Il2CppPropertyDefinition)));
//GetAttributesInfoFromIndex
attributesInfos = ReadClassArray<Il2CppCustomAttributeTypeRange>(pMetadataHdr.attributesInfoOffset, pMetadataHdr.attributesInfoCount / MySizeOf(typeof(Il2CppCustomAttributeTypeRange)));
//GetAttributeTypesFromIndex
attributeTypes = ReadClassArray<int>(pMetadataHdr.attributeTypesOffset, pMetadataHdr.attributeTypesCount / 4);
}
public Il2CppFieldDefaultValue GetFieldDefaultFromIndex(int idx)
{
return fieldDefaultValues.FirstOrDefault(x => x.fieldIndex == idx);
}
public int GetDefaultValueFromIndex(int idx)
{
return pMetadataHdr.fieldAndParameterDefaultValueDataOffset + idx;
}
public string GetString(int idx)
{
return ReadStringToNull(pMetadataHdr.stringOffset + idx);
}
private int MySizeOf(Type type)
{
var size = 0;
foreach (var i in type.GetFields())
{
if (i.FieldType == typeof(int))
{
size += 4;
}
else if (i.FieldType == typeof(uint))
{
size += 4;
}
else if (i.FieldType == typeof(short))
{
size += 2;
}
else if (i.FieldType == typeof(ushort))
{
size += 2;
}
}
return size;
}
}
}