IDA脚本写入完整MetadataUsage

Default value完善
完整嵌套类型名称
This commit is contained in:
Perfare 2019-04-07 07:10:57 +08:00
parent 5d26d0f480
commit 0dabcce8dc
6 changed files with 149 additions and 43 deletions

View file

@ -18,7 +18,7 @@ namespace Il2CppDumper
private Dictionary<ulong, Il2CppType> typesdic = new Dictionary<ulong, Il2CppType>();
public ulong[] metadataUsages;
private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable;
private Il2CppMethodSpec[] methodSpecs;
public Il2CppMethodSpec[] methodSpecs;
public Dictionary<int, ulong> genericMethoddDictionary;
private bool isNew21;
protected long maxMetadataUsages;

View file

@ -25,11 +25,12 @@ namespace Il2CppDumper
private Il2CppMetadataUsagePair[] metadataUsagePairs;
public int[] attributeTypes;
public int[] interfaceIndices;
public SortedDictionary<uint, string> stringLiteralsdic;
public Dictionary<uint, SortedDictionary<uint, uint>> metadataUsageDic;
public long maxMetadataUsages;
public int[] nestedTypeIndices;
public Il2CppEventDefinition[] eventDefs;
public Il2CppGenericContainer[] genericContainers;
public Il2CppFieldRef[] fieldRefs;
public Metadata(Stream stream, float version) : base(stream)
{
@ -87,7 +88,11 @@ namespace Il2CppDumper
metadataUsageLists = ReadClassArray<Il2CppMetadataUsageList>(pMetadataHdr.metadataUsageListsOffset, pMetadataHdr.metadataUsageListsCount / MySizeOf(typeof(Il2CppMetadataUsageList)));
//Il2CppMetadataUsagePair
metadataUsagePairs = ReadClassArray<Il2CppMetadataUsagePair>(pMetadataHdr.metadataUsagePairsOffset, pMetadataHdr.metadataUsagePairsCount / MySizeOf(typeof(Il2CppMetadataUsagePair)));
CreateStringLiteralDic();
//Il2CppFieldRef
fieldRefs = ReadMetadataClassArray<Il2CppFieldRef>(pMetadataHdr.fieldRefsOffset, pMetadataHdr.fieldRefsCount);
}
if (version > 20)
{
@ -98,6 +103,11 @@ namespace Il2CppDumper
}
}
private T[] ReadMetadataClassArray<T>(int addr, int count) where T : new()
{
return ReadClassArray<T>(addr, count / MySizeOf(typeof(T)));
}
public Il2CppFieldDefaultValue GetFieldDefaultValueFromIndex(int index)
{
return fieldDefaultValues.FirstOrDefault(x => x.fieldIndex == index);
@ -138,7 +148,7 @@ namespace Il2CppDumper
}
}
private string GetStringLiteralFromIndex(uint index)
public string GetStringLiteralFromIndex(uint index)
{
var stringLiteral = stringLiterals[index];
Position = pMetadataHdr.stringLiteralDataOffset + stringLiteral.dataIndex;
@ -147,7 +157,11 @@ namespace Il2CppDumper
private void CreateStringLiteralDic()
{
stringLiteralsdic = new SortedDictionary<uint, string>();
metadataUsageDic = new Dictionary<uint, SortedDictionary<uint, uint>>();
for (uint i = 1; i <= 6u; i++)
{
metadataUsageDic[i] = new SortedDictionary<uint, uint>();
}
foreach (var metadataUsageList in metadataUsageLists)
{
for (int i = 0; i < metadataUsageList.count; i++)
@ -156,13 +170,10 @@ namespace Il2CppDumper
var metadataUsagePair = metadataUsagePairs[offset];
var usage = GetEncodedIndexType(metadataUsagePair.encodedSourceIndex);
var decodedIndex = GetDecodedMethodIndex(metadataUsagePair.encodedSourceIndex);
if (usage == 5) //kIl2CppMetadataUsageStringLiteral
{
stringLiteralsdic[metadataUsagePair.destinationIndex] = GetStringLiteralFromIndex(decodedIndex);
}
metadataUsageDic[usage][metadataUsagePair.destinationIndex] = decodedIndex;
}
}
maxMetadataUsages = stringLiteralsdic.Last().Key + 1;
maxMetadataUsages = metadataUsageDic[5].Last().Key + 1;
}

View file

