public Metadata(Stream stream) : base(stream) { pMetadataHdr = ReadObject <Il2CppGlobalMetadataHeader>(); if (pMetadataHdr.sanity != 0xFAB11BAF) { throw new Exception("ERROR: Metadata file supplied is not valid metadata file."); } if (pMetadataHdr.version != 21 && pMetadataHdr.version != 22) { throw new Exception($"ERROR: Metadata file supplied is not a supported version[{pMetadataHdr.version}]."); } var uiImageCount = pMetadataHdr.imagesCount / MySizeOf(typeof(Il2CppImageDefinition)); var uiNumTypes = pMetadataHdr.typeDefinitionsCount / MySizeOf(typeof(Il2CppTypeDefinition)); Images = ReadArray <Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount); //GetTypeDefFromIndex Types = ReadArray <Il2CppTypeDefinition>(pMetadataHdr.typeDefinitionsOffset, uiNumTypes); //GetMethodDefinition Methods = ReadArray <Il2CppMethodDefinition>(pMetadataHdr.methodsOffset, pMetadataHdr.methodsCount / MySizeOf(typeof(Il2CppMethodDefinition))); //GetParameterFromIndex parameterDefs = ReadArray <Il2CppParameterDefinition>(pMetadataHdr.parametersOffset, pMetadataHdr.parametersCount / MySizeOf(typeof(Il2CppParameterDefinition))); //GetFieldDefFromIndex Fields = ReadArray <Il2CppFieldDefinition>(pMetadataHdr.fieldsOffset, pMetadataHdr.fieldsCount / MySizeOf(typeof(Il2CppFieldDefinition))); //GetFieldDefaultFromIndex fieldDefaultValues = ReadArray <Il2CppFieldDefaultValue>(pMetadataHdr.fieldDefaultValuesOffset, pMetadataHdr.fieldDefaultValuesCount / MySizeOf(typeof(Il2CppFieldDefaultValue))); }
public Metadata(Stream stream) : base(stream) { // Read magic bytes if (ReadUInt32() != 0xFAB11BAF) { throw new Exception("ERROR: Metadata file supplied is not valid metadata file."); } // Set object versioning for Bin2Object from metadata version Version = ReadInt32(); // Rewind and read metadata header in full Position -= 8; pMetadataHdr = ReadObject <Il2CppGlobalMetadataHeader>(); if (Version != 21 && Version != 22 && Version != 23) { throw new Exception($"ERROR: Metadata file supplied is not a supported version ({pMetadataHdr.version})."); } var uiImageCount = pMetadataHdr.imagesCount / Sizeof(typeof(Il2CppImageDefinition)); var uiNumTypes = pMetadataHdr.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition)); Images = ReadArray <Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount); //GetTypeDefFromIndex Types = ReadArray <Il2CppTypeDefinition>(pMetadataHdr.typeDefinitionsOffset, uiNumTypes); //GetMethodDefinition Methods = ReadArray <Il2CppMethodDefinition>(pMetadataHdr.methodsOffset, pMetadataHdr.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); //GetParameterFromIndex parameterDefs = ReadArray <Il2CppParameterDefinition>(pMetadataHdr.parametersOffset, pMetadataHdr.parametersCount / Sizeof(typeof(Il2CppParameterDefinition))); //GetFieldDefFromIndex Fields = ReadArray <Il2CppFieldDefinition>(pMetadataHdr.fieldsOffset, pMetadataHdr.fieldsCount / Sizeof(typeof(Il2CppFieldDefinition))); //GetFieldDefaultFromIndex fieldDefaultValues = ReadArray <Il2CppFieldDefaultValue>(pMetadataHdr.fieldDefaultValuesOffset, pMetadataHdr.fieldDefaultValuesCount / Sizeof(typeof(Il2CppFieldDefaultValue))); }
public Metadata(Stream stream) : base(stream) { pMetadataHdr = ReadObject <Il2CppGlobalMetadataHeader>(); if (pMetadataHdr.sanity != 0xFAB11BAF) { throw new Exception("ERROR: Metadata file supplied is not valid metadata file."); } if (pMetadataHdr.version != 21 && pMetadataHdr.version != 22) { throw new Exception($"ERROR: Metadata file supplied is not a supported version[{pMetadataHdr.version}]."); } // Strings literals var uiStringLiteralCount = pMetadataHdr.stringLiteralCount / MySizeOf(typeof(Il2CppStringLiteral)); var stringDefs = ReadArray <Il2CppStringLiteral>(pMetadataHdr.stringLiteralOffset, uiStringLiteralCount); Strings = new string[stringDefs.Length]; for (var idx = 0; idx < stringDefs.Length; idx++) { var raw = ReadArray <byte>(pMetadataHdr.stringLiteralDataOffset + stringDefs[idx].dataIndex, (int)stringDefs[idx].length); Strings[idx] = System.Text.Encoding.UTF8.GetString(raw); } // Images (.dll) var uiImageCount = pMetadataHdr.imagesCount / MySizeOf(typeof(Il2CppImageDefinition)); Images = ReadArray <Il2CppImageDefinition>(pMetadataHdr.imagesOffset, uiImageCount); // Interfaces Interfaces = new Dictionary <int, Il2CppTypeDefinition>(); //var uiInterfacePairCount = pMetadataHdr.interfaceOffsetsCount / MySizeOf(typeof(Il2CppInterfaceOffsetPair)); //var interfacePairs = ReadArray<Il2CppInterfaceOffsetPair>(pMetadataHdr.interfaceOffsetsOffset, uiInterfacePairCount); //var uiInterfaceCount = pMetadataHdr.interfacesCount / MySizeOf(typeof(Il2CppTypeDefinition)); //var interfaceDefs = ReadArray<Il2CppTypeDefinition>(pMetadataHdr.interfacesOffset, uiInterfaceCount); //for (var i = 0; i < interfacePairs.Count(); i++) //{ // Interfaces[i] = interfaceDefs[interfacePairs[i].interfaceTypeIndex]; //} // EncodedMethods //EncodedMethods = ReadArray<uint>(pMetadataHdr.vtableMethodsOffset, pMetadataHdr.vtableMethodsCount); // GetTypeDefFromIndex var uiNumTypes = pMetadataHdr.typeDefinitionsCount / MySizeOf(typeof(Il2CppTypeDefinition)); Types = ReadArray <Il2CppTypeDefinition>(pMetadataHdr.typeDefinitionsOffset, uiNumTypes); // GetMethodDefinition Methods = ReadArray <Il2CppMethodDefinition>(pMetadataHdr.methodsOffset, pMetadataHdr.methodsCount / MySizeOf(typeof(Il2CppMethodDefinition))); // GetParameterFromIndex parameterDefs = ReadArray <Il2CppParameterDefinition>(pMetadataHdr.parametersOffset, pMetadataHdr.parametersCount / MySizeOf(typeof(Il2CppParameterDefinition))); // GetFieldDefFromIndex Fields = ReadArray <Il2CppFieldDefinition>(pMetadataHdr.fieldsOffset, pMetadataHdr.fieldsCount / MySizeOf(typeof(Il2CppFieldDefinition))); // GetFieldDefaultFromIndex fieldDefaultValues = ReadArray <Il2CppFieldDefaultValue>(pMetadataHdr.fieldDefaultValuesOffset, pMetadataHdr.fieldDefaultValuesCount / MySizeOf(typeof(Il2CppFieldDefaultValue))); }
public Metadata(Stream stream) : base(stream) { // Read magic bytes if (ReadUInt32() != 0xFAB11BAF) { throw new Exception("ERROR: Metadata file supplied is not valid metadata file."); } // Set object versioning for Bin2Object from metadata version Version = ReadInt32(); // Rewind and read metadata header in full Position -= 8; Header = ReadObject <Il2CppGlobalMetadataHeader>(); if (Version < 21 || Version > 24) { throw new Exception($"ERROR: Metadata file supplied is not a supported version ({Header.version})."); } // Load all the relevant metadata using offsets provided in the header Images = ReadArray <Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); Types = ReadArray <Il2CppTypeDefinition>(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition))); Methods = ReadArray <Il2CppMethodDefinition>(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); Params = ReadArray <Il2CppParameterDefinition>(Header.parametersOffset, Header.parametersCount / Sizeof(typeof(Il2CppParameterDefinition))); Fields = ReadArray <Il2CppFieldDefinition>(Header.fieldsOffset, Header.fieldsCount / Sizeof(typeof(Il2CppFieldDefinition))); FieldDefaultValues = ReadArray <Il2CppFieldDefaultValue>(Header.fieldDefaultValuesOffset, Header.fieldDefaultValuesCount / Sizeof(typeof(Il2CppFieldDefaultValue))); Properties = ReadArray <Il2CppPropertyDefinition>(Header.propertiesOffset, Header.propertiesOffset / Sizeof(typeof(Il2CppPropertyDefinition))); Events = ReadArray <Il2CppEventDefinition>(Header.eventsOffset, Header.eventsOffset / Sizeof(typeof(Il2CppEventDefinition))); InterfaceUsageIndices = ReadArray <int>(Header.interfacesOffset, Header.interfacesCount / sizeof(int)); // TODO: ParameterDefaultValue, GenericParameters, ParameterConstraints, GenericContainers, MetadataUsage, CustomAttributes // Get all string literals Position = Header.stringOffset; while (Position < Header.stringOffset + Header.stringCount) { Strings.Add((int)Position - Header.stringOffset, ReadNullTerminatedString()); } }
public Metadata(Stream stream) : base(stream) { // Read magic bytes if (ReadUInt32() != 0xFAB11BAF) { throw new InvalidOperationException("The supplied metadata file is not valid."); } // Set object versioning for Bin2Object from metadata version Version = ReadInt32(); // Rewind and read metadata header in full Header = ReadObject <Il2CppGlobalMetadataHeader>(0); if (Version < 16 || Version > 24) { throw new InvalidOperationException($"The supplied metadata file is not of a supported version ({Header.version})."); } // Sanity checking // Unity.IL2CPP.MetadataCacheWriter.WriteLibIl2CppMetadata always writes the metadata information in the same order it appears in the header, // with each block always coming directly after the previous block, 4-byte aligned. We can use this to check the integrity of the data and // detect sub-versions. // For metadata v24, the header can either be either 0x110 (24.0, 24.1) or 0x108 (24.2) bytes long. Since 'stringLiteralOffset' is the first thing // in the header after the sanity and version fields, and since it will always point directly to the first byte after the end of the header, // we can use this value to determine the actual header length and therefore narrow down the metadata version to 24.0/24.1 or 24.2. var realHeaderLength = Header.stringLiteralOffset; if (realHeaderLength != Sizeof(typeof(Il2CppGlobalMetadataHeader))) { if (Version == 24.0) { Version = 24.2; Header = ReadObject <Il2CppGlobalMetadataHeader>(0); } } if (realHeaderLength != Sizeof(typeof(Il2CppGlobalMetadataHeader))) { throw new InvalidOperationException("Could not verify the integrity of the metadata file or accurately identify the metadata sub-version"); } // Load all the relevant metadata using offsets provided in the header if (Version >= 16) { Images = ReadArray <Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); } // As an additional sanity check, all images in the metadata should have Mono.Cecil.MetadataToken == 1 // In metadata v24.1, two extra fields were added which will cause the below test to fail. // In that case, we can then adjust the version number and reload // Tokens were introduced in v19 - we don't bother testing earlier versions if (Version >= 19 && Images.Any(x => x.token != 1)) { if (Version == 24.0) { Version = 24.1; // No need to re-read the header, it's the same for both sub-versions Images = ReadArray <Il2CppImageDefinition>(Header.imagesOffset, Header.imagesCount / Sizeof(typeof(Il2CppImageDefinition))); if (Images.Any(x => x.token != 1)) { throw new InvalidOperationException("Could not verify the integrity of the metadata file image list"); } } } Types = ReadArray <Il2CppTypeDefinition>(Header.typeDefinitionsOffset, Header.typeDefinitionsCount / Sizeof(typeof(Il2CppTypeDefinition))); Methods = ReadArray <Il2CppMethodDefinition>(Header.methodsOffset, Header.methodsCount / Sizeof(typeof(Il2CppMethodDefinition))); Params = ReadArray <Il2CppParameterDefinition>(Header.parametersOffset, Header.parametersCount / Sizeof(typeof(Il2CppParameterDefinition))); Fields = ReadArray <Il2CppFieldDefinition>(Header.fieldsOffset, Header.fieldsCount / Sizeof(typeof(Il2CppFieldDefinition))); FieldDefaultValues = ReadArray <Il2CppFieldDefaultValue>(Header.fieldDefaultValuesOffset, Header.fieldDefaultValuesCount / Sizeof(typeof(Il2CppFieldDefaultValue))); Properties = ReadArray <Il2CppPropertyDefinition>(Header.propertiesOffset, Header.propertiesCount / Sizeof(typeof(Il2CppPropertyDefinition))); Events = ReadArray <Il2CppEventDefinition>(Header.eventsOffset, Header.eventsCount / Sizeof(typeof(Il2CppEventDefinition))); InterfaceUsageIndices = ReadArray <int>(Header.interfacesOffset, Header.interfacesCount / sizeof(int)); NestedTypeIndices = ReadArray <int>(Header.nestedTypesOffset, Header.nestedTypesCount / sizeof(int)); GenericContainers = ReadArray <Il2CppGenericContainer>(Header.genericContainersOffset, Header.genericContainersCount / Sizeof(typeof(Il2CppGenericContainer))); GenericParameters = ReadArray <Il2CppGenericParameter>(Header.genericParametersOffset, Header.genericParametersCount / Sizeof(typeof(Il2CppGenericParameter))); GenericConstraintIndices = ReadArray <int>(Header.genericParameterConstraintsOffset, Header.genericParameterConstraintsCount / sizeof(int)); InterfaceOffsets = ReadArray <Il2CppInterfaceOffsetPair>(Header.interfaceOffsetsOffset, Header.interfaceOffsetsCount / Sizeof(typeof(Il2CppInterfaceOffsetPair))); VTableMethodIndices = ReadArray <uint>(Header.vtableMethodsOffset, Header.vtableMethodsCount / sizeof(uint)); if (Version >= 16) { Assemblies = ReadArray <Il2CppAssemblyDefinition>(Header.assembliesOffset, Header.assembliesCount / Sizeof(typeof(Il2CppAssemblyDefinition))); ParameterDefaultValues = ReadArray <Il2CppParameterDefaultValue>(Header.parameterDefaultValuesOffset, Header.parameterDefaultValuesCount / Sizeof(typeof(Il2CppParameterDefaultValue))); } if (Version >= 19) { MetadataUsageLists = ReadArray <Il2CppMetadataUsageList>(Header.metadataUsageListsOffset, Header.metadataUsageListsCount / Sizeof(typeof(Il2CppMetadataUsageList))); MetadataUsagePairs = ReadArray <Il2CppMetadataUsagePair>(Header.metadataUsagePairsOffset, Header.metadataUsagePairsCount / Sizeof(typeof(Il2CppMetadataUsagePair))); FieldRefs = ReadArray <Il2CppFieldRef>(Header.fieldRefsOffset, Header.fieldRefsCount / Sizeof(typeof(Il2CppFieldRef))); } if (Version >= 21) { AttributeTypeIndices = ReadArray <int>(Header.attributeTypesOffset, Header.attributeTypesCount / sizeof(int)); AttributeTypeRanges = ReadArray <Il2CppCustomAttributeTypeRange>(Header.attributesInfoOffset, Header.attributesInfoCount / Sizeof(typeof(Il2CppCustomAttributeTypeRange))); } // Get all metadata string literals Position = Header.stringOffset; while (Position < Header.stringOffset + Header.stringCount) { Strings.Add((int)Position - Header.stringOffset, ReadNullTerminatedString()); } // Get all managed code string literals var stringLiteralList = ReadArray <Il2CppStringLiteral>(Header.stringLiteralOffset, Header.stringLiteralCount / Sizeof(typeof(Il2CppStringLiteral))); StringLiterals = new string[stringLiteralList.Length]; for (var i = 0; i < stringLiteralList.Length; i++) { StringLiterals[i] = ReadFixedLengthString(Header.stringLiteralDataOffset + stringLiteralList[i].dataIndex, stringLiteralList[i].length); } }