mirror of
https://github.com/Perfare/Il2CppDumper.git
synced 2025-01-10 03:27:28 -03:00
支持metadata v23版本
This commit is contained in:
parent
a953d2f966
commit
f693a41d5b
8 changed files with 1159 additions and 284 deletions
|
@ -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" />
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
429
Il2CppDumper/v23/Dump.cs
Normal 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
151
Il2CppDumper/v23/Elf.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
56
Il2CppDumper/v23/Il2Cpp.cs
Normal file
56
Il2CppDumper/v23/Il2Cpp.cs
Normal 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
110
Il2CppDumper/v23/Macho.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
88
Il2CppDumper/v23/Metadata.cs
Normal file
88
Il2CppDumper/v23/Metadata.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue