基础Unity2019.1支持

Elf arm Unity2019.1支持
This commit is contained in:
Perfare 2019-04-26 09:47:42 +08:00
parent 3a2d25f39f
commit b8679e2985
7 changed files with 389 additions and 262 deletions

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
namespace Il2CppDumper
{
static class BoyerMooreHorspool
{
public static IEnumerable<int> IndicesOf(this byte[] source, byte[] pattern)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (pattern == null)
{
throw new ArgumentNullException(nameof(pattern));
}
int valueLength = source.Length;
int patternLength = pattern.Length;
if ((valueLength == 0) || (patternLength == 0) || (patternLength > valueLength))
{
yield break;
}
var badCharacters = new int[256];
for (var i = 0; i < 256; i++)
{
badCharacters[i] = patternLength;
}
var lastPatternByte = patternLength - 1;
for (int i = 0; i < lastPatternByte; i++)
{
badCharacters[pattern[i]] = lastPatternByte - i;
}
int index = 0;
while (index <= valueLength - patternLength)
{
for (var i = lastPatternByte; source[index + i] == pattern[i]; i--)
{
if (i == 0)
{
yield return index;
break;
}
}
index += badCharacters[source[index + lastPatternByte]];
}
}
}
}

View file

@ -91,164 +91,160 @@ namespace Il2CppDumper
}
}
//处理field, method, property等等
for (var index = 0; index < metadata.typeDefs.Length; ++index)
for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
{
var typeDef = metadata.typeDefs[index];
var typeDefinition = typeDefinitionDic[index];
//field
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
var imageDef = metadata.imageDefs[imageIndex];
var typeEnd = imageDef.typeStart + imageDef.typeCount;
for (int index = imageDef.typeStart; index < typeEnd; index++)
{
var fieldDef = metadata.fieldDefs[i];
var fieldType = il2cpp.types[fieldDef.typeIndex];
var fieldName = metadata.GetStringFromIndex(fieldDef.nameIndex);
var fieldTypeRef = GetTypeReference(typeDefinition, fieldType);
var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
typeDefinition.Fields.Add(fieldDefinition);
//fieldDefault
if (fieldDefinition.HasDefault)
var typeDef = metadata.typeDefs[index];
var typeDefinition = typeDefinitionDic[index];
//field
var fieldEnd = typeDef.fieldStart + typeDef.field_count;
for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
{
var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
if (fieldDefault != null && fieldDefault.dataIndex != -1)
var fieldDef = metadata.fieldDefs[i];
var fieldType = il2cpp.types[fieldDef.typeIndex];
var fieldName = metadata.GetStringFromIndex(fieldDef.nameIndex);
var fieldTypeRef = GetTypeReference(typeDefinition, fieldType);
var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
typeDefinition.Fields.Add(fieldDefinition);
//fieldDefault
if (fieldDefinition.HasDefault)
{
fieldDefinition.Constant = GetDefaultValue(fieldDefault.dataIndex, fieldDefault.typeIndex);
}
}
//fieldOffset
var fieldOffset = il2cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i);
if (fieldOffset > 0)
{
var customAttribute = new CustomAttribute(typeDefinition.Module.Import(fieldOffsetAttribute));
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
customAttribute.Fields.Add(offset);
fieldDefinition.CustomAttributes.Add(customAttribute);
}
}
//method
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
var methodDef = metadata.methodDefs[i];
var methodReturnType = il2cpp.types[methodDef.returnType];
var methodName = metadata.GetStringFromIndex(methodDef.nameIndex);
var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.Import(typeof(void)));
typeDefinition.Methods.Add(methodDefinition);
methodDefinition.ReturnType = GetTypeReference(methodDefinition, methodReturnType);
if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate")
{
var ilprocessor = methodDefinition.Body.GetILProcessor();
ilprocessor.Append(ilprocessor.Create(OpCodes.Nop));
}
methodDefinitionDic.Add(i, methodDefinition);
//method parameter
for (var j = 0; j < methodDef.parameterCount; ++j)
{
var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j];
var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex);
var parameterType = il2cpp.types[parameterDef.typeIndex];
var parameterTypeRef = GetTypeReference(methodDefinition, parameterType);
var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
methodDefinition.Parameters.Add(parameterDefinition);
//ParameterDefault
if (parameterDefinition.HasDefault)
{
var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j);
if (parameterDefault != null && parameterDefault.dataIndex != -1)
var fieldDefault = metadata.GetFieldDefaultValueFromIndex(i);
if (fieldDefault != null && fieldDefault.dataIndex != -1)
{
parameterDefinition.Constant = GetDefaultValue(parameterDefault.dataIndex, parameterDefault.typeIndex);
fieldDefinition.Constant = GetDefaultValue(fieldDefault.dataIndex, fieldDefault.typeIndex);
}
}
//fieldOffset
var fieldOffset = il2cpp.GetFieldOffsetFromIndex(index, i - typeDef.fieldStart, i);
if (fieldOffset > 0)
{
var customAttribute = new CustomAttribute(typeDefinition.Module.Import(fieldOffsetAttribute));
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{fieldOffset:X}"));
customAttribute.Fields.Add(offset);
fieldDefinition.CustomAttributes.Add(customAttribute);
}
}
//method
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
var methodDef = metadata.methodDefs[i];
var methodReturnType = il2cpp.types[methodDef.returnType];
var methodName = metadata.GetStringFromIndex(methodDef.nameIndex);
var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.Import(typeof(void)));
typeDefinition.Methods.Add(methodDefinition);
methodDefinition.ReturnType = GetTypeReference(methodDefinition, methodReturnType);
if (methodDefinition.HasBody && typeDefinition.BaseType?.FullName != "System.MulticastDelegate")
{
var ilprocessor = methodDefinition.Body.GetILProcessor();
ilprocessor.Append(ilprocessor.Create(OpCodes.Nop));
}
methodDefinitionDic.Add(i, methodDefinition);
//method parameter
for (var j = 0; j < methodDef.parameterCount; ++j)
{
var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j];
var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex);
var parameterType = il2cpp.types[parameterDef.typeIndex];
var parameterTypeRef = GetTypeReference(methodDefinition, parameterType);
var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
methodDefinition.Parameters.Add(parameterDefinition);
//ParameterDefault
if (parameterDefinition.HasDefault)
{
var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j);
if (parameterDefault != null && parameterDefault.dataIndex != -1)
{
parameterDefinition.Constant = GetDefaultValue(parameterDefault.dataIndex, parameterDefault.typeIndex);
}
}
}
//补充泛型参数
if (methodDef.genericContainerIndex >= 0)
{
var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
if (genericContainer.type_argc > methodDefinition.GenericParameters.Count)
{
for (int j = methodDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
{
var genericParameter = new GenericParameter("T" + j, methodDefinition);
methodDefinition.GenericParameters.Add(genericParameter);
}
}
}
//address
var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
if (methodPointer > 0)
{
var customAttribute = new CustomAttribute(typeDefinition.Module.Import(addressAttribute));
var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}"));
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}"));
customAttribute.Fields.Add(rva);
customAttribute.Fields.Add(offset);
methodDefinition.CustomAttributes.Add(customAttribute);
}
}
//property
var propertyEnd = typeDef.propertyStart + typeDef.property_count;
for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
{
var propertyDef = metadata.propertyDefs[i];
var propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
TypeReference propertyType = null;
MethodDefinition GetMethod = null;
MethodDefinition SetMethod = null;
if (propertyDef.get >= 0)
{
GetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.get];
propertyType = GetMethod.ReturnType;
}
if (propertyDef.set >= 0)
{
SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set];
if (propertyType == null)
propertyType = SetMethod.Parameters[0].ParameterType;
}
var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
{
GetMethod = GetMethod,
SetMethod = SetMethod
};
typeDefinition.Properties.Add(propertyDefinition);
}
//event
var eventEnd = typeDef.eventStart + typeDef.event_count;
for (var i = typeDef.eventStart; i < eventEnd; ++i)
{
var eventDef = metadata.eventDefs[i];
var eventName = metadata.GetStringFromIndex(eventDef.nameIndex);
var eventType = il2cpp.types[eventDef.typeIndex];
var eventTypeRef = GetTypeReference(typeDefinition, eventType);
var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
if (eventDef.add >= 0)
eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add];
if (eventDef.remove >= 0)
eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove];
if (eventDef.raise >= 0)
eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise];
typeDefinition.Events.Add(eventDefinition);
}
//补充泛型参数
if (methodDef.genericContainerIndex >= 0)
if (typeDef.genericContainerIndex >= 0)
{
var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
if (genericContainer.type_argc > methodDefinition.GenericParameters.Count)
var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
if (genericContainer.type_argc > typeDefinition.GenericParameters.Count)
{
for (int j = methodDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
for (int j = typeDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
{
var genericParameter = new GenericParameter("T" + j, methodDefinition);
methodDefinition.GenericParameters.Add(genericParameter);
var genericParameter = new GenericParameter("T" + j, typeDefinition);
typeDefinition.GenericParameters.Add(genericParameter);
}
}
}
//address
ulong methodPointer;
if (methodDef.methodIndex >= 0)
{
methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
}
else
{
il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer);
}
if (methodPointer > 0)
{
var customAttribute = new CustomAttribute(typeDefinition.Module.Import(addressAttribute));
var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{methodPointer:X}"));
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2cpp.MapVATR(methodPointer):X}"));
customAttribute.Fields.Add(rva);
customAttribute.Fields.Add(offset);
methodDefinition.CustomAttributes.Add(customAttribute);
}
}
//property
var propertyEnd = typeDef.propertyStart + typeDef.property_count;
for (var i = typeDef.propertyStart; i < propertyEnd; ++i)
{
var propertyDef = metadata.propertyDefs[i];
var propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
TypeReference propertyType = null;
MethodDefinition GetMethod = null;
MethodDefinition SetMethod = null;
if (propertyDef.get >= 0)
{
GetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.get];
propertyType = GetMethod.ReturnType;
}
if (propertyDef.set >= 0)
{
SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set];
if (propertyType == null)
propertyType = SetMethod.Parameters[0].ParameterType;
}
var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
{
GetMethod = GetMethod,
SetMethod = SetMethod
};
typeDefinition.Properties.Add(propertyDefinition);
}
//event
var eventEnd = typeDef.eventStart + typeDef.event_count;
for (var i = typeDef.eventStart; i < eventEnd; ++i)
{
var eventDef = metadata.eventDefs[i];
var eventName = metadata.GetStringFromIndex(eventDef.nameIndex);
var eventType = il2cpp.types[eventDef.typeIndex];
var eventTypeRef = GetTypeReference(typeDefinition, eventType);
var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
if (eventDef.add >= 0)
eventDefinition.AddMethod = methodDefinitionDic[typeDef.methodStart + eventDef.add];
if (eventDef.remove >= 0)
eventDefinition.RemoveMethod = methodDefinitionDic[typeDef.methodStart + eventDef.remove];
if (eventDef.raise >= 0)
eventDefinition.InvokeMethod = methodDefinitionDic[typeDef.methodStart + eventDef.raise];
typeDefinition.Events.Add(eventDefinition);
}
//补充泛型参数
if (typeDef.genericContainerIndex >= 0)
{
var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
if (genericContainer.type_argc > typeDefinition.GenericParameters.Count)
{
for (int j = typeDefinition.GenericParameters.Count + 1; j <= genericContainer.type_argc; j++)
{
var genericParameter = new GenericParameter("T" + j, typeDefinition);
typeDefinition.GenericParameters.Add(genericParameter);
}
}
}
}
//第三遍添加CustomAttribute。只添加SerializeField用于MonoBehaviour的反序列化

