private XElement GetAllInfoMethod(MethodTrace methodTrace)
        {
            var result = GetInfoMethod(methodTrace);

            foreach (var nestedMethod in methodTrace.NestedMethods)
            {
                result.Add(GetAllInfoMethod(nestedMethod));
            }

            return(result);
        }
        private XElement GetInfoMethod(MethodTrace methodTrace)
        {
            var result = new XElement("method");

            result.Add(new XAttribute("name", methodTrace.Metadata.Name));
            result.Add(new XAttribute("time", methodTrace.GetExecutionTime()));
            result.Add(new XAttribute("class", methodTrace.Metadata.ClassName));
            result.Add(new XAttribute("params", methodTrace.Metadata.CountParameters));

            return(result);
        }
        private void WriteMethodInfo(MethodTrace methodInfo, int nestingLevel = 0)
        {
            var nesting = new string('\t', nestingLevel);

            Console.WriteLine($"{nesting}Method name: {methodInfo.Metadata.Name}; time: {methodInfo.GetExecutionTime()}; " +
                              $" class: {methodInfo.Metadata.ClassName}; params: {methodInfo.Metadata.CountParameters}");

            foreach (var nestedMethod in methodInfo.NestedMethods)
            {
                WriteMethodInfo(nestedMethod, nestingLevel + 1);
            }
        }
示例#4
0
        /// <summary>
        ///     Replaces the placeholder call in method with actual instruction sequence.
        /// </summary>
        /// <param name="method">The methodto process.</param>
        /// <param name="repl">The function replacing the argument of placeholder call with actual instruction sequence.</param>
        public static void ReplacePlaceholder(MethodDef method, Func <Instruction[], Instruction[]> repl)
        {
            MethodTrace trace = new MethodTrace(method).Trace();

            for (int i = 0; i < method.Body.Instructions.Count; i++)
            {
                Instruction instr = method.Body.Instructions[i];
                if (instr.OpCode == OpCodes.Call)
                {
                    var operand = (IMethod)instr.Operand;
                    if (operand.DeclaringType.FullName == mutationType &&
                        operand.Name == "Placeholder")
                    {
                        var initialLoadInstructions = new List <Instruction>();
                        var pendingInstructions     = new Queue <Instruction>();
                        pendingInstructions.Enqueue(instr);
                        while (pendingInstructions.Count > 0)
                        {
                            var   currentInstr = pendingInstructions.Dequeue();
                            int[] argIndexes   = trace.TraceArguments(currentInstr);
                            if (argIndexes == null)
                            {
                                throw new ArgumentException("Failed to trace placeholder argument.");
                            }

                            if (argIndexes.Length == 0)
                            {
                                initialLoadInstructions.Add(currentInstr);
                            }

                            foreach (int argIndex in argIndexes)
                            {
                                pendingInstructions.Enqueue(method.Body.Instructions[argIndex]);
                            }
                        }

                        var           firstArgIndex = initialLoadInstructions.Select(method.Body.Instructions.IndexOf).Min();
                        Instruction[] arg           = method.Body.Instructions.Skip(firstArgIndex).Take(i - firstArgIndex).ToArray();
                        for (int j = 0; j < arg.Length; j++)
                        {
                            method.Body.Instructions.RemoveAt(firstArgIndex);
                        }
                        method.Body.Instructions.RemoveAt(firstArgIndex);
                        arg = repl(arg);
                        for (int j = arg.Length - 1; j >= 0; j--)
                        {
                            method.Body.Instructions.Insert(firstArgIndex, arg[j]);
                        }
                        return;
                    }
                }
            }
        }
示例#5
0
        private static XElement FormMethodData(MethodTrace methodTrace)
        {
            var result = new XElement("method");

            result.Add(new XAttribute("name", methodTrace.name));
            result.Add(new XAttribute("time", methodTrace.time));
            result.Add(new XAttribute("class", methodTrace.classname));

            foreach (MethodTrace nestedMethodTrace in methodTrace._nestedStack)
            {
                result.Add(FormMethodData(nestedMethodTrace));
            }

            return(result);
        }
        private string DisplayMethods(MethodTrace mth, int level = 0)
        {
            StringBuilder str = new StringBuilder();
            string        tab = string.Format($"{{0, {level * 4 + 1}}}", string.Empty);

            str.AppendLine($"{tab}method: {mth.name}");
            str.AppendLine($"{tab}class: {mth.classname}");
            str.AppendLine($"{tab}time: {mth.time} ms");

            foreach (MethodTrace nestedmth in mth._nestedStack)
            {
                str.AppendLine(DisplayMethods(nestedmth, level + 1));
            }

            return(str.ToString());
        }
        private MethodtoJson TransformMethodInfo(MethodTrace methodTrace)
        {
            MethodtoJson mth = new MethodtoJson();

            mth.name      = methodTrace.name;
            mth.classname = methodTrace.classname;
            mth.time      = methodTrace.time;
            mth.methods   = new List <MethodtoJson>();
            foreach (MethodTrace nestedMethodTrace in methodTrace._nestedStack)
            {
                MethodtoJson nestedmth = TransformMethodInfo(nestedMethodTrace);
                if (nestedmth != null)
                {
                    mth.methods.Add(nestedmth);
                }
            }
            return(mth);
        }
示例#8
0
        public void Analyze(ConfuserContext context, INameService service, ProtectionParameters parameters, IDnlibDef def)
        {
            if (!(def is MethodDef method) || !method.HasBody)
            {
                return;
            }

            var logger = context.Logger;

            var         traceService = context.Registry.GetService <ITraceService>();
            MethodTrace methodTrace  = null;

            var instructions = method.Body.Instructions;

            foreach (var instruction in instructions)
            {
                if (!IsCreateCallSiteInstruction(instruction))
                {
                    continue;
                }

                if (methodTrace is null)
                {
                    methodTrace = traceService.Trace(method);
                }

                // CallSite`1.Create(CallSiteBinder)
                int[] createArguments = methodTrace.TraceArguments(instruction);
                if (createArguments.Length != 1)
                {
                    continue;
                }

                // Binder.InvokeMember(CSharpBinderFlags, string, IEnumerable<Type>, Type, IEnumerable<CSharpArgumentInfo>)
                var binderInstruction = instructions[createArguments[0]];
                if (IsBinderInvokeMember(binderInstruction))
                {
                    HandleBinderInvokeMember(context, method, methodTrace, binderInstruction);
                }
            }
        }
示例#9
0
        /// <summary>
        ///     Replaces the placeholder call in method with actual instruction sequence.
        /// </summary>
        /// <param name="method">The methodto process.</param>
        /// <param name="repl">The function replacing the argument of placeholder call with actual instruction sequence.</param>
        public static void ReplacePlaceholder(MethodDef method, Func <Instruction[], Instruction[]> repl)
        {
            var trace = new MethodTrace(method).Trace();

            for (var i = 0; i < method.Body.Instructions.Count; i++)
            {
                var instr = method.Body.Instructions[i];
                if (instr.OpCode == OpCodes.Call)
                {
                    var operand = (IMethod)instr.Operand;
                    if (operand.DeclaringType.FullName == mutationType &&
                        operand.Name == "Placeholder")
                    {
                        var argIndexes = trace.TraceArguments(instr);
                        if (argIndexes == null)
                        {
                            throw new ArgumentException("Failed to trace placeholder argument.");
                        }

                        var argIndex = argIndexes[0];
                        var arg      = method.Body.Instructions.Skip(argIndex).Take(i - argIndex).ToArray();
                        for (var j = 0; j < arg.Length; j++)
                        {
                            method.Body.Instructions.RemoveAt(argIndex);
                        }

                        method.Body.Instructions.RemoveAt(argIndex);
                        arg = repl(arg);
                        for (var j = arg.Length - 1; j >= 0; j--)
                        {
                            method.Body.Instructions.Insert(argIndex, arg[j]);
                        }

                        return;
                    }
                }
            }
        }
