internal void SetFileFormatReader(IFileFormatReader reader) { if (reader != null) { _inflater.SetFileFormatReader(reader); } }
private static IInflater CreateInflater(IFileFormatReader reader = null) { switch (GetInflaterType()) { case WorkerType.Managed: return(new Inflater(reader)); case WorkerType.ZLib: // Rather than reading raw data and using a FormatReader to interpret // headers/footers manually, we instead set the zlib stream to parse // that information for us. if (reader == null) { return(new InflaterZlib(ZLibNative.Deflate_DefaultWindowBits)); } else { // Since we don't necessarily know what WindowSize the stream was compressed with, // we use the upper bound of (32..47) as the WindowSize for decompression. This enables // detection for Zlib and GZip headers return(new InflaterZlib(WindowSizeUpperBound)); } default: // We do not expect this to ever be thrown. // But this is better practice than returning null. throw new SystemException("Program entered an unexpected state."); } }
private static IInflater CreateInflater(IFileFormatReader reader = null) { // The deflator type (zlib or managed) is normally determined by s_deflatorType, // which is initialized by the provider based on what's available on the system. // But for testing purposes, we sometimes want to override this, forcing // compression/decompression to use a particular type. WorkerType deflatorType = s_deflaterType; #if DEBUG if (s_forcedTestingDeflaterType != WorkerType.Unknown) { deflatorType = s_forcedTestingDeflaterType; } #endif if (deflatorType == WorkerType.ZLib) { // Rather than reading raw data and using a FormatReader to interpret // headers/footers manually, we instead set the zlib stream to parse // that information for us. if (reader == null) { return(new InflaterZlib(ZLibNative.Deflate_DefaultWindowBits)); } else { Debug.Assert(reader.ZLibWindowSize == 47, "A GZip reader must be designated with ZLibWindowSize == 47. Other header formats aren't supported by ZLib."); return(new InflaterZlib(reader.ZLibWindowSize)); } } else { return(new InflaterManaged(reader)); } }
public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion) { var inst = LoadImpl(stream); // Try to process the IL2CPP image; return the instance if succeeded, otherwise null return(inst.InitializeWithoutMetadata(metadataVersion) ? inst : null); }
internal void SetFileFormatReader(IFileFormatReader reader) { if (reader == null) { return; } this.inflater.SetFileFormatReader(reader); }
// The method for ARM64: // - We want to extract values for CodeRegistration and MetadataRegistration from Il2CppCodegenRegistration(void) // - One of the functions supplied will be either Il2CppCodeGenRegistration or an initializer for Il2CppCodeGenRegistration.cpp // - The initializer (if present) loads a pointer to Il2CppCodegenRegistration in X1, if the function isn't in the function table // - Il2CppCodegenRegistration loads CodeRegistration into X0, MetadataRegistration into X1 and Il2CppCodeGenOptions into X2 // - Loads can be done either with ADRP+ADD (loads the address of the wanted struct) or ADRP+LDR (loads a pointer to the address which must be de-referenced) // - Loads do not need to be pairs of sequential instructions // - We need to sweep the whole function from the ADRP to the next B to find an ADD or LDR with a corresponding register protected override (ulong, ulong) ConsiderCode(IFileFormatReader image, uint loc) { // Load function into memory // In practice, the longest function length we need is not generally longer than 7 instructions (0x1C bytes) var func = getFunctionAtFileOffset(image, loc, 7); // Don't accept functions longer than 7 instructions (in this case, the last instruction won't be a B) if (!isB(func[^ 1]))
// Since a reader is being taken, CompressionMode.Decompress is implied internal DeflateManagedStream(Stream stream, bool leaveOpen, IFileFormatReader reader) { Debug.Assert(reader != null, "The IFileFormatReader passed to the internal DeflateStream constructor must be non-null"); if (stream == null) throw new ArgumentNullException(nameof(stream)); if (!stream.CanRead) throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); InitializeInflater(stream, leaveOpen, reader); }
public static Il2CppProcessor LoadFromFile(string codeFile, string metadataFile) { // Load the metadata file Metadata metadata; try { metadata = new Metadata(new MemoryStream(File.ReadAllBytes(metadataFile))); } catch (Exception ex) { Console.Error.WriteLine(ex.Message); return(null); } // Load the il2cpp code file (try ELF and PE) var memoryStream = new MemoryStream(File.ReadAllBytes(codeFile)); IFileFormatReader stream = ((IFileFormatReader)ElfReader.Load(memoryStream) ?? PEReader.Load(memoryStream)) ?? MachOReader.Load(memoryStream); if (stream == null) { Console.Error.WriteLine("Unsupported executable file format"); return(null); } Il2CppReader il2cpp; // We are currently supporting x86 and ARM architectures switch (stream.Arch) { case "x86": il2cpp = new Il2CppReaderX86(stream); break; case "ARM": il2cpp = new Il2CppReaderARM(stream); break; default: Console.Error.WriteLine("Unsupported architecture"); return(null); } // Find code and metadata regions if (!il2cpp.Load(metadata.Version)) { Console.Error.WriteLine("Could not process IL2CPP image"); return(null); } return(new Il2CppProcessor(il2cpp, metadata)); }
public static ulong Decode(IFileFormatReader next) { ulong uleb = 0; byte b = 0x80; for (var shift = 0; b >> 7 == 1; shift += 7) { b = next.ReadByte(); uleb |= (ulong)(b & 0x7f) << shift; } return(uleb); }
private void Configure(IFileFormatReader image, ulong codeRegistration, ulong metadataRegistration) { CodeRegistration = image.ReadMappedObject <Il2CppCodeRegistration>(codeRegistration); MetadataRegistration = image.ReadMappedObject <Il2CppMetadataRegistration>(metadataRegistration); MethodPointers = image.ReadMappedArray <uint>(CodeRegistration.pmethodPointers, (int)CodeRegistration.methodPointersCount); FieldOffsetData = image.ReadMappedArray <int>(MetadataRegistration.pfieldOffsets, MetadataRegistration.fieldOffsetsCount); var types = image.ReadMappedArray <uint>(MetadataRegistration.ptypes, MetadataRegistration.typesCount); for (int i = 0; i < MetadataRegistration.typesCount; i++) { Types.Add(image.ReadMappedObject <Il2CppType>(types[i])); } }
private void ReadSectionOffsets(IFileFormatReader elfReader) { var sectionByName = (IDictionary)elfReader.GetType().BaseType.GetField("sectionByName", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(elfReader); sectionOffsets = new Dictionary <string, ulong>(); foreach (DictionaryEntry sectionKeyValue in sectionByName) { var value = sectionKeyValue.Value; ulong offset = (ulong)value.GetType().GetField("sh_offset").GetValue(value); sectionOffsets.Add((string)sectionKeyValue.Key, offset); } }
// Since a reader is being taken, CompressionMode.Decompress is implied internal DeflateStream(Stream stream, bool leaveOpen, IFileFormatReader reader) { Debug.Assert(reader != null, "The IFileFormatReader passed to the internal DeflateStream constructor must be non-null"); if (stream == null) throw new ArgumentNullException("stream"); if (!stream.CanRead) throw new ArgumentException(SR.NotReadableStream, "stream"); _inflater = CreateInflater(reader); _stream = stream; _mode = CompressionMode.Decompress; _leaveOpen = leaveOpen; _buffer = new byte[DefaultBufferSize]; }
private readonly IFileFormatReader _formatReader; // class to decode header and footer (e.g. gzip) internal Inflater64Managed(IFileFormatReader reader) { _output = new OutputWindow(); _input = new InputBuffer(); _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements]; _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements]; if (reader != null) { _formatReader = reader; _hasFormatReader = true; } Reset(); }
// Since a reader is being taken, CompressionMode.Decompress is implied internal DeflateManagedStream(Stream stream, bool leaveOpen, IFileFormatReader reader) { Debug.Assert(reader != null, "The IFileFormatReader passed to the internal DeflateStream constructor must be non-null"); if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (!stream.CanRead) { throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); } InitializeInflater(stream, leaveOpen, reader); }
// Load and initialize a binary of any supported architecture public static Il2CppBinary Load(IFileFormatReader stream, double metadataVersion) { // Get type from image architecture var type = Assembly.GetExecutingAssembly().GetType("Il2CppInspector.Il2CppBinary" + stream.Arch.ToUpper()); if (type == null) { throw new NotImplementedException("Unsupported architecture: " + stream.Arch); } var inst = (Il2CppBinary)Activator.CreateInstance(type, stream); // Try to process the IL2CPP image; return the instance if succeeded, otherwise null return(inst.Initialize(metadataVersion) ? inst : null); }
/// <summary> /// Sets up this DeflateManagedStream to be used for Inflation/Decompression /// </summary> internal void InitializeInflater(Stream stream, bool leaveOpen, IFileFormatReader reader = null, ZipArchiveEntry.CompressionMethodValues method = ZipArchiveEntry.CompressionMethodValues.Deflate, long uncompressedSize = -1) { Debug.Assert(stream != null); Debug.Assert(method == ZipArchiveEntry.CompressionMethodValues.Deflate64); if (!stream.CanRead) { throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); } _inflater = new InflaterManaged(reader, method == ZipArchiveEntry.CompressionMethodValues.Deflate64 ? true : false, uncompressedSize); _stream = stream; _leaveOpen = leaveOpen; _buffer = new byte[DefaultBufferSize]; }
private readonly IFileFormatReader _formatReader; // class to decode header and footer (e.g. gzip) internal InflaterManaged(IFileFormatReader reader, bool deflate64, long uncompressedSize) { _output = new OutputWindow(); _input = new InputBuffer(); _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements]; _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements]; _deflate64 = deflate64; _uncompressedSize = uncompressedSize; if (reader != null) { _formatReader = reader; _hasFormatReader = true; } Reset(); }
private List <uint> getFunctionAtFileOffset(IFileFormatReader image, uint loc, uint maxLength) { // Read a function that ends in a hard branch (B) or exceeds maxLength instructions var func = new List <uint>(); uint inst; image.Position = loc; do { inst = image.ReadUInt32(); func.Add(inst); } while (!isB(inst) && func.Count < maxLength); return(func); }
// Thumb 2 Supplement Reference Manual: http://class.ece.iastate.edu/cpre288/resources/docs/Thumb-2SupplementReferenceManual.pdf // Section 3.1 private uint getNextThumbInstruction(IFileFormatReader image) { // Assume 16-bit uint inst = image.ReadUInt16(); // Is 32-bit? if (inst.Bits(13, 15) == 0b111) { if (inst.Bits(11, 2) != 0b00) { inst = (inst << 16) + image.ReadUInt16(); } } return(inst); }
// Since a reader is being taken, CompressionMode.Decompress is implied internal DeflateStream(Stream stream, bool leaveOpen, IFileFormatReader reader) { Debug.Assert(reader != null, "The IFileFormatReader passed to the internal DeflateStream constructor must be non-null"); if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { throw new ArgumentException(SR.NotReadableStream, "stream"); } _inflater = CreateInflater(reader); _stream = stream; _mode = CompressionMode.Decompress; _leaveOpen = leaveOpen; _buffer = new byte[DefaultBufferSize]; }
// Load and initialize a binary of any supported architecture private static Il2CppBinary LoadImpl(IFileFormatReader stream) { // Get type from image architecture var type = Assembly.GetExecutingAssembly().GetType("Il2CppInspector.Il2CppBinary" + stream.Arch.ToUpper()); if (type == null) { throw new NotImplementedException("Unsupported architecture: " + stream.Arch); } // Set width of long (convert to sizeof(int) for 32-bit files) if (stream[0].Bits == 32) { stream[0].Stream.PrimitiveMappings.Add(typeof(long), typeof(int)); stream[0].Stream.PrimitiveMappings.Add(typeof(ulong), typeof(uint)); } return((Il2CppBinary)Activator.CreateInstance(type, stream[0])); }
public override IFileFormatReader this[uint index] { get { Console.WriteLine($"Extracting binary from {binaryFiles[index].FullName}"); IFileFormatReader loaded = null; // ZipArchiveEntry does not support seeking so we have to close and re-open for each possible load format var binary = binaryFiles[index].Open(); loaded = ElfReader32.Load(binary, OnStatusUpdate); binary.Close(); if (loaded != null) { return(loaded); } binary = binaryFiles[index].Open(); loaded = ElfReader64.Load(binary, OnStatusUpdate); binary.Close(); return(loaded); } }
internal void SetFileFormatReader(IFileFormatReader reader) { _formatReader = reader; _hasFormatReader = true; this.Reset(); }
public void SetFileFormatReader(IFileFormatReader reader) { _formatReader = reader; _hasFormatReader = true; Reset(); }
internal InflaterManaged(IFileFormatReader reader, bool deflate64) { _output = new OutputWindow(); _input = new InputBuffer(); _codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements]; _codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements]; _deflate64 = deflate64; if (reader != null) { _formatReader = reader; _hasFormatReader = true; } Reset(); }
public void RegisterFormatReader(IFileFormatReader fileFormatReader) { _formatReaders.Add(fileFormatReader); }
public Il2CppReaderARM(IFileFormatReader stream) : base(stream) { }
internal void SetFileFormatReader(IFileFormatReader reader) { if (reader != null) { inflater.SetFileFormatReader(reader); } }
public void RegisterDefaultFormatReader(IFileFormatReader defaultFormatReader) { _defaultFormatReader = defaultFormatReader; }
protected Il2CppBinary(IFileFormatReader stream) { Image = stream; }
public Il2CppBinaryX86(IFileFormatReader stream) : base(stream) { }
protected override (ulong, ulong) ConsiderCode(IFileFormatReader image, uint loc) { ulong metadata, code; long pCgr; // x86 // Assembly bytes to search for at start of each function var bytes = new byte[] { 0x6A, 0x00, 0x6A, 0x00, 0x68 }; image.Position = loc; var buff = image.ReadBytes(5); if (bytes.SequenceEqual(buff)) { // Next 4 bytes are the function pointer being pushed onto the stack pCgr = image.ReadUInt32(); // Start of next instruction if (image.ReadByte() != 0xB9) { return(0, 0); } // Jump to Il2CppCodegenRegistration image.Position = image.MapVATR((ulong)pCgr + 6); metadata = image.ReadUInt32(); image.Position = image.MapVATR((ulong)pCgr + 11); code = image.ReadUInt32(); return(code, metadata); } // x86 based on ELF PLT if (image is IElfReader elf) { var plt = elf.GetPLTAddress(); // push ebp; mov ebp, esp; push ebx; and esp, 0FFFFFFF0h; sub esp, 20h; call $+5; pop ebx bytes = new byte[] { 0x55, 0x89, 0xE5, 0x53, 0x83, 0xE4, 0xF0, 0x83, 0xEC, 0x20, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5B }; image.Position = loc; buff = image.ReadBytes(16); if (!bytes.SequenceEqual(buff)) { return(0, 0); } // lea eax, (pCgr - offset)[ebx] (Position + 6 is the opcode lea eax; Position + 8 is the operand) image.Position += 6; // Ensure it's lea eax, #address if (image.ReadUInt16() != 0x838D) { return(0, 0); } try { pCgr = image.MapVATR(image.ReadUInt32() + plt); } // Could not find a mapping in the section table catch (InvalidOperationException) { return(0, 0); } // Extract Metadata pointer // An 0x838D opcode indicates LEA (no indirection) image.Position = pCgr + 0x20; var opcode = image.ReadUInt16(); metadata = image.ReadUInt32() + plt; // An 8x838B opcode indicates MOV (pointer indirection) if (opcode == 0x838B) { image.Position = image.MapVATR(metadata); metadata = image.ReadUInt32(); } if (opcode != 0x838B && opcode != 0x838D) { return(0, 0); } // Repeat the same logic for extracting the Code pointer image.Position = pCgr + 0x2A; opcode = image.ReadUInt16(); code = image.ReadUInt32() + plt; if (opcode == 0x838B) { image.Position = image.MapVATR(code); code = image.ReadUInt32(); } if (opcode != 0x838B && opcode != 0x838D) { return(0, 0); } return(code, metadata); } return(0, 0); }
public void RegisterFormatReader(IFileFormatReader fileFormatReader) { formatReaders.Enqueue(fileFormatReader); }
public void RegisterDefaultFormatReader(IFileFormatReader defaultFormatReader) { _defaultFormatReader = defaultFormatReader; }
public Il2CppBinaryX86(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration) { }
/// <summary> /// Sets up this DeflateManagedStream to be used for Inflation/Decompression /// </summary> internal void InitializeInflater(Stream stream, bool leaveOpen, IFileFormatReader reader = null, ZipArchiveEntry.CompressionMethodValues method = ZipArchiveEntry.CompressionMethodValues.Deflate) { Debug.Assert(stream != null); Debug.Assert(method == ZipArchiveEntry.CompressionMethodValues.Deflate || method == ZipArchiveEntry.CompressionMethodValues.Deflate64); if (!stream.CanRead) throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream)); _inflater = new InflaterManaged(reader, method == ZipArchiveEntry.CompressionMethodValues.Deflate64 ? true : false); _stream = stream; _mode = CompressionMode.Decompress; _leaveOpen = leaveOpen; _buffer = new byte[DefaultBufferSize]; }
protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) { Image = stream; Configure(Image, codeRegistration, metadataRegistration); }
internal void SetFileFormatReader(IFileFormatReader reader) { formatReader = reader; hasFormatReader = true; Reset(); }
private static IInflater CreateInflater(IFileFormatReader reader = null) { // The deflator type (zlib or managed) is normally determined by s_deflatorType, // which is initialized by the provider based on what's available on the system. // But for testing purposes, we sometimes want to override this, forcing // compression/decompression to use a particular type. WorkerType deflatorType = s_deflaterType; #if DEBUG if (s_forcedTestingDeflaterType != WorkerType.Unknown) deflatorType = s_forcedTestingDeflaterType; #endif if (deflatorType == WorkerType.ZLib) { // Rather than reading raw data and using a FormatReader to interpret // headers/footers manually, we instead set the zlib stream to parse // that information for us. if (reader == null) return new InflaterZlib(ZLibNative.Deflate_DefaultWindowBits); else { Debug.Assert(reader.ZLibWindowSize == 47, "A GZip reader must be designated with ZLibWindowSize == 47. Other header formats aren't supported by ZLib."); return new InflaterZlib(reader.ZLibWindowSize); } } else { return new InflaterManaged(reader); } }
public void RegisterFormatReader(IFileFormatReader fileFormatReader) { _formatReaders.Add(fileFormatReader); }
public void RegisterFormatReader(IFileFormatReader fileFormatReader) { formatReaders.Enqueue(fileFormatReader); }
protected Il2CppReader(IFileFormatReader stream) { Image = stream; }