View file

@ -16,9 +16,23 @@ namespace Il2CppDumper
private bool isDump;
private uint dumpAddr;
private static readonly byte[] ARMFeatureBytes = { 0x1c, 0x0, 0x9f, 0xe5, 0x1c, 0x10, 0x9f, 0xe5, 0x1c, 0x20, 0x9f, 0xe5 };
private static readonly byte[] X86FeatureBytes1 = { 0x8D, 0x83 };//lea eax, X
private static readonly byte[] X86FeatureBytes2 = { 0x89, 0x44, 0x24, 0x04, 0x8D, 0x83 };//mov [esp+4], eax and lea eax, X
//默认编译器
/*
* LDR R1, [R1,R2]
* ADD R0, R12, R2
* ADD R2, R3, R2
*/
private static readonly byte[] ARMFeatureBytesv21 = { 0x02, 0x10, 0x91, 0xE7, 0x02, 0x00, 0x8C, 0xE0, 0x02, 0x20, 0x83, 0xE0 };
/*
* LDR R1, [PC,R1]
* ADD R0, PC, R0
* ADD R2, PC, R2
*/
private static readonly byte[] ARMFeatureBytesv24 = { 0x01, 0x10, 0x9F, 0xE7, 0x00, 0x00, 0x8F, 0xE0, 0x02, 0x20, 0x8F, 0xE0 };
//TODO
private static readonly byte[] X86FeatureBytesv21 = { 0x02, 0x10, 0x91, 0xE7, 0x02, 0x00, 0x8C, 0xE0, 0x02, 0x20, 0x83, 0xE0 };
//TODO
private static readonly byte[] X86FeatureBytesv24 = { 0x01, 0x10, 0x9F, 0xE7, 0x00, 0x00, 0x8F, 0xE0, 0x02, 0x20, 0x8F, 0xE0 };
public Elf(Stream stream, float version, long maxMetadataUsages) : base(stream, version, maxMetadataUsages)
{
@ -99,63 +113,54 @@ namespace Il2CppDumper
public override bool Search()
{
var _GLOBAL_OFFSET_TABLE_ = dynamic_table.First(x => x.d_tag == DT_PLTGOT).d_un;
uint initOffset = MapVATR(dynamic_table.First(x => x.d_tag == DT_INIT_ARRAY).d_un);
var initSize = dynamic_table.First(x => x.d_tag == DT_INIT_ARRAYSZ).d_un;
var addrs = ReadClassArray<uint>(initOffset, initSize / 4u);
foreach (var i in addrs)
var execs = program_table.Where(x => x.p_type == 1u && (x.p_flags & 1) == 1).ToArray();
var resultList = new List<int>();
byte[] featureBytes = null;
if (version < 24f)
{
if (i > 0)
featureBytes = elf_header.e_machine == 40 ? ARMFeatureBytesv21 : X86FeatureBytesv21;
}
else if (version >= 24f)
{
featureBytes = elf_header.e_machine == 40 ? ARMFeatureBytesv24 : X86FeatureBytesv24;
}
foreach (var exec in execs)
{
Position = exec.p_offset;
var buff = ReadBytes((int)exec.p_filesz);
resultList.AddRange(buff.IndicesOf(featureBytes));
}
if (resultList.Count == 1)
{
uint codeRegistration = 0;
uint metadataRegistration = 0;
if (version < 24f)
{
Position = i;
if (elf_header.e_machine == 0x28) //ARM
if (elf_header.e_machine == 40)
{
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) //x86
{
Position = i + 22;
var buff = ReadBytes(2);
if (X86FeatureBytes1.SequenceEqual(buff))
{
Position = i + 28;
buff = ReadBytes(6);
if (X86FeatureBytes2.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 + 0x20;
var temp = ReadUInt16();
var metadataRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
if (temp == 0x838B)//mov
{
Position = MapVATR(metadataRegistration);
metadataRegistration = ReadUInt32();
}
Console.WriteLine("MetadataRegistration : {0:x}", metadataRegistration);
Init(codeRegistration, metadataRegistration);
return true;
}
}
var result = (uint)resultList[0];
Position = result + 0x14;
codeRegistration = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = result + 0x18;
var ptr = ReadUInt32() + _GLOBAL_OFFSET_TABLE_;
Position = MapVATR(ptr);
metadataRegistration = ReadUInt32();
}
}
else if (version >= 24f)
{
if (elf_header.e_machine == 40)
{
var result = (uint)resultList[0];
Position = result + 0x14;
codeRegistration = ReadUInt32() + result + 0xcu;
Position = result + 0x10;
var ptr = ReadUInt32() + result + 0x8;
Position = MapVATR(ptr);
metadataRegistration = ReadUInt32();
}
}
return AutoInit(codeRegistration, metadataRegistration);
}
return false;
}

View file

@ -19,9 +19,11 @@ namespace Il2CppDumper
public ulong[] metadataUsages;
private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable;
public Il2CppMethodSpec[] methodSpecs;
public Dictionary<int, ulong> genericMethoddDictionary;
private Dictionary<int, ulong> genericMethoddDictionary;
private bool isNew21;
protected long maxMetadataUsages;
private Il2CppCodeGenModule[] codeGenModules;
public ulong[][] codeGenModuleMethodPointers;
public abstract dynamic MapVATR(dynamic uiAddr);
@ -50,70 +52,106 @@ namespace Il2CppDumper
public virtual void Init(ulong codeRegistration, ulong metadataRegistration)
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
if (is32Bit)
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
methodPointers = Array.ConvertAll(MapVATR<uint>(pCodeRegistration.methodPointers, (long)pCodeRegistration.methodPointersCount), x => (ulong)x);
genericMethodPointers = Array.ConvertAll(MapVATR<uint>(pCodeRegistration.genericMethodPointers, (long)pCodeRegistration.genericMethodPointersCount), x => (ulong)x);
invokerPointers = Array.ConvertAll(MapVATR<uint>(pCodeRegistration.invokerPointers, (long)pCodeRegistration.invokerPointersCount), x => (ulong)x);
customAttributeGenerators = Array.ConvertAll(MapVATR<uint>(pCodeRegistration.customAttributeGenerators, pCodeRegistration.customAttributeCount), x => (ulong)x);
fieldOffsets = Array.ConvertAll(MapVATR<int>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount), x => (long)x);
//TODO 在21版本中存在两种FieldOffset通过判断前5个数值是否为0确认是指针还是int
//在21版本中存在两种FieldOffset通过判断前5个数值是否为0确认是指针还是int
isNew21 = version > 21 || (version == 21 && fieldOffsets.ToList().FindIndex(x => x > 0) == 5);
var ptypes = MapVATR<uint>(pMetadataRegistration.types, pMetadataRegistration.typesCount);
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] = MapVATR<Il2CppType>(pTypes[i]);
types[i].Init();
typesdic.Add(ptypes[i], types[i]);
typesdic.Add(pTypes[i], types[i]);
}
if (version > 16)
metadataUsages = Array.ConvertAll(MapVATR<uint>(pMetadataRegistration.metadataUsages, maxMetadataUsages), x => (ulong)x);
//处理泛型
genericMethodTable = MapVATR<Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount);
methodSpecs = MapVATR<Il2CppMethodSpec>(pMetadataRegistration.methodSpecs, pMetadataRegistration.methodSpecsCount);
genericMethoddDictionary = new Dictionary<int, ulong>(genericMethodTable.Length);
foreach (var table in genericMethodTable)
{
var index = methodSpecs[table.genericMethodIndex].methodDefinitionIndex;
if (!genericMethoddDictionary.ContainsKey(index))
genericMethoddDictionary.Add(index, genericMethodPointers[table.indices.methodIndex]);
metadataUsages = Array.ConvertAll(MapVATR<uint>(pMetadataRegistration.metadataUsages, maxMetadataUsages), x => (ulong)x);
}
if (version >= 24.2f)
{
var pCodeGenModules = MapVATR<uint>(pCodeRegistration.codeGenModules, (long)pCodeRegistration.codeGenModulesCount);
codeGenModules = new Il2CppCodeGenModule[pCodeGenModules.Length];
codeGenModuleMethodPointers = new ulong[pCodeGenModules.Length][];
for (int i = 0; i < pCodeGenModules.Length; i++)
{
var codeGenModule = MapVATR<Il2CppCodeGenModule>(pCodeGenModules[i]);
try
{
var ptrs = Array.ConvertAll(MapVATR<uint>(codeGenModule.methodPointers, (long)codeGenModule.methodPointerCount), x => (ulong)x);
codeGenModuleMethodPointers[i] = ptrs;
}
catch
{
//当整个DLL只有泛型函数时就有可能出现这种情况
Console.WriteLine($"WARNING: Unable to get function pointers for {ReadStringToNull(MapVATR(codeGenModule.moduleName))}");
codeGenModuleMethodPointers[i] = new ulong[codeGenModule.methodPointerCount];
}
codeGenModules[i] = codeGenModule;
}
}
else
{
methodPointers = Array.ConvertAll(MapVATR<uint>(pCodeRegistration.methodPointers, (long)pCodeRegistration.methodPointersCount), x => (ulong)x);
}
}
else
{
pCodeRegistration = MapVATR<Il2CppCodeRegistration>(codeRegistration);
pMetadataRegistration = MapVATR<Il2CppMetadataRegistration>(metadataRegistration);
methodPointers = MapVATR<ulong>(pCodeRegistration.methodPointers, (long)pCodeRegistration.methodPointersCount);
genericMethodPointers = MapVATR<ulong>(pCodeRegistration.genericMethodPointers, (long)pCodeRegistration.genericMethodPointersCount);
invokerPointers = MapVATR<ulong>(pCodeRegistration.invokerPointers, (long)pCodeRegistration.invokerPointersCount);
customAttributeGenerators = MapVATR<ulong>(pCodeRegistration.customAttributeGenerators, pCodeRegistration.customAttributeCount);
fieldOffsets = MapVATR<long>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount);
//TODO 在21版本中存在两种FieldOffset通过判断前5个数值是否为0确认是指针还是int
//在21版本中存在两种FieldOffset通过判断前5个数值是否为0确认是指针还是int
isNew21 = version > 21 || (version == 21 && fieldOffsets.ToList().FindIndex(x => x > 0) == 5);
if (!isNew21)
fieldOffsets = Array.ConvertAll(MapVATR<int>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount), x => (long)x);
var ptypes = MapVATR<ulong>(pMetadataRegistration.types, pMetadataRegistration.typesCount);
var pTypes = MapVATR<ulong>(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] = MapVATR<Il2CppType>(pTypes[i]);
types[i].Init();
typesdic.Add(ptypes[i], types[i]);
typesdic.Add(pTypes[i], types[i]);
}
if (version > 16)
metadataUsages = MapVATR<ulong>(pMetadataRegistration.metadataUsages, maxMetadataUsages);
//处理泛型
genericMethodTable = MapVATR<Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount);
methodSpecs = MapVATR<Il2CppMethodSpec>(pMetadataRegistration.methodSpecs, pMetadataRegistration.methodSpecsCount);
genericMethoddDictionary = new Dictionary<int, ulong>(genericMethodTable.Length);
foreach (var table in genericMethodTable)
{
var index = methodSpecs[table.genericMethodIndex].methodDefinitionIndex;
if (!genericMethoddDictionary.ContainsKey(index))
genericMethoddDictionary.Add(index, genericMethodPointers[table.indices.methodIndex]);
metadataUsages = MapVATR<ulong>(pMetadataRegistration.metadataUsages, maxMetadataUsages);
}
if (version >= 24.2f)
{
var pCodeGenModules = MapVATR<ulong>(pCodeRegistration.codeGenModules, (long)pCodeRegistration.codeGenModulesCount);
codeGenModules = new Il2CppCodeGenModule[pCodeGenModules.Length];
codeGenModuleMethodPointers = new ulong[pCodeGenModules.Length][];
for (int i = 0; i < pCodeGenModules.Length; i++)
{
var codeGenModule = MapVATR<Il2CppCodeGenModule>(pCodeGenModules[i]);
var ptrs = MapVATR<ulong>(codeGenModule.methodPointers, (long)codeGenModule.methodPointerCount);
codeGenModules[i] = codeGenModule;
codeGenModuleMethodPointers[i] = ptrs;
}
}
else
{
methodPointers = MapVATR<ulong>(pCodeRegistration.methodPointers, (long)pCodeRegistration.methodPointersCount);
}
}
//处理泛型
genericMethodTable = MapVATR<Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount);
methodSpecs = MapVATR<Il2CppMethodSpec>(pMetadataRegistration.methodSpecs, pMetadataRegistration.methodSpecsCount);
genericMethoddDictionary = new Dictionary<int, ulong>(genericMethodTable.Length);
foreach (var table in genericMethodTable)
{
var index = methodSpecs[table.genericMethodIndex].methodDefinitionIndex;
if (!genericMethoddDictionary.ContainsKey(index))
{
genericMethoddDictionary.Add(index, genericMethodPointers[table.indices.methodIndex]);
}
}
}
@ -163,5 +201,31 @@ namespace Il2CppDumper
return Array.ConvertAll(MapVATR<uint>(pointer, count), x => (ulong)x);
return MapVATR<ulong>(pointer, count);
}
public ulong GetMethodPointer(int methodIndex, int methodDefinitionIndex, int imageIndex, uint methodToken)
{
if (version >= 24.2f)
{
if (genericMethoddDictionary.TryGetValue(methodDefinitionIndex, out var methodPointer))
{
return methodPointer;
}
else
{
var ptrs = codeGenModuleMethodPointers[imageIndex];
var methodPointerIndex = methodToken & 0x00FFFFFFu;
return ptrs[methodPointerIndex - 1];
}
}
else
{
if (methodIndex >= 0)
{
return methodPointers[methodIndex];
}
genericMethoddDictionary.TryGetValue(methodDefinitionIndex, out var methodPointer);
return methodPointer;
}
}
}
}