示例#10
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            MethodTrace trace = ctx.Context.Registry.GetService <ITraceService>().Trace(ctx.Method);

            body.MaxStack += 2;
            IPredicate predicate = null;

            if (ctx.Predicate == PredicateType.Normal)
            {
                predicate = new NormalPredicate(ctx);
            }
            else if (ctx.Predicate == PredicateType.Expression)
            {
                predicate = new ExpressionPredicate(ctx);
            }
            else if (ctx.Predicate == PredicateType.x86)
            {
                predicate = new x86Predicate(ctx);
            }

            foreach (InstrBlock block in GetAllBlocks(root))
            {
                LinkedList <Instruction[]> statements = SpiltStatements(block, trace, ctx);

                // Make sure .ctor is executed before switch
                if (ctx.Method.IsInstanceConstructor)
                {
                    var newStatement = new List <Instruction>();
                    while (statements.First != null)
                    {
                        newStatement.AddRange(statements.First.Value);
                        Instruction lastInstr = statements.First.Value.Last();
                        statements.RemoveFirst();
                        if (lastInstr.OpCode == OpCodes.Call && ((IMethod)lastInstr.Operand).Name == ".ctor")
                        {
                            break;
                        }
                    }
                    statements.AddFirst(newStatement.ToArray());
                }

                if (statements.Count < 3)
                {
                    continue;
                }

                int[] key = Enumerable.Range(0, statements.Count).ToArray();
                ctx.Random.Shuffle(key);

                var statementKeys = new Dictionary <Instruction, int>();
                LinkedListNode <Instruction[]> current = statements.First;
                int i = 0;
                while (current != null)
                {
                    if (i != 0)
                    {
                        statementKeys[current.Value[0]] = key[i];
                    }
                    i++;
                    current = current.Next;
                }

                var switchInstr = new Instruction(OpCodes.Switch);

                var switchHdr = new List <Instruction>();

                if (predicate != null)
                {
                    predicate.Init(body);
                    switchHdr.Add(Instruction.CreateLdcI4(predicate.GetSwitchKey(key[1])));
                    predicate.EmitSwitchLoad(switchHdr);
                }
                else
                {
                    switchHdr.Add(Instruction.CreateLdcI4(key[1]));
                }

                switchHdr.Add(switchInstr);

                ctx.AddJump(switchHdr, statements.Last.Value[0]);
                ctx.AddJunk(switchHdr);

                var operands = new Instruction[statements.Count];
                current = statements.First;
                i       = 0;
                while (current.Next != null)
                {
                    var newStatement = new List <Instruction>(current.Value);

                    if (i != 0)
                    {
                        // Convert to switch
                        bool converted = false;

                        if (newStatement.Last().IsBr())
                        {
                            // Unconditional

                            var target = (Instruction)newStatement.Last().Operand;
                            int brKey;
                            if (!trace.IsBranchTarget(trace.OffsetToIndexMap(newStatement.Last().Offset)) &&
                                statementKeys.TryGetValue(target, out brKey))
                            {
                                newStatement.RemoveAt(newStatement.Count - 1);
                                newStatement.Add(Instruction.CreateLdcI4(predicate != null ? predicate.GetSwitchKey(brKey) : brKey));
                                ctx.AddJump(newStatement, switchHdr[1]);
                                ctx.AddJunk(newStatement);
                                operands[key[i]] = newStatement[0];
                                converted        = true;
                            }
                        }
                        else if (newStatement.Last().IsConditionalBranch())
                        {
                            // Conditional

                            var target = (Instruction)newStatement.Last().Operand;
                            int brKey;
                            if (!trace.IsBranchTarget(trace.OffsetToIndexMap(newStatement.Last().Offset)) &&
                                statementKeys.TryGetValue(target, out brKey))
                            {
                                int    nextKey = key[i + 1];
                                OpCode condBr  = newStatement.Last().OpCode;
                                newStatement.RemoveAt(newStatement.Count - 1);

                                if (ctx.Random.NextBoolean())
                                {
                                    condBr = InverseBranch(condBr);
                                    int tmp = brKey;
                                    brKey   = nextKey;
                                    nextKey = tmp;
                                }

                                Instruction brKeyInstr   = Instruction.CreateLdcI4(predicate != null ? predicate.GetSwitchKey(brKey) : brKey);
                                Instruction nextKeyInstr = Instruction.CreateLdcI4(predicate != null ? predicate.GetSwitchKey(nextKey) : nextKey);
                                Instruction pop          = Instruction.Create(OpCodes.Pop);
                                newStatement.Add(Instruction.Create(condBr, brKeyInstr));
                                newStatement.Add(nextKeyInstr);
                                newStatement.Add(Instruction.Create(OpCodes.Dup));
                                newStatement.Add(Instruction.Create(OpCodes.Br, pop));
                                newStatement.Add(brKeyInstr);
                                newStatement.Add(Instruction.Create(OpCodes.Dup));
                                newStatement.Add(pop);

                                ctx.AddJump(newStatement, switchHdr[1]);
                                ctx.AddJunk(newStatement);
                                operands[key[i]] = newStatement[0];
                                converted        = true;
                            }
                        }

                        if (!converted)
                        {
                            // Normal

                            newStatement.Add(Instruction.CreateLdcI4(predicate != null ? predicate.GetSwitchKey(key[i + 1]) : key[i + 1]));
                            ctx.AddJump(newStatement, switchHdr[1]);
                            ctx.AddJunk(newStatement);
                            operands[key[i]] = newStatement[0];
                        }
                    }
                    else
                    {
                        operands[key[i]] = switchHdr[0];
                    }

                    current.Value = newStatement.ToArray();
                    current       = current.Next;
                    i++;
                }
                operands[key[i]]    = current.Value[0];
                switchInstr.Operand = operands;

                Instruction[] first = statements.First.Value;
                statements.RemoveFirst();
                Instruction[] last = statements.Last.Value;
                statements.RemoveLast();

                List <Instruction[]> newStatements = statements.ToList();
                ctx.Random.Shuffle(newStatements);

                block.Instructions.Clear();
                block.Instructions.AddRange(first);
                block.Instructions.AddRange(switchHdr);
                foreach (var statement in newStatements)
                {
                    block.Instructions.AddRange(statement);
                }
                block.Instructions.AddRange(last);
            }
        }
示例#11
0
        private static void HandleBinderInvokeMember(ConfuserContext context, MethodDef method, MethodTrace methodTrace, Instruction instruction)
        {
            var instructions = method.Body.Instructions;

            int[] binderArguments = methodTrace.TraceArguments(instruction);
            if (binderArguments.Length != 5)
            {
                return;
            }

            var nameInstruction    = instructions[binderArguments[1]];
            var contextInstruction = instructions[binderArguments[3]];

            // Name instruction is expected to contain a string constant - This is the name of the invoked member
            if (nameInstruction.OpCode.Code != Code.Ldstr)
            {
                return;
            }
            string boundMemberName = nameInstruction.Operand as string;

            var ldContextTokenInstruction = contextInstruction;

            if (IsGetTypeFromHandle(contextInstruction))
            {
                int[] getTypeFromHandleArguments = methodTrace.TraceArguments(contextInstruction);
                if (getTypeFromHandleArguments.Length == 1)
                {
                    ldContextTokenInstruction = instructions[getTypeFromHandleArguments[0]];
                }
            }

            if (ldContextTokenInstruction.OpCode.Code == Code.Ldtoken &&
                ldContextTokenInstruction.Operand is ITypeDefOrRef typeDefOrRef)
            {
                // We found the load token of the context parameter. This means we know the type the member is called for.
                BuildMemberReferences(context, typeDefOrRef, boundMemberName, nameInstruction);
            }
            else
            {
                context.Logger.WarnFormat(
                    "Failed to resolve type for dynamic invoke member in {0} - blocking all members with name {1} from renaming.",
                    method, boundMemberName);

                // The type referenced is unknown. To be safe, all methods matching the name need to be blocked from renaming.
                DisableRenamingForMethods(context, boundMemberName);
            }
        }
示例#12
0
        private void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method)
        {
            var dpRegInstrs        = new List <Tuple <bool, Instruction> >();
            var routedEvtRegInstrs = new List <Instruction>();

            foreach (Instruction instr in method.Body.Instructions)
            {
                if ((instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt))
                {
                    var regMethod = (IMethod)instr.Operand;

                    if (regMethod.DeclaringType.FullName == "System.Windows.DependencyProperty" &&
                        regMethod.Name.String.StartsWith("Register"))
                    {
                        dpRegInstrs.Add(Tuple.Create(regMethod.Name.String.StartsWith("RegisterAttached"), instr));
                    }
                    else if (regMethod.DeclaringType.FullName == "System.Windows.EventManager" &&
                             regMethod.Name.String == "RegisterRoutedEvent")
                    {
                        routedEvtRegInstrs.Add(instr);
                    }
                }
            }

            if (dpRegInstrs.Count == 0)
            {
                return;
            }

            var         traceSrv = context.Registry.GetService <ITraceService>();
            MethodTrace trace    = traceSrv.Trace(method);

            bool erred = false;

            foreach (var instrInfo in dpRegInstrs)
            {
                int[] args = trace.TraceArguments(instrInfo.Item2);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }
                Instruction ldstr = method.Body.Instructions[args[0]];
                if (ldstr.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var     name     = (string)ldstr.Operand;
                TypeDef declType = method.DeclaringType;
                bool    found    = false;
                if (instrInfo.Item1)                 // Attached DP
                {
                    MethodDef accessor;
                    if ((accessor = declType.FindMethod("Get" + name)) != null && accessor.IsStatic)
                    {
                        service.SetCanRename(accessor, false);
                        found = true;
                    }
                    if ((accessor = declType.FindMethod("Set" + name)) != null && accessor.IsStatic)
                    {
                        service.SetCanRename(accessor, false);
                        found = true;
                    }
                }

                // Normal DP
                // Find CLR property for attached DP as well, because it seems attached DP can be use as normal DP as well.
                PropertyDef property = null;
                if ((property = declType.FindProperty(name)) != null)
                {
                    found = true;
                    if (property.GetMethod != null)
                    {
                        service.SetCanRename(property.GetMethod, false);
                    }

                    if (property.SetMethod != null)
                    {
                        service.SetCanRename(property.SetMethod, false);
                    }

                    if (property.HasOtherMethods)
                    {
                        foreach (MethodDef accessor in property.OtherMethods)
                        {
                            service.SetCanRename(accessor, false);
                        }
                    }
                }
                if (!found)
                {
                    if (instrInfo.Item1)
                    {
                        context.Logger.WarnFormat("Failed to find the accessors of attached dependency property '{0}' in type '{1}'.",
                                                  name, declType.FullName);
                    }
                    else
                    {
                        context.Logger.WarnFormat("Failed to find the CLR property of normal dependency property '{0}' in type '{1}'.",
                                                  name, declType.FullName);
                    }
                }
            }

            erred = false;
            foreach (Instruction instr in routedEvtRegInstrs)
            {
                int[] args = trace.TraceArguments(instr);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }
                Instruction ldstr = method.Body.Instructions[args[0]];
                if (ldstr.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var     name     = (string)ldstr.Operand;
                TypeDef declType = method.DeclaringType;

                EventDef eventDef = null;
                if ((eventDef = declType.FindEvent(name)) == null)
                {
                    context.Logger.WarnFormat("Failed to find the CLR event of routed event '{0}' in type '{1}'.",
                                              name, declType.FullName);
                    continue;
                }
                if (eventDef.AddMethod != null)
                {
                    service.SetCanRename(eventDef.AddMethod, false);
                }

                if (eventDef.RemoveMethod != null)
                {
                    service.SetCanRename(eventDef.RemoveMethod, false);
                }

                if (eventDef.InvokeMethod != null)
                {
                    service.SetCanRename(eventDef.InvokeMethod, false);
                }

                if (eventDef.HasOtherMethods)
                {
                    foreach (MethodDef accessor in eventDef.OtherMethods)
                    {
                        service.SetCanRename(accessor, false);
                    }
                }
            }
        }
示例#13
0
        void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method)
        {
            var binding          = new List <Tuple <bool, Instruction> >();
            var dataPropertyName = new List <Instruction>();

            foreach (var instr in method.Body.Instructions)
            {
                var target = instr.Operand as IMethod;
                switch (instr.OpCode.Code)
                {
                case Code.Call:
                case Code.Callvirt:
                    Debug.Assert(target != null);

                    if ((target.DeclaringType.FullName == "System.Windows.Forms.ControlBindingsCollection" ||
                         target.DeclaringType.FullName == "System.Windows.Forms.BindingsCollection") &&
                        target.Name == "Add" && target.MethodSig.Params.Count != 1)
                    {
                        binding.Add(Tuple.Create(true, instr));
                    }
                    else if (target.DeclaringType.FullName == "System.Windows.Forms.DataGridViewColumn" &&
                             target.Name == "set_DataPropertyName" &&
                             target.MethodSig.Params.Count == 1)
                    {
                        dataPropertyName.Add(instr);
                    }
                    break;

                case Code.Newobj:
                    Debug.Assert(target != null);
                    if (target.DeclaringType.FullName == "System.Windows.Forms.Binding" &&
                        target.Name.String == ".ctor")
                    {
                        binding.Add(Tuple.Create(false, instr));
                    }
                    break;
                }
            }

            if (binding.Count == 0 && dataPropertyName.Count == 0)
            {
                return;
            }

            var         traceSrv = context.Registry.GetService <ITraceService>();
            MethodTrace trace    = traceSrv.Trace(method);

            bool erred = false;

            foreach (var instrInfo in binding)
            {
                int[] args = trace.TraceArguments(instrInfo.Item2);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var argumentIndex = (instrInfo.Item1 ? 1 : 0);
                var propertyName  = ResolveNameInstruction(method, args, ref argumentIndex);
                if (propertyName.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                }
                else
                {
                    List <PropertyDef> props;
                    if (!properties.TryGetValue((string)propertyName.Operand, out props))
                    {
                        if (!erred)
                        {
                            context.Logger.WarnFormat("Failed to extract target property in '{0}'.", method.FullName);
                        }
                        erred = true;
                    }
                    else
                    {
                        foreach (var property in props)
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }

                argumentIndex += 2;
                var dataMember = ResolveNameInstruction(method, args, ref argumentIndex);
                if (dataMember.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                }
                else
                {
                    List <PropertyDef> props;
                    if (!properties.TryGetValue((string)dataMember.Operand, out props))
                    {
                        if (!erred)
                        {
                            context.Logger.WarnFormat("Failed to extract target property in '{0}'.", method.FullName);
                        }
                        erred = true;
                    }
                    else
                    {
                        foreach (var property in props)
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }
            }

            foreach (var instrInfo in dataPropertyName)
            {
                int[] args = trace.TraceArguments(instrInfo);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var argumentIndex = 1;
                var propertyName  = ResolveNameInstruction(method, args, ref argumentIndex);
                if (propertyName.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                }
                else
                {
                    if (!properties.TryGetValue((string)propertyName.Operand, out var props))
                    {
                        if (!erred)
                        {
                            context.Logger.WarnFormat("Failed to extract target property in '{0}'.", method.FullName);
                        }
                        erred = true;
                    }
                    else
                    {
                        foreach (var property in props)
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }
            }
        }
示例#14
0
        public void Analyze(INameService nameService, ITraceService traceService, IReadOnlyList <ModuleDef> moduleDefs, ILogger logger, MethodDef method)
        {
            if (!method.HasBody)
            {
                return;
            }

            MethodTrace methodTrace = null;

            MethodTrace GetMethodTrace()
            {
                if (methodTrace == null)
                {
                    methodTrace = traceService.Trace(method);
                }
                return(methodTrace);
            }

            foreach (var instr in method.Body.Instructions)
            {
                if (instr.OpCode.Code == Code.Call && instr.Operand is IMethodDefOrRef calledMethod)
                {
                    if (calledMethod.DeclaringType.FullName == "System.Type")
                    {
                        Func <TypeDef, IEnumerable <IMemberDef> > getMember = null;
                        if (calledMethod.Name == nameof(Type.GetMethod))
                        {
                            getMember = t => t.Methods;
                        }
                        else if (calledMethod.Name == nameof(Type.GetField))
                        {
                            getMember = t => t.Fields;
                        }
                        else if (calledMethod.Name == nameof(Type.GetProperty))
                        {
                            getMember = t => t.Properties;
                        }
                        else if (calledMethod.Name == nameof(Type.GetEvent))
                        {
                            getMember = t => t.Events;
                        }
                        else if (calledMethod.Name == nameof(Type.GetMember))
                        {
                            getMember = t => Enumerable.Empty <IMemberDef>().Concat(t.Methods).Concat(t.Fields).Concat(t.Properties).Concat(t.Events);
                        }

                        if (getMember != null)
                        {
                            var trace     = GetMethodTrace();
                            var arguments = trace.TraceArguments(instr);
                            if (arguments == null)
                            {
                                logger.WarnFormat(Resources.ReflectionAnalyzer_Analyze_TracingArgumentsFailed, calledMethod.FullName, method.FullName);
                            }
                            else if (arguments.Length >= 2)
                            {
                                var types = GetReferencedTypes(method.Body.Instructions[arguments[0]], method, trace);
                                var names = GetReferencedNames(method.Body.Instructions[arguments[1]]);

                                if (!types.Any())
                                {
                                    types = moduleDefs.SelectMany(m => m.GetTypes()).ToArray();
                                }

                                foreach (var possibleMethod in types.SelectMany(getMember).Where(m => names.Contains(m.Name)))
                                {
                                    nameService.SetCanRename(possibleMethod, false);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#15
0
        /// <summary>
        /// This method is used to determine the types that are load onto the stack at the referenced instruction.
        /// In case the method is unable to determine all the types reliable, it will return a empty list.
        /// </summary>
        private static IReadOnlyList <TypeDef> GetReferencedTypes(Instruction instruction, MethodDef method, MethodTrace trace)
        {
            if (instruction.OpCode.Code == Code.Call && instruction.Operand is IMethodDefOrRef calledMethod)
            {
                if (calledMethod.DeclaringType.FullName == "System.Type" && calledMethod.Name == "GetTypeFromHandle")
                {
                    var arguments = trace.TraceArguments(instruction);
                    if (arguments.Length == 1)
                    {
                        var ldTokenInstr = method.Body.Instructions[arguments[0]];
                        if (ldTokenInstr.OpCode.Code == Code.Ldtoken && ldTokenInstr.Operand is TypeDef refTypeDef)
                        {
                            return(new List <TypeDef>()
                            {
                                refTypeDef
                            });
                        }
                    }
                }
            }

            return(new List <TypeDef>());
        }
示例#16
0
        void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method)
        {
            var dpRegInstrs        = new List <Tuple <bool, Instruction> >();
            var routedEvtRegInstrs = new List <Instruction>();

            for (int i = 0; i < method.Body.Instructions.Count; i++)
            {
                Instruction instr = method.Body.Instructions[i];
                if ((instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt))
                {
                    var regMethod = (IMethod)instr.Operand;

                    if (regMethod.DeclaringType.FullName == "System.Windows.DependencyProperty" &&
                        regMethod.Name.String.StartsWith("Register"))
                    {
                        dpRegInstrs.Add(Tuple.Create(regMethod.Name.String.StartsWith("RegisterAttached"), instr));
                    }
                    else if (regMethod.DeclaringType.FullName == "System.Windows.EventManager" &&
                             regMethod.Name.String == "RegisterRoutedEvent")
                    {
                        routedEvtRegInstrs.Add(instr);
                    }
                }
                else if (instr.OpCode.Code == Code.Newobj)
                {
                    var methodRef = (IMethod)instr.Operand;

                    if (methodRef.DeclaringType.FullName == "System.Windows.Data.PropertyGroupDescription" &&
                        methodRef.Name == ".ctor" && i - 1 >= 0 && method.Body.Instructions[i - 1].OpCode.Code == Code.Ldstr)
                    {
                        foreach (var property in analyzer.LookupProperty((string)method.Body.Instructions[i - 1].Operand))
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }
                else if (instr.OpCode == OpCodes.Ldstr)
                {
                    var operand = ((string)instr.Operand).ToUpperInvariant();
                    if (operand.EndsWith(".BAML") || operand.EndsWith(".XAML"))
                    {
                        var match = UriPattern.Match(operand);
                        if (match.Success)
                        {
                            operand = match.Groups[1].Value;
                        }
                        else if (operand.Contains("/"))
                        {
                            context.Logger.WarnFormat("[WPF] Fail to extract XAML name from '{0}'.", instr.Operand);
                        }

                        var reference = new BAMLStringReference(instr);
                        operand = operand.TrimStart('/');
                        var baml = operand.Substring(0, operand.Length - 5) + ".BAML";
                        var xaml = operand.Substring(0, operand.Length - 5) + ".XAML";
                        bamlRefs.AddListEntry(baml, reference);
                        bamlRefs.AddListEntry(xaml, reference);
                    }
                }
            }

            if (dpRegInstrs.Count == 0)
            {
                return;
            }

            var         traceSrv = context.Registry.GetService <ITraceService>();
            MethodTrace trace    = traceSrv.Trace(method);

            bool erred = false;

            foreach (var instrInfo in dpRegInstrs)
            {
                int[] args = trace.TraceArguments(instrInfo.Item2);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }
                Instruction ldstr = method.Body.Instructions[args[0]];
                if (ldstr.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var     name     = (string)ldstr.Operand;
                TypeDef declType = method.DeclaringType;
                bool    found    = false;
                if (instrInfo.Item1)                 // Attached DP
                {
                    MethodDef accessor;
                    if ((accessor = declType.FindMethod("Get" + name)) != null && accessor.IsStatic)
                    {
                        service.SetCanRename(accessor, false);
                        found = true;
                    }
                    if ((accessor = declType.FindMethod("Set" + name)) != null && accessor.IsStatic)
                    {
                        service.SetCanRename(accessor, false);
                        found = true;
                    }
                }

                // Normal DP
                // Find CLR property for attached DP as well, because it seems attached DP can be use as normal DP as well.
                PropertyDef property = null;
                if ((property = declType.FindProperty(name)) != null)
                {
                    service.SetCanRename(property, false);

                    found = true;
                    if (property.GetMethod != null)
                    {
                        service.SetCanRename(property.GetMethod, false);
                    }

                    if (property.SetMethod != null)
                    {
                        service.SetCanRename(property.SetMethod, false);
                    }

                    if (property.HasOtherMethods)
                    {
                        foreach (MethodDef accessor in property.OtherMethods)
                        {
                            service.SetCanRename(accessor, false);
                        }
                    }
                }
                if (!found)
                {
                    if (instrInfo.Item1)
                    {
                        context.Logger.WarnFormat("Failed to find the accessors of attached dependency property '{0}' in type '{1}'.",
                                                  name, declType.FullName);
                    }
                    else
                    {
                        context.Logger.WarnFormat("Failed to find the CLR property of normal dependency property '{0}' in type '{1}'.",
                                                  name, declType.FullName);
                    }
                }
            }

            erred = false;
            foreach (Instruction instr in routedEvtRegInstrs)
            {
                int[] args = trace.TraceArguments(instr);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }
                Instruction ldstr = method.Body.Instructions[args[0]];
                if (ldstr.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                var     name     = (string)ldstr.Operand;
                TypeDef declType = method.DeclaringType;

                EventDef eventDef = null;
                if ((eventDef = declType.FindEvent(name)) == null)
                {
                    context.Logger.WarnFormat("Failed to find the CLR event of routed event '{0}' in type '{1}'.",
                                              name, declType.FullName);
                    continue;
                }
                service.SetCanRename(eventDef, false);

                if (eventDef.AddMethod != null)
                {
                    service.SetCanRename(eventDef.AddMethod, false);
                }

                if (eventDef.RemoveMethod != null)
                {
                    service.SetCanRename(eventDef.RemoveMethod, false);
                }

                if (eventDef.InvokeMethod != null)
                {
                    service.SetCanRename(eventDef.InvokeMethod, false);
                }

                if (eventDef.HasOtherMethods)
                {
                    foreach (MethodDef accessor in eventDef.OtherMethods)
                    {
                        service.SetCanRename(accessor, false);
                    }
                }
            }
        }
        void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method)
        {
            var binding = new List <Tuple <bool, Instruction> >();

            foreach (Instruction instr in method.Body.Instructions)
            {
                if ((instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt))
                {
                    var target = (IMethod)instr.Operand;

                    if ((target.DeclaringType.FullName == "System.Windows.Forms.ControlBindingsCollection" ||
                         target.DeclaringType.FullName == "System.Windows.Forms.BindingsCollection") &&
                        target.Name == "Add" && target.MethodSig.Params.Count != 1)
                    {
                        binding.Add(Tuple.Create(true, instr));
                    }
                    else if (target.DeclaringType.FullName == "System.Windows.Forms.Binding" &&
                             target.Name.String == ".ctor")
                    {
                        binding.Add(Tuple.Create(false, instr));
                    }
                }
            }

            if (binding.Count == 0)
            {
                return;
            }

            ITraceService traceSrv = context.Registry.GetService <ITraceService>();
            MethodTrace   trace    = traceSrv.Trace(method);

            bool erred = false;

            foreach (Tuple <bool, Instruction> instrInfo in binding)
            {
                int[] args = trace.TraceArguments(instrInfo.Item2);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.LogFormat("WARN: Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                    continue;
                }

                Instruction propertyName = method.Body.Instructions[args[0 + (instrInfo.Item1 ? 1 : 0)]];
                if (propertyName.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.LogFormat("WARN: Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                }
                else
                {
                    if (!properties.TryGetValue((string)propertyName.Operand, out List <PropertyDef> props))
                    {
                        if (!erred)
                        {
                            context.Logger.LogFormat("WARN: Failed to extract target property in '{0}'.", method.FullName);
                        }
                        erred = true;
                    }
                    else
                    {
                        foreach (PropertyDef property in props)
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }

                Instruction dataMember = method.Body.Instructions[args[2 + (instrInfo.Item1 ? 1 : 0)]];
                if (dataMember.OpCode.Code != Code.Ldstr)
                {
                    if (!erred)
                    {
                        context.Logger.LogFormat("WARN: Failed to extract binding property name in '{0}'.", method.FullName);
                    }
                    erred = true;
                }
                else
                {
                    if (!properties.TryGetValue((string)dataMember.Operand, out List <PropertyDef> props))
                    {
                        if (!erred)
                        {
                            context.Logger.LogFormat("WARN: Failed to extract target property in '{0}'.", method.FullName);
                        }
                        erred = true;
                    }
                    else
                    {
                        foreach (PropertyDef property in props)
                        {
                            service.SetCanRename(property, false);
                        }
                    }
                }
            }
        }
        // Token: 0x06000044 RID: 68 RVA: 0x00004ED4 File Offset: 0x000030D4
        private void AnalyzeMethod(ConfuserContext context, INameService service, MethodDef method)
        {
            List <Tuple <bool, Instruction> > dpRegInstrs = new List <Tuple <bool, Instruction> >();
            List <Instruction> routedEvtRegInstrs         = new List <Instruction>();

            foreach (Instruction instr in method.Body.Instructions)
            {
                if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt)
                {
                    IMethod regMethod = (IMethod)instr.Operand;
                    if (regMethod.DeclaringType.FullName == "System.Windows.DependencyProperty" && regMethod.Name.String.StartsWith("Register"))
                    {
                        dpRegInstrs.Add(Tuple.Create <bool, Instruction>(regMethod.Name.String.StartsWith("RegisterAttached"), instr));
                    }
                    else if (regMethod.DeclaringType.FullName == "System.Windows.EventManager" && regMethod.Name.String == "RegisterRoutedEvent")
                    {
                        routedEvtRegInstrs.Add(instr);
                    }
                }
                else if (instr.OpCode == OpCodes.Ldstr)
                {
                    string operand = ((string)instr.Operand).ToUpperInvariant();
                    if (operand.EndsWith(".BAML") || operand.EndsWith(".XAML"))
                    {
                        Match match = WPFAnalyzer.UriPattern.Match(operand);
                        if (match.Success)
                        {
                            operand = match.Groups[1].Value;
                        }
                        BAMLStringReference reference = new BAMLStringReference(instr);
                        operand = operand.TrimStart(new char[]
                        {
                            '/'
                        });
                        string baml = operand.Substring(0, operand.Length - 5) + ".BAML";
                        string xaml = operand.Substring(0, operand.Length - 5) + ".XAML";
                        this.bamlRefs.AddListEntry(baml, reference);
                        this.bamlRefs.AddListEntry(xaml, reference);
                    }
                }
            }
            if (dpRegInstrs.Count == 0)
            {
                return;
            }
            ITraceService traceSrv = context.Registry.GetService <ITraceService>();
            MethodTrace   trace    = traceSrv.Trace(method);
            bool          erred    = false;

            foreach (Tuple <bool, Instruction> instrInfo in dpRegInstrs)
            {
                int[] args = trace.TraceArguments(instrInfo.Item2);
                if (args == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", new object[]
                        {
                            method.FullName
                        });
                    }
                    erred = true;
                }
                else
                {
                    Instruction ldstr = method.Body.Instructions[args[0]];
                    if (ldstr.OpCode.Code != Code.Ldstr)
                    {
                        if (!erred)
                        {
                            context.Logger.WarnFormat("Failed to extract dependency property name in '{0}'.", new object[]
                            {
                                method.FullName
                            });
                        }
                        erred = true;
                    }
                    else
                    {
                        string  name     = (string)ldstr.Operand;
                        TypeDef declType = method.DeclaringType;
                        bool    found    = false;
                        if (instrInfo.Item1)
                        {
                            MethodDef accessor;
                            if ((accessor = declType.FindMethod("Get" + name)) != null && accessor.IsStatic)
                            {
                                service.SetCanRename(accessor, false);
                                found = true;
                            }
                            if ((accessor = declType.FindMethod("Set" + name)) != null && accessor.IsStatic)
                            {
                                service.SetCanRename(accessor, false);
                                found = true;
                            }
                        }
                        PropertyDef property;
                        if ((property = declType.FindProperty(name)) != null)
                        {
                            service.SetCanRename(property, false);
                            found = true;
                            if (property.GetMethod != null)
                            {
                                service.SetCanRename(property.GetMethod, false);
                            }
                            if (property.SetMethod != null)
                            {
                                service.SetCanRename(property.SetMethod, false);
                            }
                            if (property.HasOtherMethods)
                            {
                                foreach (MethodDef accessor2 in property.OtherMethods)
                                {
                                    service.SetCanRename(accessor2, false);
                                }
                            }
                        }
                        if (!found)
                        {
                            if (instrInfo.Item1)
                            {
                                context.Logger.WarnFormat("Failed to find the accessors of attached dependency property '{0}' in type '{1}'.", new object[]
                                {
                                    name,
                                    declType.FullName
                                });
                            }
                            else
                            {
                                context.Logger.WarnFormat("Failed to find the CLR property of normal dependency property '{0}' in type '{1}'.", new object[]
                                {
                                    name,
                                    declType.FullName
                                });
                            }
                        }
                    }
                }
            }
            erred = false;
            foreach (Instruction instr2 in routedEvtRegInstrs)
            {
                int[] args2 = trace.TraceArguments(instr2);
                if (args2 == null)
                {
                    if (!erred)
                    {
                        context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", new object[]
                        {
                            method.FullName
                        });
                    }
                    erred = true;
                }
                else
                {
                    Instruction ldstr2 = method.Body.Instructions[args2[0]];
                    if (ldstr2.OpCode.Code != Code.Ldstr)
                    {
                        if (!erred)
                        {
                            context.Logger.WarnFormat("Failed to extract routed event name in '{0}'.", new object[]
                            {
                                method.FullName
                            });
                        }
                        erred = true;
                    }
                    else
                    {
                        string   name2     = (string)ldstr2.Operand;
                        TypeDef  declType2 = method.DeclaringType;
                        EventDef eventDef;
                        if ((eventDef = declType2.FindEvent(name2)) == null)
                        {
                            context.Logger.WarnFormat("Failed to find the CLR event of routed event '{0}' in type '{1}'.", new object[]
                            {
                                name2,
                                declType2.FullName
                            });
                        }
                        else
                        {
                            service.SetCanRename(eventDef, false);
                            if (eventDef.AddMethod != null)
                            {
                                service.SetCanRename(eventDef.AddMethod, false);
                            }
                            if (eventDef.RemoveMethod != null)
                            {
                                service.SetCanRename(eventDef.RemoveMethod, false);
                            }
                            if (eventDef.InvokeMethod != null)
                            {
                                service.SetCanRename(eventDef.InvokeMethod, false);
                            }
                            if (eventDef.HasOtherMethods)
                            {
                                foreach (MethodDef accessor3 in eventDef.OtherMethods)
                                {
                                    service.SetCanRename(accessor3, false);
                                }
                            }
                        }
                    }
                }
            }
        }