Exemplo n.º 1
0
 internal void SetFileFormatReader(IFileFormatReader reader)
 {
     if (reader != null)
     {
         _inflater.SetFileFormatReader(reader);
     }
 }
Exemplo n.º 2
0
        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.");
            }
        }
Exemplo n.º 3
0
        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));
            }
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
 internal void SetFileFormatReader(IFileFormatReader reader)
 {
     if (reader == null)
     {
         return;
     }
     this.inflater.SetFileFormatReader(reader);
 }
Exemplo n.º 6
0
        // 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]))
Exemplo n.º 7
0
        // 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);
        }
Exemplo n.º 8
0
        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));
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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);
            }
        }
Exemplo n.º 12
0
        // 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];
        }
Exemplo n.º 13
0
        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();
        }
Exemplo n.º 14
0
        // 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);
        }
Exemplo n.º 15
0
        // 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);
        }
Exemplo n.º 16
0
        /// <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];
        }
Exemplo n.º 17
0
        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();
        }
Exemplo n.º 18
0
        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);
        }
Exemplo n.º 19
0
        // 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);
        }
Exemplo n.º 20
0
        // 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];
        }
Exemplo n.º 21
0
        // 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]));
        }
Exemplo n.º 22
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);
            }
        }
Exemplo n.º 23
0
 internal void SetFileFormatReader(IFileFormatReader reader)
 {
     _formatReader = reader;
     _hasFormatReader = true;
     this.Reset();
 }
Exemplo n.º 24
0
 public void SetFileFormatReader(IFileFormatReader reader)
 {
     _formatReader = reader;
     _hasFormatReader = true;
     Reset();
 }
Exemplo n.º 25
0
        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);
 }
Exemplo n.º 27
0
 public Il2CppReaderARM(IFileFormatReader stream) : base(stream)
 {
 }
Exemplo n.º 28
0
 internal void SetFileFormatReader(IFileFormatReader reader) {
     if (reader != null) {
         inflater.SetFileFormatReader(reader);
     }
 }
 public void RegisterDefaultFormatReader(IFileFormatReader defaultFormatReader)
 {
     _defaultFormatReader = defaultFormatReader;
 }
Exemplo n.º 30
0
 protected Il2CppBinary(IFileFormatReader stream)
 {
     Image = stream;
 }
Exemplo n.º 31
0
 public Il2CppBinaryX86(IFileFormatReader stream) : base(stream)
 {
 }
Exemplo n.º 32
0
        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);
 }
Exemplo n.º 34
0
 public void RegisterDefaultFormatReader(IFileFormatReader defaultFormatReader)
 {
     _defaultFormatReader = defaultFormatReader;
 }
Exemplo n.º 35
0
 public Il2CppBinaryX86(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration) : base(stream, codeRegistration, metadataRegistration)
 {
 }
Exemplo n.º 36
0
        /// <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];
        }
Exemplo n.º 37
0
 protected Il2CppBinary(IFileFormatReader stream, uint codeRegistration, uint metadataRegistration)
 {
     Image = stream;
     Configure(Image, codeRegistration, metadataRegistration);
 }
Exemplo n.º 38
0
 internal void SetFileFormatReader(IFileFormatReader reader) {
     formatReader = reader;
     hasFormatReader = true;
     Reset();
 }
Exemplo n.º 39
0
        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);
 }
Exemplo n.º 41
0
 public void RegisterFormatReader(IFileFormatReader fileFormatReader)
 {
     formatReaders.Enqueue(fileFormatReader);
 }
Exemplo n.º 42
0
 protected Il2CppReader(IFileFormatReader stream)
 {
     Image = stream;
 }