예제 #1
0
        void DecryptMethodsOld(MDTable methodDefTable, ref DumpedMethods dumpedMethods)
        {
            dumpedMethods = new DumpedMethods();
            var decrypter = new Decrypter10(peImage, codeHeader.decryptionKey);

            for (uint rid = 1; rid <= methodDefTable.Rows; rid++)
            {
                var dm = new DumpedMethod();

                var method = (MethodDef)module.ResolveMethod(rid);
                if (method == null || method.DeclaringType == module.GlobalType)
                {
                    continue;
                }

                peImage.ReadMethodTableRowTo(dm, rid);
                if (dm.mdRVA == 0)
                {
                    continue;
                }
                uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

                var mbHeader = decrypter.Decrypt(bodyOffset, out dm.code, out dm.extraSections);
                peImage.UpdateMethodHeaderInfo(dm, mbHeader);

                dumpedMethods.Add(dm);
            }
        }
예제 #2
0
        public SymbolMethod ReadMethodSymbolInfo(int methodMetadataToken)
        {
            var rid      = MDToken.ToRID(methodMetadataToken);
            var mdMethod = _module.ResolveMethod(rid);

            return(_symbolReader.GetMethod(mdMethod, version: 1));
        }
예제 #3
0
        public static IEnumerable <MethodDef> EnumerateAllMethodDefs(this ModuleDefMD moduleDefMd)
        {
            var methodTableLength = moduleDefMd.TablesStream.MethodTable.Rows;

            for (uint rid = 1; rid <= methodTableLength; rid++)
            {
                yield return(moduleDefMd.ResolveMethod(rid));
            }
        }
예제 #4
0
        // Not working for all tokens !

        /*public static IEnumerable<Tuple<Instruction, MethodDef>> FindAllReferences(this MethodDef mDef)
         * {
         *  foreach (
         *      var method in
         *          mDef.Module.Assembly.FindMethods(x => x.HasBody))
         *  {
         *      for (var i = 0; i < method.Body.Instructions.Count; i++)
         *      {
         *          if (method.Body.Instructions[i].OpCode == OpCodes.Call)
         *              if ((method.Body.Instructions[i].Operand as MethodSpec) != null)
         *              {
         *                  var a = method.Body.Instructions[i].Operand as MethodSpec;
         *                  if (a.Method == mDef)
         *                      yield return Tuple.Create(method.Body.Instructions[i], method);
         *              }
         *              else if ((method.Body.Instructions[i].Operand as MethodDef) != null)
         *              {
         *                  var a = method.Body.Instructions[i].Operand as MethodDef;
         *                  if (a == mDef)
         *                      yield return Tuple.Create(method.Body.Instructions[i], method);
         *              }
         *              else if ((method.Body.Instructions[i].Operand as MemberRef != null))
         *              {
         *                  var a = method.Body.Instructions[i].Operand as MemberRef;
         *                  if (a.ResolveMethod() != null)
         *                      yield return Tuple.Create(method.Body.Instructions[i], method);
         *              }
         *      }
         *  }
         * }*/

        // Somehow the other method skipped some references
        // Now we resolve every method by its token and check the instructions, it works this way (but isn't as clean as the other)
        public static IEnumerable <Instruction> FindAllReferences(this MethodDef mDef, ModuleDefMD module)
        {
            var returnList = new List <Instruction>();

            var totalMethods2 = new List <MethodDef>();

            // TODO: Read count dynamically
            for (var i = 1; i < 0x10000; i++)
            {
                var resolved = module.ResolveMethod((uint)i);
                if (resolved == null)
                {
                    continue;
                }

                if (resolved.HasBody)
                {
                    totalMethods2.Add(resolved);
                }
            }

            foreach (
                var method in
                totalMethods2)
            {
                if (!method.HasBody)
                {
                    continue;
                }

                for (var i = 0; i < method.Body.Instructions.Count; i++)
                {
                    if (method.Body.Instructions[i].OpCode == OpCodes.Call)
                    {
                        var currentMethod = method.Body.Instructions[i].Operand as MethodDef;

                        if (currentMethod != null && currentMethod.MDToken.ToInt32() == mDef.MDToken.ToInt32())
                        {
                            returnList.Add(method.Body.Instructions[i]);
                        }

                        var currentMethodSpec = method.Body.Instructions[i].Operand as MethodSpec;
                        if (currentMethodSpec != null && currentMethodSpec.MDToken.ToInt32() == mDef.MDToken.ToInt32())
                        {
                            returnList.Add(method.Body.Instructions[i]);
                        }
                    }
                }
            }

            return(returnList);
        }
        // Token: 0x0600001A RID: 26 RVA: 0x00002D9C File Offset: 0x00000F9C
        public void Analyze(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def)
        {
            ModuleDefMD module = def as ModuleDefMD;

            if (module == null)
            {
                return;
            }
            MDTable table = module.TablesStream.Get(Table.Method);
            uint    len   = table.Rows;

            for (uint i = 1u; i <= len; i += 1u)
            {
                MethodDef methodDef = module.ResolveMethod(i);
                foreach (MethodOverride ov in methodDef.Overrides)
                {
                    this.ProcessMemberRef(context, service, module, ov.MethodBody);
                    this.ProcessMemberRef(context, service, module, ov.MethodDeclaration);
                }
                if (methodDef.HasBody)
                {
                    foreach (Instruction instr in methodDef.Body.Instructions)
                    {
                        if (instr.Operand is MemberRef || instr.Operand is MethodSpec)
                        {
                            this.ProcessMemberRef(context, service, module, (IMemberRef)instr.Operand);
                        }
                    }
                }
            }
            table = module.TablesStream.Get(Table.TypeRef);
            len   = table.Rows;
            for (uint j = 1u; j <= len; j += 1u)
            {
                TypeRef typeRef = module.ResolveTypeRef(j);
                TypeDef typeDef = typeRef.ResolveTypeDefThrow();
                if (typeDef.Module != module && context.Modules.Contains((ModuleDefMD)typeDef.Module))
                {
                    service.AddReference <TypeDef>(typeDef, new TypeRefReference(typeRef, typeDef));
                }
            }
        }
예제 #6
0
        private static void *[] LoadMethodHandles(Module module, ModuleDefMD moduleDef)
        {
            void *[]     methodHandles;
            ModuleHandle moduleHandle;

            methodHandles = new void *[moduleDef.TablesStream.MethodTable.Rows];
            moduleHandle  = module.ModuleHandle;
            for (int i = 0; i < methodHandles.Length; i++)
            {
                MethodDef methodDef;

                methodDef = moduleDef.ResolveMethod((uint)i + 1);
                if (!methodDef.HasBody)
                {
                    continue;
                }
                methodHandles[i] = (void *)moduleHandle.ResolveMethodHandle(0x06000001 + i).Value;
            }
            return(methodHandles);
        }
예제 #7
0
        public MethodSymbol ReadMethodSymbol(int token)
        {
            var method = _moduleDefMd.ResolveMethod((uint)(token & 0x00FFFFFF));

            var stateClassType = GetStateClassType(method);

            if (stateClassType != null)
            {
                var sequencePoints = new List <SequencePoint>();
                if (stateClassType != null)
                {
                    foreach (var typeMethod in stateClassType.Methods)
                    {
                        sequencePoints.AddRange(GetSequencePointsFromMethodBody(typeMethod));
                    }
                }

                sequencePoints.AddRange(GetSequencePointsFromMethodBody(method));
                sequencePoints.Sort((sp1, sp2) => Comparer <int> .Default.Compare(sp1.StartLine, sp2.StartLine));
                return(new MethodSymbol(token, sequencePoints.ToArray()));
            }
            return(new MethodSymbol(token, GetSequencePointsFromMethodBody(method).ToArray()));
        }
        unsafe DumpedMethod decryptMethod(uint token)
        {
            if (!canDecryptMethods())
            {
                throw new ApplicationException("Can't decrypt methods since compileMethod() isn't hooked yet");
            }

            ctx          = new DecryptContext();
            ctx.dm       = new DumpedMethod();
            ctx.dm.token = token;

            ctx.method = dnlibModule.ResolveMethod(MDToken.ToRID(token));
            if (ctx.method == null)
            {
                throw new ApplicationException(string.Format("Could not find method {0:X8}", token));
            }

            byte *mh = (byte *)hInstModule + (uint)ctx.method.RVA;
            byte *code;

            if (mh == (byte *)hInstModule)
            {
                ctx.dm.mhMaxStack       = 0;
                ctx.dm.mhCodeSize       = 0;
                ctx.dm.mhFlags          = 0;
                ctx.dm.mhLocalVarSigTok = 0;
                code = null;
            }
            else if ((*mh & 3) == 2)
            {
                uint headerSize = 1;
                ctx.dm.mhMaxStack       = 8;
                ctx.dm.mhCodeSize       = (uint)(*mh >> 2);
                ctx.dm.mhFlags          = 2;
                ctx.dm.mhLocalVarSigTok = 0;
                code = mh + headerSize;
            }
            else
            {
                uint headerSize = (uint)((mh[1] >> 4) * 4);
                ctx.dm.mhMaxStack       = *(ushort *)(mh + 2);
                ctx.dm.mhCodeSize       = *(uint *)(mh + 4);
                ctx.dm.mhFlags          = *(ushort *)mh;
                ctx.dm.mhLocalVarSigTok = *(uint *)(mh + 8);
                code = mh + headerSize;
            }

            CORINFO_METHOD_INFO info = default(CORINFO_METHOD_INFO);

            info.ILCode     = new IntPtr(code);
            info.ILCodeSize = ctx.dm.mhCodeSize;
            info.maxStack   = ctx.dm.mhMaxStack;
            info.scope      = moduleToDecryptScope;

            initializeOurComp();
            if (code == null)
            {
                ctx.dm.code = new byte[0];
                updateFromMethodDefTableRow();
            }
            else
            {
                callMethodDelegate(*(IntPtr *)jitterVtbl, jitterInstance, ourCompMem, new IntPtr(&info), 0, new IntPtr(0x12345678), new IntPtr(0x3ABCDEF0));
            }

            var dm = ctx.dm;

            ctx = null;
            return(dm);
        }