@ -292,4 +292,10 @@ namespace Il2CppDumper
/* Our type parameters. */
public int genericParameterStart;
}
public class Il2CppFieldRef
{
public int typeIndex;
public int fieldIndex; // local offset into type fields
}
}

View file

@ -313,7 +313,7 @@ namespace Il2CppDumper
writer.Write("enum ");
else
writer.Write("class ");
var typeName = metadata.GetStringFromIndex(typeDef.nameIndex);
var typeName = GetTypeName(typeDef);
writer.Write($"{typeName}");
if (extends.Count > 0)
writer.Write($" : {string.Join(", ", extends)}");
@ -371,61 +371,65 @@ namespace Il2CppDumper
var pointer = metadata.GetDefaultValueFromIndex(fieldDefault.dataIndex);
if (pointer > 0)
{
var pTypeToUse = il2cpp.types[fieldDefault.typeIndex];
var fieldDefaultType = il2cpp.types[fieldDefault.typeIndex];
metadata.Position = pointer;
object multi = null;
switch (pTypeToUse.type)
object val = null;
switch (fieldDefaultType.type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
multi = metadata.ReadBoolean();
val = metadata.ReadBoolean();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
multi = metadata.ReadByte();
val = metadata.ReadByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
multi = metadata.ReadSByte();
val = metadata.ReadSByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
multi = BitConverter.ToChar(metadata.ReadBytes(2), 0);
val = BitConverter.ToChar(metadata.ReadBytes(2), 0);
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
multi = metadata.ReadUInt16();
val = metadata.ReadUInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
multi = metadata.ReadInt16();
val = metadata.ReadInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
multi = metadata.ReadUInt32();
val = metadata.ReadUInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
multi = metadata.ReadInt32();
val = metadata.ReadInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
multi = metadata.ReadUInt64();
val = metadata.ReadUInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
multi = metadata.ReadInt64();
val = metadata.ReadInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
multi = metadata.ReadSingle();
val = metadata.ReadSingle();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
multi = metadata.ReadDouble();
val = metadata.ReadDouble();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
var uiLen = metadata.ReadInt32();
multi = Encoding.UTF8.GetString(metadata.ReadBytes(uiLen));
var len = metadata.ReadInt32();
val = Encoding.UTF8.GetString(metadata.ReadBytes(len));
break;
//case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
default:
writer.Write($" /*Default value offset 0x{pointer:X}*/");
break;
}
if (multi is string str)
if (val is string str)
writer.Write($" = \"{ToEscapedString(str)}\"");
else if (multi is char c)
else if (val is char c)
{
var v = (int)c;
writer.Write($" = '\\x{v:x}'");
}
else if (multi != null)
writer.Write($" = {multi}");
else if (val != null)
writer.Write($" = {val}");
}
}
if (config.DumpFieldOffset)
@ -513,7 +517,7 @@ namespace Il2CppDumper
writer.Write("); // RVA: 0x{0:X} Offset: 0x{1:X}\n", methodPointer, il2cpp.MapVATR(methodPointer));
//Script - method
var name = ToEscapedString(HandleSpecialCharacters(typeName + "$$" + methodName));
scriptwriter.WriteLine($"SetMethod(0x{methodPointer:X}, '{name}')");
scriptwriter.WriteLine($"SetName(0x{methodPointer:X}, '{name}')");
}
else
{
@ -537,17 +541,81 @@ namespace Il2CppDumper
writer.Write("*/\n}\n");
}
}
//Script - stringLiteral
scriptwriter.WriteLine("print('Make method name done')");
scriptwriter.WriteLine("print('Setting String...')");
//Script - MetadataUsage
scriptwriter.WriteLine("print('Setting MetadataUsage...')");
if (il2cpp.version > 16)
{
foreach (var i in metadata.stringLiteralsdic)
foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
{
scriptwriter.WriteLine($"SetString(0x{il2cpp.metadataUsages[i.Key]:X}, r'{ToEscapedString(i.Value)}')");
var type = il2cpp.types[i.Value];
var typeName = GetTypeName(type, true);
var legalName = "Class$" + HandleSpecialCharacters(typeName);
scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{legalName}')");
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'{typeName}')");
}
foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
{
var type = il2cpp.types[i.Value];
var typeName = GetTypeName(type, true);
var legalName = "Class$" + HandleSpecialCharacters(typeName);
scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{legalName}')");
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'{typeName}')");
}
foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
{
var methodDef = metadata.methodDefs[i.Key];
var typeName = GetTypeName(metadata.typeDefs[methodDef.declaringType]);
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);
}
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'0x{methodPointer:X}')");
}
foreach (var i in metadata.metadataUsageDic[4]) //kIl2CppMetadataUsageFieldInfo
{
var fieldRef = metadata.fieldRefs[i.Value];
var type = il2cpp.types[fieldRef.typeIndex];
var typeDef = metadata.typeDefs[type.data.klassIndex];
var fieldDef = metadata.fieldDefs[typeDef.fieldStart + fieldRef.fieldIndex];
var fieldName = GetTypeName(type, true) + "." + metadata.GetStringFromIndex(fieldDef.nameIndex);
var legalName = "Field$" + HandleSpecialCharacters(fieldName);
scriptwriter.WriteLine($"SetName(0x{il2cpp.metadataUsages[i.Key]:X}, '{legalName}')");
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'{fieldName}')");
}
foreach (var i in metadata.metadataUsageDic[5]) //kIl2CppMetadataUsageStringLiteral
{
scriptwriter.WriteLine($"SetString(0x{il2cpp.metadataUsages[i.Key]:X}, r'{ToEscapedString(metadata.GetStringLiteralFromIndex(i.Value))}')");
}
foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
{
var methodSpec = il2cpp.methodSpecs[i.Value];
var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex];
var typeName = GetTypeName(metadata.typeDefs[methodDef.declaringType]);
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);
}
scriptwriter.WriteLine($"idc.MakeComm(0x{il2cpp.metadataUsages[i.Key]:X}, r'0x{methodPointer:X}')");
}
}
scriptwriter.WriteLine("print('Set string done')");
scriptwriter.WriteLine("print('Set MetadataUsage done')");
//Script - MakeFunction
if (config.MakeFunction)
{
@ -588,7 +656,7 @@ namespace Il2CppDumper
}
}
private static string GetTypeName(Il2CppType pType)
private static string GetTypeName(Il2CppType pType, bool fullName = false)
{
string ret;
switch (pType.type)
@ -596,8 +664,17 @@ namespace Il2CppDumper
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
{
var klass = metadata.typeDefs[pType.data.klassIndex];
ret = metadata.GetStringFromIndex(klass.nameIndex);
var typeDef = metadata.typeDefs[pType.data.klassIndex];
ret = string.Empty;
if (fullName)
{
ret = metadata.GetStringFromIndex(typeDef.namespaceIndex);
if (ret != string.Empty)
{
ret += ".";
}
}
ret += GetTypeName(typeDef);
break;
}
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
@ -643,6 +720,17 @@ namespace Il2CppDumper
return ret;
}
private static string GetTypeName(Il2CppTypeDefinition typeDef)
{
var ret = string.Empty;
if (typeDef.declaringTypeIndex != -1)
{
ret += GetTypeName(il2cpp.types[typeDef.declaringTypeIndex]) + ".";
}
ret += metadata.GetStringFromIndex(typeDef.nameIndex);
return ret;
}
private static string GetCustomAttribute(Il2CppImageDefinition image, int customAttributeIndex, uint token, string padding = "")
{
if (!config.DumpAttribute || il2cpp.version < 21)
@ -722,6 +810,7 @@ namespace Il2CppDumper
str = str.Replace("<", "_");
str = str.Replace(">", "_");
str = str.Replace(",", "_");
str = str.Replace("-", "_");
return str;
}

View file

@ -72,7 +72,7 @@ namespace Il2CppDumper {
/// idc.MakeComm(addr, comm)
/// index += 1
///
///def SetMethod(addr, name):
///def SetName(addr, name):
/// i = 0
/// ret = idc.MakeNameEx(addr, name, SN_NOWARN)
/// if ret == 0:
@ -81,7 +81,7 @@ namespace Il2CppDumper {
///
///def MakeFunction(start, end):
/// if GetFunctionAttr(start, FUNCATTR_START) == 0xFFFFFFFF:
/// idc.Mak [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// idc.MakeF [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string ida {
get {

View file

@ -129,7 +129,7 @@ def SetString(addr, comm):
idc.MakeComm(addr, comm)
index += 1
def SetMethod(addr, name):
def SetName(addr, name):
i = 0
ret = idc.MakeNameEx(addr, name, SN_NOWARN)
if ret == 0: