Exemple #1
0
        private LinkedList <Instruction[]> SpiltStatements(InstrBlock block, MethodTrace trace, CFContext ctx)
        {
            var statements       = new LinkedList <Instruction[]>();
            var currentStatement = new List <Instruction>();

            for (int i = 0; i < block.Instructions.Count; i++)
            {
                Instruction instr = block.Instructions[i];
                currentStatement.Add(instr);

                bool nextIsBrTarget = i + 1 < block.Instructions.Count && trace.IsBranchTarget(trace.OffsetToIndexMap(block.Instructions[i + 1].Offset));

                if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStackDepths[trace.OffsetToIndexMap(instr.Offset)] == 0) &&
                    (nextIsBrTarget || ctx.Intensity > ctx.Random.NextDouble()))
                {
                    statements.AddLast(currentStatement.ToArray());
                    currentStatement.Clear();
                }
            }

            if (currentStatement.Count > 0)
            {
                statements.AddLast(currentStatement.ToArray());
            }

            return(statements);
        }
Exemple #2
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);
            }
        }