View file

@ -47,6 +47,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BoyerMooreHorspool.cs" />
<Compile Include="Lz4DecoderStream.cs" />
<Compile Include="NSO.cs" />
<Compile Include="NSOClass.cs" />

View file

@ -132,7 +132,9 @@ namespace Il2CppDumper
public int parentIndex;
public int elementTypeIndex; // we can probably remove this one. Only used for enums
[Version(Max = 24.1f)]
public int rgctxStartIndex;
[Version(Max = 24.1f)]
public int rgctxCount;
public int genericContainerIndex;
@ -188,10 +190,15 @@ namespace Il2CppDumper
[Version(Max = 24)]
public int customAttributeIndex;
public int genericContainerIndex;
[Version(Max = 24.1f)]
public int methodIndex;
[Version(Max = 24.1f)]
public int invokerIndex;
[Version(Max = 24.1f)]
public int delegateWrapperIndex;
[Version(Max = 24.1f)]
public int rgctxStartIndex;
[Version(Max = 24.1f)]
public int rgctxCount;
public uint token;
public ushort flags;

View file

@ -16,6 +16,7 @@ namespace Il2CppDumper
private static Il2Cpp il2cpp;
private static Config config = new JavaScriptSerializer().Deserialize<Config>(File.ReadAllText(Application.StartupPath + Path.DirectorySeparatorChar + @"config.json"));
private static Dictionary<Il2CppMethodDefinition, string> methodModifiers = new Dictionary<Il2CppMethodDefinition, string>();
private static Dictionary<Il2CppTypeDefinition, int> typeDefImageIndices = new Dictionary<Il2CppTypeDefinition, int>();
static void ShowHelp(string programName)
{
@ -258,14 +259,16 @@ namespace Il2CppDumper
writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n");
}
//dump type
foreach (var imageDef in metadata.imageDefs)
for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
{
try
{
var imageDef = metadata.imageDefs[imageIndex];
var typeEnd = imageDef.typeStart + imageDef.typeCount;
for (int idx = imageDef.typeStart; idx < typeEnd; idx++)
{
var typeDef = metadata.typeDefs[idx];
typeDefImageIndices.Add(typeDef, imageIndex);
var isStruct = false;
var isEnum = false;
var extends = new List<string>();
@ -519,15 +522,7 @@ namespace Il2CppDumper
writer.Write(string.Join(", ", parameterStrs));
if (config.DumpMethodOffset)
{
ulong methodPointer;
if (methodDef.methodIndex >= 0)
{
methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
}
else
{
il2cpp.genericMethoddDictionary.TryGetValue(i, out methodPointer);
}
var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, i, imageIndex, methodDef.token);
if (methodPointer > 0)
{
writer.Write("); // RVA: 0x{0:X} Offset: 0x{1:X}\n", methodPointer, il2cpp.MapVATR(methodPointer));
@ -581,19 +576,13 @@ namespace Il2CppDumper
foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
{
var methodDef = metadata.methodDefs[i.Key];
var typeName = GetTypeName(metadata.typeDefs[methodDef.declaringType]);
var typeDef = metadata.typeDefs[methodDef.declaringType];
var typeName = GetTypeName(typeDef);
var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
var legalName = "Method$" + HandleSpecialCharacters(methodName);
scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{legalName}')");
ulong methodPointer;
if (methodDef.methodIndex >= 0)
{
methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
}
else
{
il2cpp.genericMethoddDictionary.TryGetValue((int)i.Key, out methodPointer);
}
var imageIndex = typeDefImageIndices[typeDef];
var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, (int)i.Key, imageIndex, methodDef.token);
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'0x{methodPointer:X}')");
}
foreach (var i in metadata.metadataUsageDic[4]) //kIl2CppMetadataUsageFieldInfo
@ -615,19 +604,13 @@ namespace Il2CppDumper
{
var methodSpec = il2cpp.methodSpecs[i.Value];
var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex];
var typeName = GetTypeName(metadata.typeDefs[methodDef.declaringType]);
var typeDef = metadata.typeDefs[methodDef.declaringType];
var typeName = GetTypeName(typeDef);
var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex) + "()";
var legalName = "Method$" + HandleSpecialCharacters(methodName);
scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{legalName}')");
ulong methodPointer;
if (methodDef.methodIndex >= 0)
{
methodPointer = il2cpp.methodPointers[methodDef.methodIndex];
}
else
{
il2cpp.genericMethoddDictionary.TryGetValue(methodSpec.methodDefinitionIndex, out methodPointer);
}
var imageIndex = typeDefImageIndices[typeDef];
var methodPointer = il2cpp.GetMethodPointer(methodDef.methodIndex, methodSpec.methodDefinitionIndex, imageIndex, methodDef.token);
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'0x{methodPointer:X}')");
}
scriptwriter.WriteLine("print('Set MetadataUsage done')");
@ -635,7 +618,19 @@ namespace Il2CppDumper
//Script - MakeFunction
if (config.MakeFunction)
{
var orderedPointers = il2cpp.methodPointers.ToList();
List<ulong> orderedPointers;
if (il2cpp.version >= 24.2f)
{
orderedPointers = new List<ulong>();
foreach (var methodPointers in il2cpp.codeGenModuleMethodPointers)
{
orderedPointers.AddRange(methodPointers);
}
}
else
{
orderedPointers = il2cpp.methodPointers.ToList();
}
orderedPointers.AddRange(il2cpp.genericMethodPointers.Where(x => x > 0));
orderedPointers.AddRange(il2cpp.invokerPointers);
orderedPointers.AddRange(il2cpp.customAttributeGenerators);