예제 #9
0
        public static IEnumerable <Instruction> FindAllReferences(this MethodDef mDef, ModuleDefMD module)
        {
            List <Instruction> instructionList = new List <Instruction>();
            List <MethodDef>   methodDefList   = new List <MethodDef>();

            for (int index = 1; index < 65536; ++index)
            {
                MethodDef methodDef = module.ResolveMethod((uint)index);
                if (methodDef != null && methodDef.HasBody)
                {
                    methodDefList.Add(methodDef);
                }
            }
            foreach (MethodDef methodDef in methodDefList)
            {
                if (methodDef.HasBody)
                {
                    for (int index = 0; index < methodDef.Body.Instructions.Count; ++index)
                    {
                        if (methodDef.Body.Instructions[index].OpCode == OpCodes.Call)
                        {
                            MethodDef operand1 = methodDef.Body.Instructions[index].Operand as MethodDef;
                            MDToken   mdToken;
                            int       num1;
                            if (operand1 != null)
                            {
                                mdToken = operand1.MDToken;
                                int int32_1 = mdToken.ToInt32();
                                mdToken = mDef.MDToken;
                                int int32_2 = mdToken.ToInt32();
                                num1 = int32_1 == int32_2 ? 1 : 0;
                            }
                            else
                            {
                                num1 = 0;
                            }
                            if (num1 != 0)
                            {
                                instructionList.Add(methodDef.Body.Instructions[index]);
                            }
                            MethodSpec operand2 = methodDef.Body.Instructions[index].Operand as MethodSpec;
                            int        num2;
                            if (operand2 != null)
                            {
                                mdToken = operand2.MDToken;
                                int int32_1 = mdToken.ToInt32();
                                mdToken = mDef.MDToken;
                                int int32_2 = mdToken.ToInt32();
                                num2 = int32_1 == int32_2 ? 1 : 0;
                            }
                            else
                            {
                                num2 = 0;
                            }
                            if (num2 != 0)
                            {
                                instructionList.Add(methodDef.Body.Instructions[index]);
                            }
                        }
                    }
                }
            }
            return((IEnumerable <Instruction>)instructionList);
        }
