From 217f1d4737cd9d9d16ab5bef355156bcbc44f9e0 Mon Sep 17 00:00:00 2001 From: Perfare Date: Sun, 5 Mar 2023 01:49:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Il2CppDumper/ExecutableFormats/Macho.cs | 4 +- Il2CppDumper/ExecutableFormats/Macho64.cs | 4 +- Il2CppDumper/ExecutableFormats/MachoFat.cs | 14 +-- Il2CppDumper/ExecutableFormats/NSO.cs | 28 ++--- Il2CppDumper/ExecutableFormats/PE.cs | 2 +- Il2CppDumper/ExecutableFormats/WebAssembly.cs | 4 +- .../ExecutableFormats/WebAssemblyMemory.cs | 2 +- .../Extensions/BinaryReaderExtensions.cs | 2 +- Il2CppDumper/IO/BinaryStream.cs | 50 ++++---- Il2CppDumper/Il2Cpp/Il2Cpp.cs | 6 +- Il2CppDumper/Il2Cpp/Metadata.cs | 31 +++-- Il2CppDumper/Outputs/DummyAssemblyExporter.cs | 8 +- Il2CppDumper/Outputs/Il2CppDecompiler.cs | 11 +- Il2CppDumper/Outputs/ScriptJson.cs | 8 +- Il2CppDumper/Outputs/StructGenerator.cs | 97 ++++++---------- Il2CppDumper/Outputs/StructInfo.cs | 6 +- Il2CppDumper/Program.cs | 11 +- Il2CppDumper/Utils/ArmUtils.cs | 4 +- .../Utils/CustomAttributeDataReader.cs | 6 +- Il2CppDumper/Utils/DummyAssemblyGenerator.cs | 49 ++++---- Il2CppDumper/Utils/Il2CppExecutor.cs | 12 +- Il2CppDumper/Utils/PELoader.cs | 109 +++++++++--------- Il2CppDumper/Utils/SectionHelper.cs | 10 +- 23 files changed, 219 insertions(+), 259 deletions(-) diff --git a/Il2CppDumper/ExecutableFormats/Macho.cs b/Il2CppDumper/ExecutableFormats/Macho.cs index e0e77da..0b56b9a 100644 --- a/Il2CppDumper/ExecutableFormats/Macho.cs +++ b/Il2CppDumper/ExecutableFormats/Macho.cs @@ -9,10 +9,10 @@ namespace Il2CppDumper { public sealed class Macho : Il2Cpp { - private List sections = new List(); private static readonly byte[] FeatureBytes1 = { 0x0, 0x22 };//MOVS R2, #0 private static readonly byte[] FeatureBytes2 = { 0x78, 0x44, 0x79, 0x44 };//ADD R0, PC and ADD R1, PC - private ulong vmaddr; + private readonly List sections = new(); + private readonly ulong vmaddr; public Macho(Stream stream) : base(stream) { diff --git a/Il2CppDumper/ExecutableFormats/Macho64.cs b/Il2CppDumper/ExecutableFormats/Macho64.cs index 1008ef1..451ba3c 100644 --- a/Il2CppDumper/ExecutableFormats/Macho64.cs +++ b/Il2CppDumper/ExecutableFormats/Macho64.cs @@ -9,10 +9,10 @@ namespace Il2CppDumper { public sealed class Macho64 : Il2Cpp { - private List sections = new List(); private static readonly byte[] FeatureBytes1 = { 0x2, 0x0, 0x80, 0xD2 };//MOV X2, #0 private static readonly byte[] FeatureBytes2 = { 0x3, 0x0, 0x80, 0x52 };//MOV W3, #0 - private ulong vmaddr; + private readonly List sections = new(); + private readonly ulong vmaddr; public Macho64(Stream stream) : base(stream) { diff --git a/Il2CppDumper/ExecutableFormats/MachoFat.cs b/Il2CppDumper/ExecutableFormats/MachoFat.cs index 261d465..1162bb1 100644 --- a/Il2CppDumper/ExecutableFormats/MachoFat.cs +++ b/Il2CppDumper/ExecutableFormats/MachoFat.cs @@ -1,6 +1,5 @@ -using System; +using System.Buffers.Binary; using System.IO; -using System.Linq; namespace Il2CppDumper { @@ -10,16 +9,17 @@ namespace Il2CppDumper public MachoFat(Stream stream) : base(stream) { - //BigEndian Position += 4; - var size = BitConverter.ToInt32(ReadBytes(4).Reverse().ToArray(), 0); + var size = BinaryPrimitives.ReadInt32BigEndian(ReadBytes(4)); fats = new Fat[size]; for (var i = 0; i < size; i++) { Position += 8; - fats[i] = new Fat(); - fats[i].offset = BitConverter.ToUInt32(ReadBytes(4).Reverse().ToArray(), 0); - fats[i].size = BitConverter.ToUInt32(ReadBytes(4).Reverse().ToArray(), 0); + fats[i] = new Fat + { + offset = BinaryPrimitives.ReadUInt32BigEndian(ReadBytes(4)), + size = BinaryPrimitives.ReadUInt32BigEndian(ReadBytes(4)) + }; Position += 4; } for (var i = 0; i < size; i++) diff --git a/Il2CppDumper/ExecutableFormats/NSO.cs b/Il2CppDumper/ExecutableFormats/NSO.cs index 3ab0af7..4d964d8 100644 --- a/Il2CppDumper/ExecutableFormats/NSO.cs +++ b/Il2CppDumper/ExecutableFormats/NSO.cs @@ -8,23 +8,25 @@ namespace Il2CppDumper { public sealed class NSO : Il2Cpp { - private NSOHeader header; - private bool isTextCompressed; - private bool isRoDataCompressed; - private bool isDataCompressed; - private List segments = new List(); + private readonly NSOHeader header; + private readonly bool isTextCompressed; + private readonly bool isRoDataCompressed; + private readonly bool isDataCompressed; + private readonly List segments = new(); private Elf64_Sym[] symbolTable; - private List dynamicSection = new List(); - private bool isCompressed => isTextCompressed || isRoDataCompressed || isDataCompressed; + private readonly List dynamicSection = new(); + private bool IsCompressed => isTextCompressed || isRoDataCompressed || isDataCompressed; public NSO(Stream stream) : base(stream) { - header = new NSOHeader(); - header.Magic = ReadUInt32(); - header.Version = ReadUInt32(); - header.Reserved = ReadUInt32(); - header.Flags = ReadUInt32(); + header = new NSOHeader + { + Magic = ReadUInt32(), + Version = ReadUInt32(), + Reserved = ReadUInt32(), + Flags = ReadUInt32() + }; isTextCompressed = (header.Flags & 1) != 0; isRoDataCompressed = (header.Flags & 2) != 0; isDataCompressed = (header.Flags & 4) != 0; @@ -76,7 +78,7 @@ namespace Il2CppDumper header.RoDataHash = ReadBytes(0x20); header.DataHash = ReadBytes(0x20); - if (!isCompressed) + if (!IsCompressed) { Position = header.TextSegment.FileOffset + 4; var modOffset = ReadUInt32(); diff --git a/Il2CppDumper/ExecutableFormats/PE.cs b/Il2CppDumper/ExecutableFormats/PE.cs index 384bfa8..de52fc9 100644 --- a/Il2CppDumper/ExecutableFormats/PE.cs +++ b/Il2CppDumper/ExecutableFormats/PE.cs @@ -7,7 +7,7 @@ namespace Il2CppDumper { public sealed class PE : Il2Cpp { - private SectionHeader[] sections; + private readonly SectionHeader[] sections; public PE(Stream stream) : base(stream) { diff --git a/Il2CppDumper/ExecutableFormats/WebAssembly.cs b/Il2CppDumper/ExecutableFormats/WebAssembly.cs index eee93da..32e105c 100644 --- a/Il2CppDumper/ExecutableFormats/WebAssembly.cs +++ b/Il2CppDumper/ExecutableFormats/WebAssembly.cs @@ -5,7 +5,7 @@ namespace Il2CppDumper { public sealed class WebAssembly : BinaryStream { - private DataSection[] dataSections; + private readonly DataSection[] dataSections; public WebAssembly(Stream stream) : base(stream) { @@ -46,7 +46,7 @@ namespace Il2CppDumper public WebAssemblyMemory CreateMemory() { - var last = dataSections[dataSections.Length - 1]; + var last = dataSections[^1]; var bssStart = last.Offset + (uint)last.Data.Length; var stream = new MemoryStream(new byte[Length]); foreach (var dataSection in dataSections) diff --git a/Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs b/Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs index dfb2b72..6333e38 100644 --- a/Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs +++ b/Il2CppDumper/ExecutableFormats/WebAssemblyMemory.cs @@ -4,7 +4,7 @@ namespace Il2CppDumper { public sealed class WebAssemblyMemory : Il2Cpp { - private uint bssStart; + private readonly uint bssStart; public WebAssemblyMemory(Stream stream, uint bssStart) : base(stream) { diff --git a/Il2CppDumper/Extensions/BinaryReaderExtensions.cs b/Il2CppDumper/Extensions/BinaryReaderExtensions.cs index 7fab586..b044cad 100644 --- a/Il2CppDumper/Extensions/BinaryReaderExtensions.cs +++ b/Il2CppDumper/Extensions/BinaryReaderExtensions.cs @@ -10,7 +10,7 @@ namespace Il2CppDumper { var start = reader.BaseStream.Position; // UTF8 takes up to 4 bytes per character - var str = Encoding.UTF8.GetString(reader.ReadBytes(numChars * 4)).Substring(0, numChars); + var str = Encoding.UTF8.GetString(reader.ReadBytes(numChars * 4))[..numChars]; // make our position what it would have been if we'd known the exact number of bytes needed. reader.BaseStream.Position = start; reader.ReadBytes(Encoding.UTF8.GetByteCount(str)); diff --git a/Il2CppDumper/IO/BinaryStream.cs b/Il2CppDumper/IO/BinaryStream.cs index a9ac94a..043a65b 100644 --- a/Il2CppDumper/IO/BinaryStream.cs +++ b/Il2CppDumper/IO/BinaryStream.cs @@ -12,13 +12,13 @@ namespace Il2CppDumper public double Version; public bool Is32Bit; public ulong ImageBase; - private Stream stream; - private BinaryReader reader; - private BinaryWriter writer; - private MethodInfo readClass; - private MethodInfo readClassArray; - private Dictionary genericMethodCache = new Dictionary(); - private Dictionary attributeCache = new Dictionary(); + private readonly Stream stream; + private readonly BinaryReader reader; + private readonly BinaryWriter writer; + private readonly MethodInfo readClass; + private readonly MethodInfo readClassArray; + private readonly Dictionary genericMethodCache; + private readonly Dictionary attributeCache; public BinaryStream(Stream input) { @@ -27,6 +27,8 @@ namespace Il2CppDumper writer = new BinaryWriter(stream, Encoding.UTF8, true); readClass = GetType().GetMethod("ReadClass", Type.EmptyTypes); readClassArray = GetType().GetMethod("ReadClassArray", new[] { typeof(long) }); + genericMethodCache = new(); + attributeCache = new(); } public bool ReadBoolean() => reader.ReadBoolean(); @@ -91,26 +93,17 @@ namespace Il2CppDumper private object ReadPrimitive(Type type) { - var typename = type.Name; - switch (typename) + return type.Name switch { - case "Int32": - return ReadInt32(); - case "UInt32": - return ReadUInt32(); - case "Int16": - return ReadInt16(); - case "UInt16": - return ReadUInt16(); - case "Byte": - return ReadByte(); - case "Int64": - return ReadIntPtr(); - case "UInt64": - return ReadUIntPtr(); - default: - throw new NotSupportedException(); - } + "Int32" => ReadInt32(), + "UInt32" => ReadUInt32(), + "Int16" => ReadInt16(), + "UInt16" => ReadUInt16(), + "Byte" => ReadByte(), + "Int64" => ReadIntPtr(), + "UInt64" => ReadUIntPtr(), + _ => throw new NotSupportedException() + }; } public T ReadClass(ulong addr) where T : new() @@ -243,8 +236,8 @@ namespace Il2CppDumper { if (disposing) { - reader.Close(); - writer.Close(); + reader.Dispose(); + writer.Dispose(); stream.Close(); } } @@ -252,6 +245,7 @@ namespace Il2CppDumper public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } } } diff --git a/Il2CppDumper/Il2Cpp/Il2Cpp.cs b/Il2CppDumper/Il2Cpp/Il2Cpp.cs index f1ba9d9..ad66583 100644 --- a/Il2CppDumper/Il2Cpp/Il2Cpp.cs +++ b/Il2CppDumper/Il2Cpp/Il2Cpp.cs @@ -17,14 +17,14 @@ namespace Il2CppDumper public ulong[] unresolvedVirtualCallPointers; private ulong[] fieldOffsets; public Il2CppType[] types; - private Dictionary typeDic = new Dictionary(); + private readonly Dictionary typeDic = new(); public ulong[] metadataUsages; private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable; public ulong[] genericInstPointers; public Il2CppGenericInst[] genericInsts; public Il2CppMethodSpec[] methodSpecs; - public Dictionary> methodDefinitionMethodSpecs = new Dictionary>(); - public Dictionary methodSpecGenericMethodPointers = new Dictionary(); + public Dictionary> methodDefinitionMethodSpecs = new(); + public Dictionary methodSpecGenericMethodPointers = new(); private bool fieldOffsetsArePointers; protected long metadataUsagesCount; public Dictionary codeGenModules; diff --git a/Il2CppDumper/Il2Cpp/Metadata.cs b/Il2CppDumper/Il2Cpp/Metadata.cs index c30e720..9cb4627 100644 --- a/Il2CppDumper/Il2Cpp/Metadata.cs +++ b/Il2CppDumper/Il2Cpp/Metadata.cs @@ -16,15 +16,15 @@ namespace Il2CppDumper public Il2CppMethodDefinition[] methodDefs; public Il2CppParameterDefinition[] parameterDefs; public Il2CppFieldDefinition[] fieldDefs; - private Dictionary fieldDefaultValuesDic; - private Dictionary parameterDefaultValuesDic; + private readonly Dictionary fieldDefaultValuesDic; + private readonly Dictionary parameterDefaultValuesDic; public Il2CppPropertyDefinition[] propertyDefs; public Il2CppCustomAttributeTypeRange[] attributeTypeRanges; public Il2CppCustomAttributeDataRange[] attributeDataRanges; - private Dictionary> attributeTypeRangesDic; + private readonly Dictionary> attributeTypeRangesDic; public Il2CppStringLiteral[] stringLiterals; - private Il2CppMetadataUsageList[] metadataUsageLists; - private Il2CppMetadataUsagePair[] metadataUsagePairs; + private readonly Il2CppMetadataUsageList[] metadataUsageLists; + private readonly Il2CppMetadataUsagePair[] metadataUsagePairs; public int[] attributeTypes; public int[] interfaceIndices; public Dictionary> metadataUsageDic; @@ -38,7 +38,7 @@ namespace Il2CppDumper public uint[] vtableMethods; public Il2CppRGCTXDefinition[] rgctxEntries; - private Dictionary stringCache = new Dictionary(); + private readonly Dictionary stringCache = new(); public Metadata(Stream stream) : base(stream) { @@ -239,7 +239,7 @@ namespace Il2CppDumper metadataUsagesCount = metadataUsageDic.Max(x => x.Value.Select(y => y.Key).DefaultIfEmpty().Max()) + 1; } - public uint GetEncodedIndexType(uint index) + public static uint GetEncodedIndexType(uint index) { return (index & 0xE0000000) >> 29; } @@ -286,19 +286,14 @@ namespace Il2CppDumper } return size; - int GetPrimitiveTypeSize(string name) + static int GetPrimitiveTypeSize(string name) { - switch (name) + return name switch { - case "Int32": - case "UInt32": - return 4; - case "Int16": - case "UInt16": - return 2; - default: - return 0; - } + "Int32" or "UInt32" => 4, + "Int16" or "UInt16" => 2, + _ => 0, + }; } } } diff --git a/Il2CppDumper/Outputs/DummyAssemblyExporter.cs b/Il2CppDumper/Outputs/DummyAssemblyExporter.cs index ae2b1e6..883ff42 100644 --- a/Il2CppDumper/Outputs/DummyAssemblyExporter.cs +++ b/Il2CppDumper/Outputs/DummyAssemblyExporter.cs @@ -14,11 +14,9 @@ namespace Il2CppDumper var dummy = new DummyAssemblyGenerator(il2CppExecutor, addToken); foreach (var assembly in dummy.Assemblies) { - using (var stream = new MemoryStream()) - { - assembly.Write(stream); - File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray()); - } + using var stream = new MemoryStream(); + assembly.Write(stream); + File.WriteAllBytes(assembly.MainModule.Name, stream.ToArray()); } } } diff --git a/Il2CppDumper/Outputs/Il2CppDecompiler.cs b/Il2CppDumper/Outputs/Il2CppDecompiler.cs index ce36fd2..a3cfe3d 100644 --- a/Il2CppDumper/Outputs/Il2CppDecompiler.cs +++ b/Il2CppDumper/Outputs/Il2CppDecompiler.cs @@ -9,16 +9,17 @@ namespace Il2CppDumper { public class Il2CppDecompiler { - private Il2CppExecutor executor; - private Metadata metadata; - private Il2Cpp il2Cpp; - private Dictionary methodModifiers = new Dictionary(); + private readonly Il2CppExecutor executor; + private readonly Metadata metadata; + private readonly Il2Cpp il2Cpp; + private readonly Dictionary methodModifiers; public Il2CppDecompiler(Il2CppExecutor il2CppExecutor) { executor = il2CppExecutor; metadata = il2CppExecutor.metadata; il2Cpp = il2CppExecutor.il2Cpp; + methodModifiers = new(); } public void Decompile(Config config, string outputDir) @@ -436,7 +437,7 @@ namespace Il2CppDumper { sb.Append(padding); sb.Append(reader.GetStringCustomAttributeData()); - sb.Append("\n"); + sb.Append('\n'); } return sb.ToString(); } diff --git a/Il2CppDumper/Outputs/ScriptJson.cs b/Il2CppDumper/Outputs/ScriptJson.cs index 04cb992..e91cd6b 100644 --- a/Il2CppDumper/Outputs/ScriptJson.cs +++ b/Il2CppDumper/Outputs/ScriptJson.cs @@ -4,10 +4,10 @@ namespace Il2CppDumper { public class ScriptJson { - public List ScriptMethod = new List(); - public List ScriptString = new List(); - public List ScriptMetadata = new List(); - public List ScriptMetadataMethod = new List(); + public List ScriptMethod = new(); + public List ScriptString = new(); + public List ScriptMetadata = new(); + public List ScriptMetadataMethod = new(); public ulong[] Addresses; } diff --git a/Il2CppDumper/Outputs/StructGenerator.cs b/Il2CppDumper/Outputs/StructGenerator.cs index 831e7a6..9c2189d 100644 --- a/Il2CppDumper/Outputs/StructGenerator.cs +++ b/Il2CppDumper/Outputs/StructGenerator.cs @@ -11,25 +11,25 @@ namespace Il2CppDumper { public class StructGenerator { - private Il2CppExecutor executor; - private Metadata metadata; - private Il2Cpp il2Cpp; - private Dictionary typeDefImageNames = new Dictionary(); - private HashSet structNameHashSet = new HashSet(StringComparer.Ordinal); - private List structInfoList = new List(); - private Dictionary structInfoWithStructName = new Dictionary(); - private HashSet structCache = new HashSet(); - private Dictionary structNameDic = new Dictionary(); - private Dictionary genericClassStructNameDic = new Dictionary(); - private Dictionary nameGenericClassDic = new Dictionary(); - private List genericClassList = new List(); - private StringBuilder arrayClassHeader = new StringBuilder(); - private StringBuilder methodInfoHeader = new StringBuilder(); - private static HashSet methodInfoCache = new HashSet(); - private static HashSet keyword = new HashSet(StringComparer.Ordinal) + private readonly Il2CppExecutor executor; + private readonly Metadata metadata; + private readonly Il2Cpp il2Cpp; + private readonly Dictionary typeDefImageNames = new(); + private readonly HashSet structNameHashSet = new(StringComparer.Ordinal); + private readonly List structInfoList = new(); + private readonly Dictionary structInfoWithStructName = new(); + private readonly HashSet structCache = new(); + private readonly Dictionary structNameDic = new(); + private readonly Dictionary genericClassStructNameDic = new(); + private readonly Dictionary nameGenericClassDic = new(); + private readonly List genericClassList = new(); + private readonly StringBuilder arrayClassHeader = new(); + private readonly StringBuilder methodInfoHeader = new(); + private static readonly HashSet methodInfoCache = new(); + private static readonly HashSet keyword = new(StringComparer.Ordinal) { "klass", "monitor", "register", "_cs", "auto", "friend", "template", "flat", "default", "_ds", "interrupt", "unsigned", "signed", "asm", "if", "case", "break", "continue", "do", "new", "_", "short", "union", "class", "namespace"}; - private static HashSet specialKeywords = new HashSet(StringComparer.Ordinal) + private static readonly HashSet specialKeywords = new(StringComparer.Ordinal) { "inline", "near", "far" }; public StructGenerator(Il2CppExecutor il2CppExecutor) @@ -278,7 +278,7 @@ namespace Il2CppDumper if (metadataValue < uint.MaxValue) { var encodedToken = (uint)metadataValue; - var usage = metadata.GetEncodedIndexType(encodedToken); + var usage = Metadata.GetEncodedIndexType(encodedToken); if (usage > 0 && usage <= 6) { var decodedIndex = metadata.GetDecodedMethodIndex(encodedToken); @@ -674,54 +674,21 @@ namespace Il2CppDumper throw new NotSupportedException(); } } - public string GetMethodTypeSignature(List types) + public static string GetMethodTypeSignature(List types) { string signature = string.Empty; foreach (Il2CppTypeEnum type in types) { - switch (type) + signature += type switch { - case Il2CppTypeEnum.IL2CPP_TYPE_VOID: - signature += "v"; - break; - case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN: - case Il2CppTypeEnum.IL2CPP_TYPE_CHAR: - case Il2CppTypeEnum.IL2CPP_TYPE_I1: - case Il2CppTypeEnum.IL2CPP_TYPE_U1: - case Il2CppTypeEnum.IL2CPP_TYPE_I2: - case Il2CppTypeEnum.IL2CPP_TYPE_U2: - case Il2CppTypeEnum.IL2CPP_TYPE_I4: - case Il2CppTypeEnum.IL2CPP_TYPE_U4: - signature += "i"; - break; - case Il2CppTypeEnum.IL2CPP_TYPE_I8: - case Il2CppTypeEnum.IL2CPP_TYPE_U8: - signature += "j"; - break; - case Il2CppTypeEnum.IL2CPP_TYPE_R4: - signature += "f"; - break; - case Il2CppTypeEnum.IL2CPP_TYPE_R8: - signature += "d"; - break; - case Il2CppTypeEnum.IL2CPP_TYPE_STRING: - case Il2CppTypeEnum.IL2CPP_TYPE_PTR: - case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: - case Il2CppTypeEnum.IL2CPP_TYPE_CLASS: - case Il2CppTypeEnum.IL2CPP_TYPE_VAR: - case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: - case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: - case Il2CppTypeEnum.IL2CPP_TYPE_TYPEDBYREF: - case Il2CppTypeEnum.IL2CPP_TYPE_I: - case Il2CppTypeEnum.IL2CPP_TYPE_U: - case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT: - case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: - case Il2CppTypeEnum.IL2CPP_TYPE_MVAR: - signature += "i"; - break; - default: - throw new NotSupportedException(); - } + Il2CppTypeEnum.IL2CPP_TYPE_VOID => "v", + Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN or Il2CppTypeEnum.IL2CPP_TYPE_CHAR or Il2CppTypeEnum.IL2CPP_TYPE_I1 or Il2CppTypeEnum.IL2CPP_TYPE_U1 or Il2CppTypeEnum.IL2CPP_TYPE_I2 or Il2CppTypeEnum.IL2CPP_TYPE_U2 or Il2CppTypeEnum.IL2CPP_TYPE_I4 or Il2CppTypeEnum.IL2CPP_TYPE_U4 => "i", + Il2CppTypeEnum.IL2CPP_TYPE_I8 or Il2CppTypeEnum.IL2CPP_TYPE_U8 => "j", + Il2CppTypeEnum.IL2CPP_TYPE_R4 => "f", + Il2CppTypeEnum.IL2CPP_TYPE_R8 => "d", + Il2CppTypeEnum.IL2CPP_TYPE_STRING or Il2CppTypeEnum.IL2CPP_TYPE_PTR or Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE or Il2CppTypeEnum.IL2CPP_TYPE_CLASS or Il2CppTypeEnum.IL2CPP_TYPE_VAR or Il2CppTypeEnum.IL2CPP_TYPE_ARRAY or Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST or Il2CppTypeEnum.IL2CPP_TYPE_TYPEDBYREF or Il2CppTypeEnum.IL2CPP_TYPE_I or Il2CppTypeEnum.IL2CPP_TYPE_U or Il2CppTypeEnum.IL2CPP_TYPE_OBJECT or Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY or Il2CppTypeEnum.IL2CPP_TYPE_MVAR => "i", + _ => throw new NotSupportedException(), + }; } return signature; } @@ -780,8 +747,10 @@ namespace Il2CppDumper { continue; } - var structFieldInfo = new StructFieldInfo(); - structFieldInfo.FieldTypeName = ParseType(fieldType, context); + var structFieldInfo = new StructFieldInfo + { + FieldTypeName = ParseType(fieldType, context) + }; var fieldName = FixName(metadata.GetStringFromIndex(fieldDef.nameIndex)); if (!cache.Add(fieldName)) { @@ -809,7 +778,7 @@ namespace Il2CppDumper { var vTableIndex = typeDef.vtableStart + i; var encodedMethodIndex = metadata.vtableMethods[vTableIndex]; - var usage = metadata.GetEncodedIndexType(encodedMethodIndex); + var usage = Metadata.GetEncodedIndexType(encodedMethodIndex); var index = metadata.GetDecodedMethodIndex(encodedMethodIndex); Il2CppMethodDefinition methodDef; if (usage == 6) //kIl2CppMetadataUsageMethodRef diff --git a/Il2CppDumper/Outputs/StructInfo.cs b/Il2CppDumper/Outputs/StructInfo.cs index 651c2c8..422531e 100644 --- a/Il2CppDumper/Outputs/StructInfo.cs +++ b/Il2CppDumper/Outputs/StructInfo.cs @@ -8,10 +8,10 @@ namespace Il2CppDumper public string TypeName; public bool IsValueType; public string Parent; - public List Fields = new List(); - public List StaticFields = new List(); + public List Fields = new(); + public List StaticFields = new(); public StructVTableMethodInfo[] VTableMethod = Array.Empty(); - public List RGCTXs = new List(); + public List RGCTXs = new(); } public class StructFieldInfo diff --git a/Il2CppDumper/Program.cs b/Il2CppDumper/Program.cs index 03362f2..e09ab83 100644 --- a/Il2CppDumper/Program.cs +++ b/Il2CppDumper/Program.cs @@ -53,16 +53,15 @@ namespace Il2CppDumper } } } - if (outputDir == null) - { - outputDir = AppDomain.CurrentDomain.BaseDirectory; - } + outputDir ??= AppDomain.CurrentDomain.BaseDirectory; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (il2cppPath == null) { - var ofd = new OpenFileDialog(); - ofd.Filter = "Il2Cpp binary file|*.*"; + var ofd = new OpenFileDialog + { + Filter = "Il2Cpp binary file|*.*" + }; if (ofd.ShowDialog()) { il2cppPath = ofd.FileName; diff --git a/Il2CppDumper/Utils/ArmUtils.cs b/Il2CppDumper/Utils/ArmUtils.cs index 027cefd..b1d4619 100644 --- a/Il2CppDumper/Utils/ArmUtils.cs +++ b/Il2CppDumper/Utils/ArmUtils.cs @@ -14,7 +14,7 @@ namespace Il2CppDumper public static ulong DecodeAdr(ulong pc, byte[] inst) { var bin = inst.HexToBin(); - var uint64 = bin.Substring(8, 19) + bin.Substring(1, 2); + var uint64 = string.Concat(bin.AsSpan(8, 19), bin.AsSpan(1, 2)); uint64 = uint64.PadLeft(64, uint64[0]); return pc + Convert.ToUInt64(uint64, 2); } @@ -23,7 +23,7 @@ namespace Il2CppDumper { pc &= 0xFFFFFFFFFFFFF000; var bin = inst.HexToBin(); - var uint64 = bin.Substring(8, 19) + bin.Substring(1, 2) + new string('0', 12); + var uint64 = string.Concat(bin.AsSpan(8, 19), bin.AsSpan(1, 2), new string('0', 12)); uint64 = uint64.PadLeft(64, uint64[0]); return pc + Convert.ToUInt64(uint64, 2); } diff --git a/Il2CppDumper/Utils/CustomAttributeDataReader.cs b/Il2CppDumper/Utils/CustomAttributeDataReader.cs index f889496..75850f3 100644 --- a/Il2CppDumper/Utils/CustomAttributeDataReader.cs +++ b/Il2CppDumper/Utils/CustomAttributeDataReader.cs @@ -5,9 +5,8 @@ namespace Il2CppDumper { public class CustomAttributeDataReader : BinaryReader { - private Il2CppExecutor executor; - private Metadata metadata; - private Il2Cpp il2Cpp; + private readonly Il2CppExecutor executor; + private readonly Metadata metadata; private long ctorBuffer; private long dataBuffer; @@ -17,7 +16,6 @@ namespace Il2CppDumper { this.executor = executor; metadata = executor.metadata; - il2Cpp = executor.il2Cpp; Count = this.ReadCompressedUInt32(); ctorBuffer = BaseStream.Position; dataBuffer = BaseStream.Position + Count * 4; diff --git a/Il2CppDumper/Utils/DummyAssemblyGenerator.cs b/Il2CppDumper/Utils/DummyAssemblyGenerator.cs index e5f037a..1c47210 100644 --- a/Il2CppDumper/Utils/DummyAssemblyGenerator.cs +++ b/Il2CppDumper/Utils/DummyAssemblyGenerator.cs @@ -10,19 +10,19 @@ namespace Il2CppDumper { public class DummyAssemblyGenerator { - public List Assemblies = new List(); + public List Assemblies = new(); - private Il2CppExecutor executor; - private Metadata metadata; - private Il2Cpp il2Cpp; - private Dictionary typeDefinitionDic = new Dictionary(); - private Dictionary genericParameterDic = new Dictionary(); - private MethodDefinition attributeAttribute; - private TypeReference stringType; - private TypeSystem typeSystem; - private Dictionary fieldDefinitionDic = new Dictionary(); - private Dictionary propertyDefinitionDic = new Dictionary(); - private Dictionary methodDefinitionDic = new Dictionary(); + private readonly Il2CppExecutor executor; + private readonly Metadata metadata; + private readonly Il2Cpp il2Cpp; + private readonly Dictionary typeDefinitionDic = new(); + private readonly Dictionary genericParameterDic = new(); + private readonly MethodDefinition attributeAttribute; + private readonly TypeReference stringType; + private readonly TypeSystem typeSystem; + private readonly Dictionary fieldDefinitionDic = new(); + private readonly Dictionary propertyDefinitionDic = new(); + private readonly Dictionary methodDefinitionDic = new(); public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor, bool addToken) { @@ -221,8 +221,10 @@ namespace Il2CppDumper { var methodDef = metadata.methodDefs[i]; var methodName = metadata.GetStringFromIndex(methodDef.nameIndex); - var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.ImportReference(typeSystem.Void)); - methodDefinition.ImplAttributes = (MethodImplAttributes)methodDef.iflags; + var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags, typeDefinition.Module.ImportReference(typeSystem.Void)) + { + ImplAttributes = (MethodImplAttributes)methodDef.iflags + }; typeDefinition.Methods.Add(methodDefinition); //genericParameter if (methodDef.genericContainerIndex >= 0) @@ -336,8 +338,7 @@ namespace Il2CppDumper if (propertyDef.set >= 0) { SetMethod = methodDefinitionDic[typeDef.methodStart + propertyDef.set]; - if (propertyType == null) - propertyType = SetMethod.Parameters[0].ParameterType; + propertyType ??= SetMethod.Parameters[0].ParameterType; } var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType) { @@ -554,7 +555,7 @@ namespace Il2CppDumper return new PointerType(GetTypeReference(memberReference, oriType)); } default: - throw new ArgumentOutOfRangeException(); + throw new NotSupportedException(); } } @@ -635,7 +636,7 @@ namespace Il2CppDumper } } - private bool TryRestoreCustomAttribute(TypeDefinition attributeType, ModuleDefinition moduleDefinition, Collection customAttributes) + private static bool TryRestoreCustomAttribute(TypeDefinition attributeType, ModuleDefinition moduleDefinition, Collection customAttributes) { if (attributeType.Methods.Count == 1 && attributeType.Name != "CompilerGeneratedAttribute") { @@ -655,8 +656,10 @@ namespace Il2CppDumper if (!genericParameterDic.TryGetValue(param, out var genericParameter)) { var genericName = metadata.GetStringFromIndex(param.nameIndex); - genericParameter = new GenericParameter(genericName, iGenericParameterProvider); - genericParameter.Attributes = (GenericParameterAttributes)param.flags; + genericParameter = new GenericParameter(genericName, iGenericParameterProvider) + { + Attributes = (GenericParameterAttributes)param.flags + }; genericParameterDic.Add(param, genericParameter); for (int i = 0; i < param.constraintsCount; ++i) { @@ -709,8 +712,10 @@ namespace Il2CppDumper { return GetTypeReference(memberReference, blobValue.EnumType); } - var il2CppType = new Il2CppType(); - il2CppType.type = blobValue.il2CppTypeEnum; + var il2CppType = new Il2CppType + { + type = blobValue.il2CppTypeEnum + }; return GetTypeReference(memberReference, il2CppType); } } diff --git a/Il2CppDumper/Utils/Il2CppExecutor.cs b/Il2CppDumper/Utils/Il2CppExecutor.cs index 29cbace..1b9405b 100644 --- a/Il2CppDumper/Utils/Il2CppExecutor.cs +++ b/Il2CppDumper/Utils/Il2CppExecutor.cs @@ -10,7 +10,7 @@ namespace Il2CppDumper { public Metadata metadata; public Il2Cpp il2Cpp; - private static readonly Dictionary TypeString = new Dictionary + private static readonly Dictionary TypeString = new() { {1,"void"}, {2,"bool"}, @@ -118,7 +118,7 @@ namespace Il2CppDumper var index = typeName.IndexOf("`"); if (index != -1) { - str += typeName.Substring(0, index); + str += typeName[..index]; } else { @@ -167,7 +167,7 @@ namespace Il2CppDumper var index = typeName.IndexOf("`"); if (index != -1) { - typeName = typeName.Substring(0, index); + typeName = typeName[..index]; } if (genericParameter) { @@ -342,8 +342,10 @@ namespace Il2CppDumper public bool GetConstantValueFromBlob(Il2CppTypeEnum type, BinaryReader reader, out BlobValue value) { - value = new BlobValue(); - value.il2CppTypeEnum = type; + value = new BlobValue + { + il2CppTypeEnum = type + }; switch (type) { case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN: diff --git a/Il2CppDumper/Utils/PELoader.cs b/Il2CppDumper/Utils/PELoader.cs index d021fa1..e76b19c 100644 --- a/Il2CppDumper/Utils/PELoader.cs +++ b/Il2CppDumper/Utils/PELoader.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel; using System.IO; -using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -9,68 +8,66 @@ namespace Il2CppDumper { public class PELoader { - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private extern static IntPtr LoadLibrary(string path); public static PE Load(string fileName) { var buff = File.ReadAllBytes(fileName); - using (var reader = new BinaryStream(new MemoryStream(buff))) + using var reader = new BinaryStream(new MemoryStream(buff)); + var dosHeader = reader.ReadClass(); + if (dosHeader.Magic != 0x5A4D) { - var dosHeader = reader.ReadClass(); - if (dosHeader.Magic != 0x5A4D) - { - throw new InvalidDataException("ERROR: Invalid PE file"); - } - reader.Position = dosHeader.Lfanew; - if (reader.ReadUInt32() != 0x4550u) //Signature - { - throw new InvalidDataException("ERROR: Invalid PE file"); - } - var fileHeader = reader.ReadClass(); - if (fileHeader.Machine == 0x14c && Environment.Is64BitProcess) //64bit process can't load 32bit dll - { - throw new InvalidOperationException("The file is a 32-bit file, please try to load it with Il2CppDumper-x86.exe"); - } - if (fileHeader.Machine == 0x8664 && !Environment.Is64BitProcess) //32bit process can't load 64bit dll - { - throw new InvalidOperationException("The file is a 64-bit file, please try to load it with Il2CppDumper.exe"); - } - var pos = reader.Position; - reader.Position = pos + fileHeader.SizeOfOptionalHeader; - var sections = reader.ReadClassArray(fileHeader.NumberOfSections); - var last = sections.Last(); - var size = last.VirtualAddress + last.VirtualSize; - var peBuff = new byte[size]; - var handle = LoadLibrary(fileName); - if (handle == IntPtr.Zero) - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } - foreach (var section in sections) - { - switch (section.Characteristics) - { - case 0x60000020: - case 0x40000040: - case 0xC0000040: - Marshal.Copy(new IntPtr(handle.ToInt64() + section.VirtualAddress), peBuff, (int)section.VirtualAddress, (int)section.VirtualSize); - break; - } - } - var peMemory = new MemoryStream(peBuff); - var writer = new BinaryWriter(peMemory, Encoding.UTF8, true); - var headerSize = reader.Position; - reader.Position = 0; - var buff2 = reader.ReadBytes((int)headerSize); - writer.Write(buff2); - writer.Flush(); - writer.Close(); - peMemory.Position = 0; - var pe = new PE(peMemory); - pe.LoadFromMemory((ulong)handle.ToInt64()); - return pe; + throw new InvalidDataException("ERROR: Invalid PE file"); } + reader.Position = dosHeader.Lfanew; + if (reader.ReadUInt32() != 0x4550u) //Signature + { + throw new InvalidDataException("ERROR: Invalid PE file"); + } + var fileHeader = reader.ReadClass(); + if (fileHeader.Machine == 0x14c && Environment.Is64BitProcess) //64bit process can't load 32bit dll + { + throw new InvalidOperationException("The file is a 32-bit file, please try to load it with Il2CppDumper-x86.exe"); + } + if (fileHeader.Machine == 0x8664 && !Environment.Is64BitProcess) //32bit process can't load 64bit dll + { + throw new InvalidOperationException("The file is a 64-bit file, please try to load it with Il2CppDumper.exe"); + } + var pos = reader.Position; + reader.Position = pos + fileHeader.SizeOfOptionalHeader; + var sections = reader.ReadClassArray(fileHeader.NumberOfSections); + var last = sections[^1]; + var size = last.VirtualAddress + last.VirtualSize; + var peBuff = new byte[size]; + var handle = LoadLibrary(fileName); + if (handle == IntPtr.Zero) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + foreach (var section in sections) + { + switch (section.Characteristics) + { + case 0x60000020: + case 0x40000040: + case 0xC0000040: + Marshal.Copy(new IntPtr(handle.ToInt64() + section.VirtualAddress), peBuff, (int)section.VirtualAddress, (int)section.VirtualSize); + break; + } + } + var peMemory = new MemoryStream(peBuff); + var writer = new BinaryWriter(peMemory, Encoding.UTF8, true); + var headerSize = reader.Position; + reader.Position = 0; + var buff2 = reader.ReadBytes((int)headerSize); + writer.Write(buff2); + writer.Flush(); + writer.Close(); + peMemory.Position = 0; + var pe = new PE(peMemory); + pe.LoadFromMemory((ulong)handle.ToInt64()); + return pe; } } } diff --git a/Il2CppDumper/Utils/SectionHelper.cs b/Il2CppDumper/Utils/SectionHelper.cs index 5b10bae..d4d80e9 100644 --- a/Il2CppDumper/Utils/SectionHelper.cs +++ b/Il2CppDumper/Utils/SectionHelper.cs @@ -9,11 +9,11 @@ namespace Il2CppDumper private List exec; private List data; private List bss; - private Il2Cpp il2Cpp; - private int methodCount; - private int typeDefinitionsCount; - private long metadataUsagesCount; - private int imageCount; + private readonly Il2Cpp il2Cpp; + private readonly int methodCount; + private readonly int typeDefinitionsCount; + private readonly long metadataUsagesCount; + private readonly int imageCount; private bool pointerInExec; public List Exec => exec;