private bool CheckProtection() { //.init_proc if (dynamicSection.Any(x => x.d_tag == DT_INIT)) { FormGUI.Log("WARNING: find .init_proc"); return(true); } //JNI_OnLoad ulong dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un); foreach (var symbol in symbolTable) { var name = ReadStringToNull(dynstrOffset + symbol.st_name); switch (name) { case "JNI_OnLoad": FormGUI.Log("WARNING: find JNI_OnLoad"); return(true); } } if (sectionTable != null && sectionTable.Any(x => x.sh_type == SHT_LOUSER)) { FormGUI.Log("WARNING: find SHT_LOUSER section"); return(true); } return(false); }
protected bool AutoPlusInit(ulong codeRegistration, ulong metadataRegistration) { if (codeRegistration != 0 && metadataRegistration != 0) { if (Version == 24.2) { pCodeRegistration = MapVATR <Il2CppCodeRegistration>(codeRegistration); if (pCodeRegistration.reversePInvokeWrapperCount > 0x30000) //TODO { Version = 24.4; codeRegistration -= PointerSize * 3; Console.WriteLine($"Change il2cpp version to: {Version}"); } else { pMetadataRegistration = MapVATR <Il2CppMetadataRegistration>(metadataRegistration); genericMethodTable = MapVATR <Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount); var genericMethodPointersCount = genericMethodTable.Max(x => x.indices.methodIndex) + 1; if (pCodeRegistration.reversePInvokeWrapperCount == genericMethodPointersCount) { Version = 24.3; codeRegistration -= Is32Bit ? 8u : 16u; FormGUI.Log($"Change il2cpp version to: {Version}"); } } } FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); return(false); }
private void RelocationProcessing() { FormGUI.Log("Applying relocations..."); try { var reldynOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_REL).d_un); var reldynSize = dynamicSection.First(x => x.d_tag == DT_RELSZ).d_un; var relTable = ReadClassArray <Elf32_Rel>(reldynOffset, reldynSize / 8); var isx86 = elfHeader.e_machine == 0x3; foreach (var rel in relTable) { var type = rel.r_info & 0xff; var sym = rel.r_info >> 8; switch (type) { case R_386_32 when isx86: case R_ARM_ABS32 when !isx86: { var symbol = symbolTable[sym]; Position = MapVATR(rel.r_offset); Write(symbol.st_value); break; } } } } catch { // ignored } }
public Elf64(Stream stream) : base(stream) { elfHeader = ReadClass <Elf64_Ehdr>(); programSegment = ReadClassArray <Elf64_Phdr>(elfHeader.e_phoff, elfHeader.e_phnum); if (!CheckSection()) { GetDumpAddress(); } if (IsDumped) { FixedProgramSegment(); } pt_dynamic = programSegment.First(x => x.p_type == PT_DYNAMIC); dynamicSection = ReadClassArray <Elf64_Dyn>(pt_dynamic.p_offset, (long)pt_dynamic.p_filesz / 16L); if (IsDumped) { FixedDynamicSection(); } ReadSymbol(); if (!IsDumped) { RelocationProcessing(); if (CheckProtection()) { FormGUI.Log("ERROR: This file may be protected."); } } }
public override bool SymbolSearch() { ulong codeRegistration = 0ul; ulong metadataRegistration = 0ul; ulong dynstrOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_STRTAB).d_un); foreach (var symbol in symbolTable) { var name = ReadStringToNull(dynstrOffset + symbol.st_name); switch (name) { case "g_CodeRegistration": codeRegistration = symbol.st_value; break; case "g_MetadataRegistration": metadataRegistration = symbol.st_value; break; } } if (codeRegistration > 0 && metadataRegistration > 0) { FormGUI.Log("Detected Symbol !"); FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } FormGUI.Log("ERROR: No symbol is detected"); return(false); }
public override bool Search() { var _GLOBAL_OFFSET_TABLE_ = dynamicSection.First(x => x.d_tag == DT_PLTGOT).d_un; var execs = programSegment.Where(x => x.p_type == PT_LOAD && (x.p_flags & PF_X) == 1).ToArray(); var resultList = new List <int>(); var featureBytes = elfHeader.e_machine == EM_ARM ? ARMFeatureBytes : X86FeatureBytes; foreach (var exec in execs) { Position = exec.p_offset; var buff = ReadBytes((int)exec.p_filesz); foreach (var temp in buff.Search(featureBytes)) { var bin = buff[temp + 2].HexToBin(); if (bin[3] == '1') //LDR { resultList.Add(temp); } } } if (resultList.Count == 1) { uint codeRegistration = 0; uint metadataRegistration = 0; var result = (uint)resultList[0]; if (Version < 24) { if (elfHeader.e_machine == EM_ARM) { 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 >= 24) { if (elfHeader.e_machine == EM_ARM) { Position = result + 0x14; codeRegistration = ReadUInt32() + result + 0xcu + (uint)DumpAddr; Position = result + 0x10; var ptr = ReadUInt32() + result + 0x8; Position = MapVATR(ptr + DumpAddr); metadataRegistration = ReadUInt32(); } } FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } return(false); }
public Macho(Stream stream) : base(stream) { Is32Bit = true; Position += 16; //skip magic, cputype, cpusubtype, filetype var ncmds = ReadUInt32(); Position += 8; //skip sizeofcmds, flags for (var i = 0; i < ncmds; i++) { var pos = Position; var cmd = ReadUInt32(); var cmdsize = ReadUInt32(); switch (cmd) { case 1: //LC_SEGMENT var segname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0'); if (segname == "__TEXT") //__PAGEZERO { vmaddr = ReadUInt32(); } else { Position += 4; } Position += 20; //skip vmsize, fileoff, filesize, maxprot, initprot var nsects = ReadUInt32(); Position += 4; //skip flags for (var j = 0; j < nsects; j++) { var section = new MachoSection(); sections.Add(section); section.sectname = Encoding.UTF8.GetString(ReadBytes(16)).TrimEnd('\0'); Position += 16; //skip segname section.addr = ReadUInt32(); section.size = ReadUInt32(); section.offset = ReadUInt32(); Position += 12; //skip align, reloff, nreloc section.flags = ReadUInt32(); Position += 8; //skip reserved1, reserved2 } break; case 0x21: //LC_ENCRYPTION_INFO Position += 8; var cryptID = ReadUInt32(); if (cryptID != 0) { FormGUI.Log("ERROR: This Mach-O executable is encrypted and cannot be processed."); } break; } Position = pos + cmdsize;//next } }
public void GetDumpAddress() { FormGUI.Log("Detected this may be a dump file."); FormDump form = new FormDump(); form.Message = 0; if (form.ShowDialog() == DialogResult.OK) { DumpAddr = Convert.ToUInt64(form.ReturnedText, 16); FormGUI.Log("Inputted address: " + DumpAddr.ToString("X")); } if (DumpAddr != 0) { IsDumped = true; } }
private void RelocationProcessing() { FormGUI.Log("Applying relocations..."); try { var relaOffset = MapVATR(dynamicSection.First(x => x.d_tag == DT_RELA).d_un); var relaSize = dynamicSection.First(x => x.d_tag == DT_RELASZ).d_un; var relaTable = ReadClassArray <Elf64_Rela>(relaOffset, (long)relaSize / 24L); foreach (var rela in relaTable) { var type = rela.r_info & 0xffffffff; var sym = rela.r_info >> 32; switch (type) { case R_AARCH64_ABS64: { var symbol = symbolTable[sym]; Position = MapVATR(rela.r_offset); Write(symbol.st_value + (ulong)rela.r_addend); break; } case R_AARCH64_RELATIVE: { Position = MapVATR(rela.r_offset); Write(rela.r_addend); break; } } } } catch { // ignored } }
public virtual void Init(ulong codeRegistration, ulong metadataRegistration) { pCodeRegistration = MapVATR <Il2CppCodeRegistration>(codeRegistration); if (Version == 27) { if (pCodeRegistration.reversePInvokeWrapperCount > 0x30000) //TODO { Version = 27.1; codeRegistration -= PointerSize; FormGUI.Log($"Change il2cpp version to: {Version}"); FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); pCodeRegistration = MapVATR <Il2CppCodeRegistration>(codeRegistration); } } if (Version == 24.2) { if (pCodeRegistration.reversePInvokeWrapperCount > 0x30000) //TODO { Version = 24.4; codeRegistration -= PointerSize * 3; FormGUI.Log($"Change il2cpp version to: {Version}"); FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); pCodeRegistration = MapVATR <Il2CppCodeRegistration>(codeRegistration); } else { if (pCodeRegistration.codeGenModules == 0) //TODO { Version = 24.3; FormGUI.Log($"Change il2cpp version to: {Version}"); pCodeRegistration = MapVATR <Il2CppCodeRegistration>(codeRegistration); } } } pMetadataRegistration = MapVATR <Il2CppMetadataRegistration>(metadataRegistration); genericMethodPointers = MapVATR <ulong>(pCodeRegistration.genericMethodPointers, pCodeRegistration.genericMethodPointersCount); invokerPointers = MapVATR <ulong>(pCodeRegistration.invokerPointers, pCodeRegistration.invokerPointersCount); if (Version < 27) { customAttributeGenerators = MapVATR <ulong>(pCodeRegistration.customAttributeGenerators, pCodeRegistration.customAttributeCount); } if (Version > 16 && Version < 27) { metadataUsages = MapVATR <ulong>(pMetadataRegistration.metadataUsages, maxMetadataUsages); } if (Version >= 22) { if (pCodeRegistration.reversePInvokeWrapperCount != 0) { reversePInvokeWrappers = MapVATR <ulong>(pCodeRegistration.reversePInvokeWrappers, pCodeRegistration.reversePInvokeWrapperCount); } if (pCodeRegistration.unresolvedVirtualCallCount != 0) { unresolvedVirtualCallPointers = MapVATR <ulong>(pCodeRegistration.unresolvedVirtualCallPointers, pCodeRegistration.unresolvedVirtualCallCount); } } genericInstPointers = MapVATR <ulong>(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount); genericInsts = Array.ConvertAll(genericInstPointers, MapVATR <Il2CppGenericInst>); fieldOffsetsArePointers = Version > 21; if (Version == 21) { var fieldTest = MapVATR <uint>(pMetadataRegistration.fieldOffsets, 6); fieldOffsetsArePointers = fieldTest[0] == 0 && fieldTest[1] == 0 && fieldTest[2] == 0 && fieldTest[3] == 0 && fieldTest[4] == 0 && fieldTest[5] > 0; } if (fieldOffsetsArePointers) { fieldOffsets = MapVATR <ulong>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount); } else { fieldOffsets = Array.ConvertAll(MapVATR <uint>(pMetadataRegistration.fieldOffsets, pMetadataRegistration.fieldOffsetsCount), x => (ulong)x); } 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].Init(); typeDic.Add(pTypes[i], types[i]); } if (Version >= 24.2) { var pCodeGenModules = MapVATR <ulong>(pCodeRegistration.codeGenModules, pCodeRegistration.codeGenModulesCount); codeGenModules = new Dictionary <string, Il2CppCodeGenModule>(pCodeGenModules.Length, StringComparer.Ordinal); codeGenModuleMethodPointers = new Dictionary <string, ulong[]>(pCodeGenModules.Length, StringComparer.Ordinal); rgctxsDictionary = new Dictionary <string, Dictionary <uint, Il2CppRGCTXDefinition[]> >(pCodeGenModules.Length, StringComparer.Ordinal); foreach (var pCodeGenModule in pCodeGenModules) { var codeGenModule = MapVATR <Il2CppCodeGenModule>(pCodeGenModule); var moduleName = ReadStringToNull(MapVATR(codeGenModule.moduleName)); codeGenModules.Add(moduleName, codeGenModule); ulong[] methodPointers; try { methodPointers = MapVATR <ulong>(codeGenModule.methodPointers, codeGenModule.methodPointerCount); } catch { methodPointers = new ulong[codeGenModule.methodPointerCount]; } codeGenModuleMethodPointers.Add(moduleName, methodPointers); var rgctxsDefDictionary = new Dictionary <uint, Il2CppRGCTXDefinition[]>(); rgctxsDictionary.Add(moduleName, rgctxsDefDictionary); if (codeGenModule.rgctxsCount > 0) { var rgctxs = MapVATR <Il2CppRGCTXDefinition>(codeGenModule.rgctxs, codeGenModule.rgctxsCount); var rgctxRanges = MapVATR <Il2CppTokenRangePair>(codeGenModule.rgctxRanges, codeGenModule.rgctxRangesCount); foreach (var rgctxRange in rgctxRanges) { var rgctxDefs = new Il2CppRGCTXDefinition[rgctxRange.range.length]; Array.Copy(rgctxs, rgctxRange.range.start, rgctxDefs, 0, rgctxRange.range.length); rgctxsDefDictionary.Add(rgctxRange.token, rgctxDefs); } } } } else { methodPointers = MapVATR <ulong>(pCodeRegistration.methodPointers, pCodeRegistration.methodPointersCount); } genericMethodTable = MapVATR <Il2CppGenericMethodFunctionsDefinitions>(pMetadataRegistration.genericMethodTable, pMetadataRegistration.genericMethodTableCount); methodSpecs = MapVATR <Il2CppMethodSpec>(pMetadataRegistration.methodSpecs, pMetadataRegistration.methodSpecsCount); foreach (var table in genericMethodTable) { var methodSpec = methodSpecs[table.genericMethodIndex]; var methodDefinitionIndex = methodSpec.methodDefinitionIndex; if (!methodDefinitionMethodSpecs.TryGetValue(methodDefinitionIndex, out var list)) { list = new List <Il2CppMethodSpec>(); methodDefinitionMethodSpecs.Add(methodDefinitionIndex, list); } list.Add(methodSpec); methodSpecGenericMethodPointers.Add(methodSpec, genericMethodPointers[table.indices.methodIndex]); } }
public static void Log(string text) { main.Log(text); }
public override bool Search() { var codeRegistration = 0ul; var metadataRegistration = 0ul; if (Version < 23) { var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func"); var addrs = ReadClassArray <ulong>(__mod_init_func.offset, (long)__mod_init_func.size / 8); foreach (var i in addrs) { if (i > 0) { var flag = false; var subaddr = 0ul; Position = MapVATR(i); var buff = ReadBytes(4); if (FeatureBytes1.SequenceEqual(buff)) { buff = ReadBytes(4); if (FeatureBytes2.SequenceEqual(buff)) { Position += 8; var inst = ReadBytes(4); if (IsAdr(inst)) { subaddr = DecodeAdr(i + 16, inst); flag = true; } } } else { Position += 0xc; buff = ReadBytes(4); if (FeatureBytes2.SequenceEqual(buff)) { buff = ReadBytes(4); if (FeatureBytes1.SequenceEqual(buff)) { Position -= 0x10; var inst = ReadBytes(4); if (IsAdr(inst)) { subaddr = DecodeAdr(i + 8, inst); flag = true; } } } } if (flag) { var rsubaddr = MapVATR(subaddr); Position = rsubaddr; codeRegistration = DecodeAdrp(subaddr, ReadBytes(4)); codeRegistration += DecodeAdd(ReadBytes(4)); Position = rsubaddr + 8; metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4)); metadataRegistration += DecodeAdd(ReadBytes(4)); } } } } if (Version == 23) { /* ADRP X0, unk * ADD X0, X0, unk * ADR X1, sub * NOP * MOV X2, #0 * MOV W3, #0 * B sub */ var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func"); var addrs = ReadClassArray <ulong>(__mod_init_func.offset, (long)__mod_init_func.size / 8); foreach (var i in addrs) { if (i > 0) { Position = MapVATR(i) + 16; var buff = ReadBytes(4); if (FeatureBytes1.SequenceEqual(buff)) { buff = ReadBytes(4); if (FeatureBytes2.SequenceEqual(buff)) { Position -= 16; var subaddr = DecodeAdr(i + 8, ReadBytes(4)); var rsubaddr = MapVATR(subaddr); Position = rsubaddr; codeRegistration = DecodeAdrp(subaddr, ReadBytes(4)); codeRegistration += DecodeAdd(ReadBytes(4)); Position = rsubaddr + 8; metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4)); metadataRegistration += DecodeAdd(ReadBytes(4)); } } } } } if (Version >= 24) { /* ADRP X0, unk * ADD X0, X0, unk * ADR X1, sub * NOP * MOV W3, #0 * MOV X2, #0 * B sub */ var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func"); var addrs = ReadClassArray <ulong>(__mod_init_func.offset, (long)__mod_init_func.size / 8); foreach (var i in addrs) { if (i > 0) { Position = MapVATR(i) + 16; var buff = ReadBytes(4); if (FeatureBytes2.SequenceEqual(buff)) { buff = ReadBytes(4); if (FeatureBytes1.SequenceEqual(buff)) { Position -= 16; var subaddr = DecodeAdr(i + 8, ReadBytes(4)); var rsubaddr = MapVATR(subaddr); Position = rsubaddr; codeRegistration = DecodeAdrp(subaddr, ReadBytes(4)); codeRegistration += DecodeAdd(ReadBytes(4)); Position = rsubaddr + 8; metadataRegistration = DecodeAdrp(subaddr + 8, ReadBytes(4)); metadataRegistration += DecodeAdd(ReadBytes(4)); } } } } } if (codeRegistration != 0 && metadataRegistration != 0) { FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } return(false); }
public void Decompile(Config config, string outputDir) { var writer = new StreamWriter(new FileStream(outputDir + "dump.cs", FileMode.Create), new UTF8Encoding(false)); //dump image for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++) { var imageDef = metadata.imageDefs[imageIndex]; writer.Write($"// Image {imageIndex}: {metadata.GetStringFromIndex(imageDef.nameIndex)} - {imageDef.typeStart}\n"); } //dump type foreach (var imageDef in metadata.imageDefs) { try { var imageName = metadata.GetStringFromIndex(imageDef.nameIndex); var typeEnd = imageDef.typeStart + imageDef.typeCount; for (int typeDefIndex = imageDef.typeStart; typeDefIndex < typeEnd; typeDefIndex++) { var typeDef = metadata.typeDefs[typeDefIndex]; var extends = new List <string>(); if (typeDef.parentIndex >= 0) { var parent = il2Cpp.types[typeDef.parentIndex]; var parentName = executor.GetTypeName(parent, false, false); if (!typeDef.IsValueType && !typeDef.IsEnum && parentName != "object") { extends.Add(parentName); } } if (typeDef.interfaces_count > 0) { for (int i = 0; i < typeDef.interfaces_count; i++) { var @interface = il2Cpp.types[metadata.interfaceIndices[typeDef.interfacesStart + i]]; extends.Add(executor.GetTypeName(@interface, false, false)); } } writer.Write($"\n// Namespace: {metadata.GetStringFromIndex(typeDef.namespaceIndex)}\n"); if (config.DumpAttribute) { writer.Write(GetCustomAttribute(imageDef, typeDef.customAttributeIndex, typeDef.token)); } if (config.DumpAttribute && (typeDef.flags & TYPE_ATTRIBUTE_SERIALIZABLE) != 0) { writer.Write("[Serializable]\n"); } var visibility = typeDef.flags & TYPE_ATTRIBUTE_VISIBILITY_MASK; switch (visibility) { case TYPE_ATTRIBUTE_PUBLIC: case TYPE_ATTRIBUTE_NESTED_PUBLIC: writer.Write("public "); break; case TYPE_ATTRIBUTE_NOT_PUBLIC: case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM: case TYPE_ATTRIBUTE_NESTED_ASSEMBLY: writer.Write("internal "); break; case TYPE_ATTRIBUTE_NESTED_PRIVATE: writer.Write("private "); break; case TYPE_ATTRIBUTE_NESTED_FAMILY: writer.Write("protected "); break; case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM: writer.Write("protected internal "); break; } if ((typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0 && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0) { writer.Write("static "); } else if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) == 0 && (typeDef.flags & TYPE_ATTRIBUTE_ABSTRACT) != 0) { writer.Write("abstract "); } else if (!typeDef.IsValueType && !typeDef.IsEnum && (typeDef.flags & TYPE_ATTRIBUTE_SEALED) != 0) { writer.Write("sealed "); } if ((typeDef.flags & TYPE_ATTRIBUTE_INTERFACE) != 0) { writer.Write("interface "); } else if (typeDef.IsEnum) { writer.Write("enum "); } else if (typeDef.IsValueType) { writer.Write("struct "); } else { writer.Write("class "); } var typeName = executor.GetTypeDefName(typeDef, false, true); writer.Write($"{typeName}"); if (extends.Count > 0) { writer.Write($" : {string.Join(", ", extends)}"); } if (config.DumpTypeDefIndex) { writer.Write($" // TypeDefIndex: {typeDefIndex}\n{{"); } else { writer.Write("\n{"); } //dump field if (config.DumpField && typeDef.field_count > 0) { writer.Write("\n\t// Fields\n"); var fieldEnd = typeDef.fieldStart + typeDef.field_count; for (var i = typeDef.fieldStart; i < fieldEnd; ++i) { var fieldDef = metadata.fieldDefs[i]; var fieldType = il2Cpp.types[fieldDef.typeIndex]; var isStatic = false; var isConst = false; if (config.DumpAttribute) { writer.Write(GetCustomAttribute(imageDef, fieldDef.customAttributeIndex, fieldDef.token, "\t")); } writer.Write("\t"); var access = fieldType.attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK; switch (access) { case FIELD_ATTRIBUTE_PRIVATE: writer.Write("private "); break; case FIELD_ATTRIBUTE_PUBLIC: writer.Write("public "); break; case FIELD_ATTRIBUTE_FAMILY: writer.Write("protected "); break; case FIELD_ATTRIBUTE_ASSEMBLY: case FIELD_ATTRIBUTE_FAM_AND_ASSEM: writer.Write("internal "); break; case FIELD_ATTRIBUTE_FAM_OR_ASSEM: writer.Write("protected internal "); break; } if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0) { isConst = true; writer.Write("const "); } else { if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0) { isStatic = true; writer.Write("static "); } if ((fieldType.attrs & FIELD_ATTRIBUTE_INIT_ONLY) != 0) { writer.Write("readonly "); } } writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}"); if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1) { if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value)) { writer.Write($" = "); if (value is string str) { writer.Write($"\"{str.ToEscapedString()}\""); } else if (value is char c) { var v = (int)c; writer.Write($"'\\x{v:x}'"); } else if (value != null) { writer.Write($"{value}"); } } else { writer.Write($" /*Metadata offset 0x{value:X}*/"); } } if (config.DumpFieldOffset && !isConst) { writer.Write("; // 0x{0:X}\n", il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType, isStatic)); } else { writer.Write(";\n"); } } } //dump property if (config.DumpProperty && typeDef.property_count > 0) { writer.Write("\n\t// Properties\n"); var propertyEnd = typeDef.propertyStart + typeDef.property_count; for (var i = typeDef.propertyStart; i < propertyEnd; ++i) { var propertyDef = metadata.propertyDefs[i]; if (config.DumpAttribute) { writer.Write(GetCustomAttribute(imageDef, propertyDef.customAttributeIndex, propertyDef.token, "\t")); } writer.Write("\t"); if (propertyDef.get >= 0) { var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.get]; writer.Write(GetModifiers(methodDef)); var propertyType = il2Cpp.types[methodDef.returnType]; writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ "); } else if (propertyDef.set >= 0) { var methodDef = metadata.methodDefs[typeDef.methodStart + propertyDef.set]; writer.Write(GetModifiers(methodDef)); var parameterDef = metadata.parameterDefs[methodDef.parameterStart]; var propertyType = il2Cpp.types[parameterDef.typeIndex]; writer.Write($"{executor.GetTypeName(propertyType, false, false)} {metadata.GetStringFromIndex(propertyDef.nameIndex)} {{ "); } if (propertyDef.get >= 0) { writer.Write("get; "); } if (propertyDef.set >= 0) { writer.Write("set; "); } writer.Write("}"); writer.Write("\n"); } } //dump method if (config.DumpMethod && typeDef.method_count > 0) { writer.Write("\n\t// Methods\n"); var methodEnd = typeDef.methodStart + typeDef.method_count; for (var i = typeDef.methodStart; i < methodEnd; ++i) { writer.Write("\n"); var methodDef = metadata.methodDefs[i]; if (config.DumpAttribute) { writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t")); } if (config.DumpMethodOffset) { var methodPointer = il2Cpp.GetMethodPointer(imageName, methodDef); if (methodPointer > 0) { var fixedMethodPointer = il2Cpp.GetRVA(methodPointer); writer.Write("\t// RVA: 0x{0:X} Offset: 0x{1:X} VA: 0x{2:X}", fixedMethodPointer, il2Cpp.MapVATR(methodPointer), methodPointer); } else { writer.Write("\t// RVA: -1 Offset: -1"); } if (methodDef.slot != ushort.MaxValue) { writer.Write(" Slot: {0}", methodDef.slot); } writer.Write("\n"); } writer.Write("\t"); writer.Write(GetModifiers(methodDef)); var methodReturnType = il2Cpp.types[methodDef.returnType]; var methodName = metadata.GetStringFromIndex(methodDef.nameIndex); if (methodDef.genericContainerIndex >= 0) { var genericContainer = metadata.genericContainers[methodDef.genericContainerIndex]; methodName += executor.GetGenericContainerParams(genericContainer); } if (methodReturnType.byref == 1) { writer.Write("ref "); } writer.Write($"{executor.GetTypeName(methodReturnType, false, false)} {methodName}("); var parameterStrs = new List <string>(); for (var j = 0; j < methodDef.parameterCount; ++j) { var parameterStr = ""; var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j]; var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex); var parameterType = il2Cpp.types[parameterDef.typeIndex]; var parameterTypeName = executor.GetTypeName(parameterType, false, false); if (parameterType.byref == 1) { if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) == 0) { parameterStr += "out "; } else if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) == 0 && (parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0) { parameterStr += "in "; } else { parameterStr += "ref "; } } else { if ((parameterType.attrs & PARAM_ATTRIBUTE_IN) != 0) { parameterStr += "[In] "; } if ((parameterType.attrs & PARAM_ATTRIBUTE_OUT) != 0) { parameterStr += "[Out] "; } } parameterStr += $"{parameterTypeName} {parameterName}"; if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1) { if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value)) { parameterStr += " = "; if (value is string str) { parameterStr += $"\"{str.ToEscapedString()}\""; } else if (value is char c) { var v = (int)c; parameterStr += $"'\\x{v:x}'"; } else if (value != null) { parameterStr += $"{value}"; } } else { parameterStr += $" /*Metadata offset 0x{value:X}*/"; } } parameterStrs.Add(parameterStr); } writer.Write(string.Join(", ", parameterStrs)); writer.Write(") { }\n"); if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs)) { writer.Write("\t/* GenericInstMethod :\n"); var groups = methodSpecs.GroupBy(x => il2Cpp.methodSpecGenericMethodPointers[x]); foreach (var group in groups) { writer.Write("\t|\n"); var genericMethodPointer = group.Key; if (genericMethodPointer > 0) { var fixedPointer = il2Cpp.GetRVA(genericMethodPointer); writer.Write($"\t|-RVA: 0x{fixedPointer:X} Offset: 0x{il2Cpp.MapVATR(genericMethodPointer):X} VA: 0x{genericMethodPointer:X}\n"); } else { writer.Write("\t|-RVA: -1 Offset: -1\n"); } foreach (var methodSpec in group) { (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec); writer.Write($"\t|-{methodSpecTypeName}.{methodSpecMethodName}\n"); } } writer.Write("\t*/\n"); } } } writer.Write("}\n"); } } catch (Exception e) { FormGUI.Log("ERROR: Some errors in dumping"); writer.Write("/*"); writer.Write(e); writer.Write("*/\n}\n"); } } writer.Close(); }
public override bool Search() { if (Version < 21) { var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func"); var addrs = ReadClassArray <uint>(__mod_init_func.offset, __mod_init_func.size / 4u); 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 + 22u; FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } } } } return(false); } else { var __mod_init_func = sections.First(x => x.sectname == "__mod_init_func"); var addrs = ReadClassArray <uint>(__mod_init_func.offset, __mod_init_func.size / 4u); 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; FormGUI.Log("CodeRegistration : {0:x}", codeRegistration); FormGUI.Log("MetadataRegistration : {0:x}", metadataRegistration); Init(codeRegistration, metadataRegistration); return(true); } } } } return(false); } }