예제 #10
0
        static void ParseMethods(TypeDef clazz)
        {
            foreach (var rid in currentModule.Metadata.GetMethodRidList(clazz.Rid))
            {
                var method = currentModule.ResolveMethod(rid);

                if (method == null || method.IsConstructor || method.IsStaticConstructor)
                {
                    continue;
                }

                var methodName = method.Name.Replace("::", "_").Replace("<", "").Replace(">", "").Replace(".", "_").Replace("`", "_");

                if (methodName.Equals("auto") || methodName.Equals("register"))
                {
                    methodName += "_";
                }

                var methodType   = Il2CppTypeToCppType(method.ReturnType);
                var methodOffset = GetMethodOffset(method);

                string methodKey = clazz.Namespace + clazz.FullName + method.Name;
                if (m_DuplicateMethodTable.ContainsKey(methodKey))
                {
                    methodName += "_" + m_DuplicateMethodTable[methodKey]++;
                }
                else
                {
                    m_DuplicateMethodTable.Add(methodKey, 1);
                }

                List <string> methodParams = new List <string>();
                List <string> paramTypes   = new List <string>();
                List <string> paramNames   = new List <string>();

                foreach (var param in method.Parameters)
                {
                    if (param.IsNormalMethodParameter)
                    {
                        var paramType = Il2CppTypeToCppType(param.Type);

                        if (param.HasParamDef)
                        {
                            if (param.ParamDef.IsOut)
                            {
                                paramType += "*";
                            }
                        }

                        if (param.Name.Equals("auto") || param.Name.Equals("register"))
                        {
                            param.Name += "_";
                        }

                        paramTypes.Add(paramType);
                        paramNames.Add(param.Name);

                        methodParams.Add(paramType + " " + param.Name);
                    }
                }

                currentFile.Write(string.Format("\ttemplate <typename T = {0}>", methodType));
                currentFile.WriteLine(string.Format(" {0}{1} {2}({3}) {{", (method.IsStatic ? "static " : ""), "T", methodName, string.Join(", ", methodParams)));
                if (!method.IsStatic)
                {
                    if (methodParams.Count > 0)
                    {
                        currentFile.WriteLine("\t\treturn (({0} (*)({1}*, {2}))(Il2CppBase() + {3}))(this, {4});", "T", FormatToValidClassname(clazz.Name), string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames));
                    }
                    else
                    {
                        currentFile.WriteLine("\t\treturn (({0} (*)({1}*))(Il2CppBase() + {3}))(this);", "T", FormatToValidClassname(clazz.Name), string.Join(", ", paramTypes), methodOffset);
                    }
                }
                else
                {
                    if (methodParams.Count > 0)
                    {
                        currentFile.WriteLine("\t\treturn (({0} (*)(void *, {1}))(Il2CppBase() + {2}))(0, {3});", "T", string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames));
                    }
                    else
                    {
                        currentFile.WriteLine("\t\treturn (({0} (*)(void *))(Il2CppBase() + {2}))(0);", "T", string.Join(", ", paramTypes), methodOffset, string.Join(", ", paramNames));
                    }
                }
                currentFile.WriteLine("\t}");
            }
        }
        public void DecryptString(ref int amount)
        {
            //Checking if the method of decryption list is not empty
            if (DecryptionMeth.Count == 0)
            {
                Console.WriteLine("No decryption method found, please input token of meth : ");
            }
            try
            {
                //Removing 0x
                string corrected = Console.ReadLine().Remove(0, 2);
                //Converting token to rid by substracting 0x06000000
                MethodDef found = module.ResolveMethod(uint.Parse(corrected, System.Globalization.NumberStyles.HexNumber) - 0x06000000);
                Console.WriteLine("Found decryption method : {0}", found.Name);
                //If the method wasn't found, we ask to the use to input one
                DecryptionMeth.Add(found);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            //Looping through the type
            foreach (TypeDef type in module.Types)
            {
                //Looping through the methods
                foreach (MethodDef method in type.Methods)
                {
                    //Checking if method.HasBody
                    if (method.HasBody)
                    {
                        //Now we loop through each instruction
                        for (int i = 0; i < method.Body.Instructions.Count; i++)
                        {
                            /*
                             * [*] First check -> checking if argument is ldstr (most of the time, ldstr become int
                             * so  you have to adapt this part
                             * [*] Second check -> checking if next instr is call (sometimes, the ldstr is not right
                             * after the ldstr, see my toolYano deobfuscator for a more stable version
                             * [*] Third check -> checking if the call is a methoddef
                             * [*] Fourth check -> checking if the method is a decryption method
                             */
                            if (method.Body.Instructions[i].OpCode == OpCodes.Ldstr && method.Body.Instructions[i + 1].OpCode == OpCodes.Call && method.Body.Instructions[i + 1].Operand is MethodDef && DecryptionMeth.Contains((MethodDef)method.Body.Instructions[i + 1].Operand))
                            {
                                //Getting the encrypted string
                                string argument = method.Body.Instructions[i].Operand.ToString();
                                string resolved;
                                if (mode == Mode.Static)
                                {
                                    //decrypting the string
                                    //STATIC APPROACH
                                    resolved = DecryptString(argument);
                                }
                                else
                                {
                                    //DYNAMIC APPROACH
                                    //We grab the methodDef to get its mdtoken
                                    MethodDef toinvoke = (MethodDef)method.Body.Instructions[i + 1].Operand;
                                    //Then we invoke the methodofdecryption to get the string
                                    //It's more reliable but can be dangerous as it loads the assembly which
                                    //may contains virus
                                    resolved = (string)asm.ManifestModule.ResolveMethod(toinvoke.MDToken.ToInt32()).Invoke(null, new object[] { argument });
                                }
                                //Replacing the decrypted string
                                //Here you can use resolve or resolved2, they should be the same
                                method.Body.Instructions[i].Operand = resolved;
                                //Nop the call !! not deleting it !
                                method.Body.Instructions[i + 1].OpCode = OpCodes.Nop;
                                //Printing the decrypted strings
                                amount++;
                                Console.ForegroundColor = ConsoleColor.Green;
                                Console.WriteLine("Decrypted : {0}", resolved);
                                Console.ForegroundColor = ConsoleColor.White;
                            }
                        }
                    }
                }
            }
        }
예제 #12
0
        PdbAsyncMethod CreateAsyncMethod(ModuleDefMD module, MethodDef method, CilBody body, ISymbolMethod2 symMethod)
        {
            var kickoffToken = new MDToken(symMethod.KickoffMethod);

            if (kickoffToken.Table != MD.Table.Method)
            {
                return(null);
            }
            var kickoffMethod = module.ResolveMethod(kickoffToken.Rid);

            var rawStepInfos = symMethod.GetAsyncStepInfos();

            var asyncMethod = new PdbAsyncMethod(rawStepInfos.Length);

            asyncMethod.KickoffMethod = kickoffMethod;

            var catchHandlerILOffset = symMethod.CatchHandlerILOffset;

            if (catchHandlerILOffset != null)
            {
                asyncMethod.CatchHandlerInstruction = GetInstruction(body, catchHandlerILOffset.Value);
                Debug.Assert(asyncMethod.CatchHandlerInstruction != null);
            }

            foreach (var rawInfo in rawStepInfos)
            {
                var yieldInstruction = GetInstruction(body, rawInfo.YieldOffset);
                Debug.Assert(yieldInstruction != null);
                if (yieldInstruction == null)
                {
                    continue;
                }
                MethodDef breakpointMethod;
                Instruction breakpointInstruction;
                if (method.MDToken.Raw == rawInfo.BreakpointMethod)
                {
                    breakpointMethod      = method;
                    breakpointInstruction = GetInstruction(body, rawInfo.BreakpointOffset);
                }
                else
                {
                    var breakpointMethodToken = new MDToken(rawInfo.BreakpointMethod);
                    Debug.Assert(breakpointMethodToken.Table == MD.Table.Method);
                    if (breakpointMethodToken.Table != MD.Table.Method)
                    {
                        continue;
                    }
                    breakpointMethod = module.ResolveMethod(breakpointMethodToken.Rid);
                    Debug.Assert(breakpointMethod != null);
                    if (breakpointMethod == null)
                    {
                        continue;
                    }
                    breakpointInstruction = GetInstruction(breakpointMethod.Body, rawInfo.BreakpointOffset);
                }
                Debug.Assert(breakpointInstruction != null);
                if (breakpointInstruction == null)
                {
                    continue;
                }

                asyncMethod.StepInfos.Add(new PdbAsyncStepInfo(yieldInstruction, breakpointMethod, breakpointInstruction));
            }

            return(asyncMethod);
        }
예제 #13
0
        // Token: 0x0600002B RID: 43 RVA: 0x00003AAC File Offset: 0x00001CAC
        public void Analyze(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def)
        {
            ModuleDefMD module = def as ModuleDefMD;

            if (module == null)
            {
                return;
            }
            MDTable table = module.TablesStream.Get(Table.Method);
            uint    len   = table.Rows;
            IEnumerable <MethodDef> methods = from rid in Enumerable.Range(1, (int)len)
                                              select module.ResolveMethod((uint)rid);

            foreach (MethodDef method in methods)
            {
                foreach (MethodOverride methodImpl in method.Overrides)
                {
                    if (methodImpl.MethodBody is MemberRef)
                    {
                        this.AnalyzeMemberRef(context, service, (MemberRef)methodImpl.MethodBody);
                    }
                    if (methodImpl.MethodDeclaration is MemberRef)
                    {
                        this.AnalyzeMemberRef(context, service, (MemberRef)methodImpl.MethodDeclaration);
                    }
                }
                if (method.HasBody)
                {
                    foreach (Instruction instr in method.Body.Instructions)
                    {
                        if (instr.Operand is MemberRef)
                        {
                            this.AnalyzeMemberRef(context, service, (MemberRef)instr.Operand);
                        }
                        else if (instr.Operand is MethodSpec)
                        {
                            MethodSpec spec = (MethodSpec)instr.Operand;
                            if (spec.Method is MemberRef)
                            {
                                this.AnalyzeMemberRef(context, service, (MemberRef)spec.Method);
                            }
                        }
                    }
                }
            }
            table = module.TablesStream.Get(Table.CustomAttribute);
            len   = table.Rows;
            IEnumerable <CustomAttribute> attrs = (from rid in Enumerable.Range(1, (int)len)
                                                   select module.ResolveHasCustomAttribute(module.TablesStream.ReadCustomAttributeRow((uint)rid).Parent)).Distinct <IHasCustomAttribute>().SelectMany((IHasCustomAttribute owner) => owner.CustomAttributes);

            foreach (CustomAttribute attr in attrs)
            {
                if (attr.Constructor is MemberRef)
                {
                    this.AnalyzeMemberRef(context, service, (MemberRef)attr.Constructor);
                }
                foreach (CAArgument arg in attr.ConstructorArguments)
                {
                    this.AnalyzeCAArgument(context, service, arg);
                }
                foreach (CANamedArgument arg2 in attr.Fields)
                {
                    this.AnalyzeCAArgument(context, service, arg2.Argument);
                }
                foreach (CANamedArgument arg3 in attr.Properties)
                {
                    this.AnalyzeCAArgument(context, service, arg3.Argument);
                }
                TypeDef attrType = attr.AttributeType.ResolveTypeDefThrow();
                if (context.Modules.Contains((ModuleDefMD)attrType.Module))
                {
                    foreach (CANamedArgument fieldArg in attr.Fields)
                    {
                        FieldDef field = attrType.FindField(fieldArg.Name, new FieldSig(fieldArg.Type));
                        if (field == null)
                        {
                            context.Logger.WarnFormat("Failed to resolve CA field '{0}::{1} : {2}'.", new object[]
                            {
                                attrType,
                                fieldArg.Name,
                                fieldArg.Type
                            });
                        }
                        else
                        {
                            service.AddReference <IDnlibDef>(field, new CAMemberReference(fieldArg, field));
                        }
                    }
                    foreach (CANamedArgument propertyArg in attr.Properties)
                    {
                        PropertyDef property = attrType.FindProperty(propertyArg.Name, new PropertySig(true, propertyArg.Type));
                        if (property == null)
                        {
                            context.Logger.WarnFormat("Failed to resolve CA property '{0}::{1} : {2}'.", new object[]
                            {
                                attrType,
                                propertyArg.Name,
                                propertyArg.Type
                            });
                        }
                        else
                        {
                            service.AddReference <IDnlibDef>(property, new CAMemberReference(propertyArg, property));
                        }
                    }
                }
            }
        }