Пример #1
0
        public ulong FindMetadataRegistrationV27()
        {
            var ptrSize             = _pe.is32Bit ? 4u : 8u;
            var sizeOfMr            = (uint)LibCpp2ILUtils.VersionAwareSizeOf(typeof(Il2CppMetadataRegistration));
            var ptrsToNumberOfTypes = FindAllMappedWords((ulong)typeDefinitionsCount);

            var possibleMetadataUsages = ptrsToNumberOfTypes.Select(a => a - sizeOfMr + ptrSize * 4);

            var mrFieldCount = sizeOfMr / (ulong)(ptrSize);

            foreach (var va in possibleMetadataUsages)
            {
                var mrWords = _pe.ReadClassArrayAtVirtualAddress <long>(va, (int)mrFieldCount);

                // Even field indices are counts, odd field indices are pointers
                var ok = true;
                for (var i = 0; i < mrWords.Length && ok; i++)
                {
                    ok = i % 2 == 0 ? mrWords[i] < 0x30000 : mrWords[i] == 0 || _pe.TryMapVirtualAddressToRaw((ulong)mrWords[i], out _);  //Maybe need an investigation here, but metadataUsages can be a null ptr.
                }

                if (ok)
                {
                    return(va);
                }
            }

            return(0);
        }
Пример #2
0
 internal static void MapGlobalIdentifiers(Il2CppMetadata metadata, PE.PE cppAssembly)
 {
     //Type references
     TypeRefs = metadata.metadataUsageDic[1]
                .Select(kvp => new { kvp, type = cppAssembly.types[kvp.Value] })
                .Select(t => new GlobalIdentifier
     {
         Name           = LibCpp2ILUtils.GetTypeName(metadata, cppAssembly, t.type, true),
         Value          = LibCpp2ILUtils.GetTypeReflectionData(t.type) !,
         Offset         = cppAssembly.metadataUsages[t.kvp.Key],
         IdentifierType = GlobalIdentifier.Type.TYPEREF
     }).ToList();
Пример #3
0
        public ulong TryFindCodeRegUsingMetaReg(ulong metadataRegistration)
        {
            var textSection     = _pe.sections.First(s => s.Name == ".text");
            var toDisasm        = _pe.raw.SubArray((int)textSection.PointerToRawData, (int)textSection.SizeOfRawData);
            var allInstructions = LibCpp2ILUtils.DisassembleBytesNew(_pe.is32Bit, toDisasm, textSection.VirtualAddress + _pe.imageBase);

            var pushMetaReg = allInstructions.FirstOrDefault(i => i.Mnemonic == Mnemonic.Push && i.Op0Kind.IsImmediate() && i.GetImmediate(0) == metadataRegistration);

            if (pushMetaReg.Mnemonic == Mnemonic.Push) //Check non-default.
            {
                var idx = allInstructions.IndexOf(pushMetaReg);
                //Code reg has to be pushed after meta reg, cause that's how functions are called on 32-bit stdcall.
                var hopefullyPushCodeReg = allInstructions[idx + 1];
                if (hopefullyPushCodeReg.Mnemonic == Mnemonic.Push && hopefullyPushCodeReg.Op0Kind.IsImmediate())
                {
                    return(hopefullyPushCodeReg.GetImmediate(0));
                }
            }

            return(0);
        }
Пример #4
0
        internal ulong FindCodeRegistrationUsingMscorlib()
        {
            //Works only on >=24.2
            var searchBytes              = Encoding.ASCII.GetBytes("mscorlib.dll\0");
            var mscorlibs                = _pe.raw.Search(searchBytes).Select(idx => _pe.MapRawAddressToVirtual(idx));
            var usagesOfMscorlib         = FindAllMappedWords(mscorlibs);                //CodeGenModule address will be in here
            var codeGenModulesStructAddr = FindAllMappedWords(usagesOfMscorlib);         //CodeGenModules list address will be in here
            var endOfCodeGenRegAddr      = FindAllMappedWords(codeGenModulesStructAddr); //The end of the CodeRegistration object will be in here.

            if (!_pe.is32Bit)
            {
                var codeGenAddr     = endOfCodeGenRegAddr.First();
                var textSection     = _pe.sections.First(s => s.Name == ".text");
                var toDisasm        = _pe.raw.SubArray((int)textSection.PointerToRawData, (int)textSection.SizeOfRawData);
                var allInstructions = LibCpp2ILUtils.DisassembleBytesNew(_pe.is32Bit, toDisasm, textSection.VirtualAddress + _pe.imageBase);

                var allSensibleInstructions = allInstructions.Where(i =>
                                                                    i.Mnemonic == Mnemonic.Lea &&
                                                                    i.OpCount == 2 &&
                                                                    i.Op0Kind == OpKind.Register &&
                                                                    i.Op1Kind == OpKind.Memory &&
                                                                    i.Op0Register == Register.RCX).ToList();

                var sanity = 0;
                while (sanity++ < 500)
                {
                    var instruction = allSensibleInstructions.FirstOrDefault(i =>
                                                                             i.GetRipBasedInstructionMemoryAddress() == codeGenAddr
                                                                             );

                    if (instruction != default)
                    {
                        return(codeGenAddr);
                    }

                    codeGenAddr -= 8; //Always 64-bit here so IntPtr is 8
                }

                return(0);
            }
            else
            {
                IEnumerable <ulong>?codeRegVas = null;
                var sanity = 0;
                while ((codeRegVas?.Count() ?? 0) != 1)
                {
                    if (sanity++ > 500)
                    {
                        break;
                    }

                    endOfCodeGenRegAddr = endOfCodeGenRegAddr.Select(va => va - 4);
                    codeRegVas          = FindAllMappedWords(endOfCodeGenRegAddr);
                }

                if (endOfCodeGenRegAddr.Count() != 1)
                {
                    return(0ul);
                }

                return(endOfCodeGenRegAddr.First());
            }
        }
Пример #5
0
        internal ulong FindCodeRegistrationUsingMscorlib()
        {
            //Works only on >=24.2
            var searchBytes            = Encoding.ASCII.GetBytes("mscorlib.dll\0");
            var mscorlibs              = _pe.raw.Search(searchBytes).Select(idx => _pe.MapRawAddressToVirtual(idx));
            var pMscorlibCodegenModule = FindAllMappedWords(mscorlibs);                                 //CodeGenModule address will be in here
            var pMscorlibCodegenEntryInCodegenModulesList = FindAllMappedWords(pMscorlibCodegenModule); //CodeGenModules list address will be in here

            IEnumerable <ulong>?pCodegenModules = null;

            if (!(LibCpp2IlMain.MetadataVersion >= 27f))
            {
                //Pre-v27, mscorlib is the first codegen module, so *MscorlibCodegenEntryInCodegenModulesList == g_CodegenModules, so we can just find a pointer to this.
                var intermediate = pMscorlibCodegenEntryInCodegenModulesList;
                pCodegenModules = FindAllMappedWords(intermediate);
            }
            else
            {
                //but in v27 it's close to the LAST codegen module (winrt.dll is an exception), so we need to work back until we find an xref.
                var sanityCheckNumberOfModules = 200;
                var pSomewhereInCodegenModules = pMscorlibCodegenEntryInCodegenModulesList;
                var ptrSize = (_pe.is32Bit ? 4u : 8u);
                for (var backtrack = 0; backtrack < sanityCheckNumberOfModules && (pCodegenModules?.Count() ?? 0) != 1; backtrack++)
                {
                    pCodegenModules = FindAllMappedWords(pSomewhereInCodegenModules);

                    //Sanity check the count, which is one pointer back
                    if (pCodegenModules.Count() == 1)
                    {
                        var moduleCount = _pe.ReadClassAtVirtualAddress <int>(pCodegenModules.First() - ptrSize);

                        if (moduleCount < 0 || moduleCount > sanityCheckNumberOfModules)
                        {
                            pCodegenModules = Enumerable.Empty <ulong>();
                        }
                    }

                    pSomewhereInCodegenModules = pSomewhereInCodegenModules.Select(va => va - ptrSize);
                }

                if (!pCodegenModules.Any())
                {
                    throw new Exception("Failed to find pCodegenModules");
                }

                if (pCodegenModules.Count() > 1)
                {
                    throw new Exception("Found more than 1 pointer as pCodegenModules");
                }
            }

            if (!_pe.is32Bit)
            {
                var codeGenAddr     = pCodegenModules.First();
                var textSection     = _pe.sections.First(s => s.Name == ".text");
                var toDisasm        = _pe.raw.SubArray((int)textSection.PointerToRawData, (int)textSection.SizeOfRawData);
                var allInstructions = LibCpp2ILUtils.DisassembleBytesNew(_pe.is32Bit, toDisasm, textSection.VirtualAddress + _pe.imageBase);

                var allSensibleInstructions = allInstructions.Where(i =>
                                                                    i.Mnemonic == Mnemonic.Lea &&
                                                                    i.OpCount == 2 &&
                                                                    i.Op0Kind == OpKind.Register &&
                                                                    i.Op1Kind == OpKind.Memory
                                                                    /*&& i.Op0Register == Register.RCX*/).ToList();

                var sanity = 0;
                while (sanity++ < 500)
                {
                    var instruction = allSensibleInstructions.FirstOrDefault(i =>
                                                                             i.GetRipBasedInstructionMemoryAddress() == codeGenAddr
                                                                             );

                    if (instruction != default)
                    {
                        return(codeGenAddr);
                    }

                    codeGenAddr -= 8; //Always 64-bit here so IntPtr is 8
                }

                return(0);
            }
            else
            {
                IEnumerable <ulong>?codeRegVas = null;
                var sanity = 0;
                while ((codeRegVas?.Count() ?? 0) != 1)
                {
                    if (sanity++ > 500)
                    {
                        break;
                    }

                    pCodegenModules = pCodegenModules.Select(va => va - 4);
                    codeRegVas      = FindAllMappedWords(pCodegenModules).AsParallel().ToList();
                }

                if (pCodegenModules.Count() != 1)
                {
                    return(0ul);
                }

                return(pCodegenModules.First());
            }
        }