Exemplo n.º 1
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            body.MaxStack++;
            foreach (InstrBlock block in GetAllBlocks(root)) {
                LinkedList<Instruction[]> fragments = SpiltFragments(block, ctx);
                if (fragments.Count < 4) continue;

                LinkedListNode<Instruction[]> current = fragments.First;
                while (current.Next != null) {
                    var newFragment = new List<Instruction>(current.Value);
                    ctx.AddJump(newFragment, current.Next.Value[0]);
                    ctx.AddJunk(newFragment);
                    current.Value = newFragment.ToArray();
                    current = current.Next;
                }
                Instruction[] first = fragments.First.Value;
                fragments.RemoveFirst();
                Instruction[] last = fragments.Last.Value;
                fragments.RemoveLast();

                List<Instruction[]> newFragments = fragments.ToList();
                ctx.Random.Shuffle(newFragments);

                block.Instructions = first
                    .Concat(newFragments.SelectMany(fragment => fragment))
                    .Concat(last).ToList();
            }
        }
Exemplo n.º 2
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            body.MaxStack++;
            foreach (InstrBlock block in GetAllBlocks(root))
            {
                LinkedList <Instruction[]> fragments = SpiltFragments(block, ctx);
                if (fragments.Count < 4)
                {
                    continue;
                }

                LinkedListNode <Instruction[]> current = fragments.First;
                while (current.Next != null)
                {
                    var newFragment = new List <Instruction>(current.Value);
                    ctx.AddJump(newFragment, current.Next.Value[0]);
                    ctx.AddJunk(newFragment);
                    current.Value = newFragment.ToArray();
                    current       = current.Next;
                }
                Instruction[] first = fragments.First.Value;
                fragments.RemoveFirst();
                Instruction[] last = fragments.Last.Value;
                fragments.RemoveLast();

                List <Instruction[]> newFragments = fragments.ToList();
                ctx.Random.Shuffle(newFragments);

                block.Instructions = first
                                     .Concat(newFragments.SelectMany(fragment => fragment))
                                     .Concat(last).ToList();
            }
        }
Exemplo n.º 3
0
        void ProcessMethod(CilBody body, CFContext ctx)
        {
            uint maxStack;

            if (!MaxStackCalculator.GetMaxStack(body.Instructions, body.ExceptionHandlers, out maxStack))
            {
                ctx.Context.Logger.Error("Failed to calcuate maxstack.");
                throw new ConfuserException(null);
            }
            body.MaxStack = (ushort)maxStack;
            ScopeBlock root = BlockParser.ParseBody(body);

            GetMangler(ctx.Type).Mangle(body, root, ctx);

            body.Instructions.Clear();
            root.ToBody(body);
            foreach (ExceptionHandler eh in body.ExceptionHandlers)
            {
                var index = body.Instructions.IndexOf(eh.TryEnd) + 1;
                eh.TryEnd     = index < body.Instructions.Count ? body.Instructions[index] : null;
                index         = body.Instructions.IndexOf(eh.HandlerEnd) + 1;
                eh.HandlerEnd = index < body.Instructions.Count ? body.Instructions[index] : null;
            }
            body.KeepOldMaxStack = true;
        }
Exemplo n.º 4
0
		protected static IEnumerable<InstrBlock> GetAllBlocks(ScopeBlock scope) {
			foreach (BlockBase child in scope.Children) {
				if (child is InstrBlock)
					yield return (InstrBlock)child;
				else {
					foreach (InstrBlock block in GetAllBlocks((ScopeBlock)child))
						yield return block;
				}
			}
		}
Exemplo n.º 5
0
 protected static IEnumerable <InstrBlock> GetAllBlocks(ScopeBlock scope)
 {
     foreach (var child in scope.Children)
     {
         if (child is InstrBlock)
         {
             yield return((InstrBlock)child);
         }
         else
         {
             foreach (var block in GetAllBlocks((ScopeBlock)child))
             {
                 yield return(block);
             }
         }
     }
 }
Exemplo n.º 6
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            Trace trace = new Trace(body, ctx.Method.ReturnType.RemoveModifiers().ElementType != ElementType.Void);
            var   local = new Local(ctx.Method.Module.CorLibTypes.UInt32);

            body.Variables.Add(local);
            body.InitLocals = true;

            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 i;

                var keyId = Enumerable.Range(0, statements.Count).ToArray();
                ctx.Random.Shuffle(keyId);
                var key = new int[keyId.Length];
                for (i = 0; i < key.Length; i++)
                {
                    var q = ctx.Random.NextInt32() & 0x7fffffff;
                    key[i] = q - q % statements.Count + keyId[i];
                }

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

                var statementLast = new HashSet <Instruction>(statements.Select(st => st.Last()));

                Func <IList <Instruction>, bool> hasUnknownSource;
                hasUnknownSource = instrs => instrs.Any(instr =>
                {
                    if (trace.HasMultipleSources(instr.Offset))
                    {
                        return(true);
                    }
                    List <Instruction> srcs;
                    if (trace.BrRefs.TryGetValue(instr.Offset, out srcs))
                    {
                        // Target of switch => assume unknown
                        if (srcs.Any(src => src.Operand is Instruction[]))
                        {
                            return(true);
                        }

                        // Not within current instruction block / targeted in first statement
                        if (srcs.Any(src => src.Offset <= statements.First.Value.Last().Offset ||
                                     src.Offset >= block.Instructions.Last().Offset))
                        {
                            return(true);
                        }

                        // Not targeted by the last of statements
                        if (srcs.Any(src => statementLast.Contains(src)))
                        {
                            return(true);
                        }
                    }
                    return(false);
                });

                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(Instruction.Create(OpCodes.Dup));
                switchHdr.Add(Instruction.Create(OpCodes.Stloc, local));
                switchHdr.Add(Instruction.Create(OpCodes.Ldc_I4, statements.Count));
                switchHdr.Add(Instruction.Create(OpCodes.Rem_Un));
                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(newStatement.Last().Offset) &&
                                statementKeys.TryGetValue(target, out brKey))
                            {
                                var targetKey = predicate != null?predicate.GetSwitchKey(brKey) : brKey;

                                var unkSrc = hasUnknownSource(newStatement);

                                newStatement.RemoveAt(newStatement.Count - 1);

                                if (unkSrc)
                                {
                                    newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
                                }
                                else
                                {
                                    var thisKey = key[i];
                                    var r       = ctx.Random.NextInt32();
                                    newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                    newStatement.Add(Instruction.CreateLdcI4(r));
                                    newStatement.Add(Instruction.Create(OpCodes.Mul));
                                    newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
                                    newStatement.Add(Instruction.Create(OpCodes.Xor));
                                }

                                ctx.AddJump(newStatement, switchHdr[1]);
                                ctx.AddJunk(newStatement);
                                operands[keyId[i]] = newStatement[0];
                                converted          = true;
                            }
                        }
                        else if (newStatement.Last().IsConditionalBranch())
                        {
                            // Conditional

                            var target = (Instruction)newStatement.Last().Operand;
                            int brKey;
                            if (!trace.IsBranchTarget(newStatement.Last().Offset) &&
                                statementKeys.TryGetValue(target, out brKey))
                            {
                                bool   unkSrc  = hasUnknownSource(newStatement);
                                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;
                                }

                                var thisKey = key[i];
                                int r = 0, xorKey = 0;
                                if (!unkSrc)
                                {
                                    r      = ctx.Random.NextInt32();
                                    xorKey = thisKey * r;
                                }

                                Instruction brKeyInstr   = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(brKey) : brKey));
                                Instruction nextKeyInstr = Instruction.CreateLdcI4(xorKey ^ (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);

                                if (!unkSrc)
                                {
                                    newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                    newStatement.Add(Instruction.CreateLdcI4(r));
                                    newStatement.Add(Instruction.Create(OpCodes.Mul));
                                    newStatement.Add(Instruction.Create(OpCodes.Xor));
                                }

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

                        if (!converted)
                        {
                            // Normal

                            var targetKey = predicate != null?predicate.GetSwitchKey(key[i + 1]) : key[i + 1];

                            if (!hasUnknownSource(newStatement))
                            {
                                var thisKey = key[i];
                                var r       = ctx.Random.NextInt32();
                                newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                newStatement.Add(Instruction.CreateLdcI4(r));
                                newStatement.Add(Instruction.Create(OpCodes.Mul));
                                newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
                                newStatement.Add(Instruction.Create(OpCodes.Xor));
                            }
                            else
                            {
                                newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
                            }

                            ctx.AddJump(newStatement, switchHdr[1]);
                            ctx.AddJunk(newStatement);
                            operands[keyId[i]] = newStatement[0];
                        }
                    }
                    else
                    {
                        operands[keyId[i]] = switchHdr[0];
                    }

                    current.Value = newStatement.ToArray();
                    current       = current.Next;
                    i++;
                }
                operands[keyId[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);
            }
        }
Exemplo n.º 7
0
 public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx);
Exemplo n.º 8
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            Trace trace = new Trace(body, ctx.Method.ReturnType.RemoveModifiers().ElementType != ElementType.Void);
            var local = new Local(ctx.Method.Module.CorLibTypes.UInt32);
            body.Variables.Add(local);
            body.InitLocals = true;

            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 i;

                var keyId = Enumerable.Range(0, statements.Count).ToArray();
                ctx.Random.Shuffle(keyId);
                var key = new int[keyId.Length];
                for (i = 0; i < key.Length; i++) {
                    var q = ctx.Random.NextInt32() & 0x7fffffff;
                    key[i] = q - q % statements.Count + keyId[i];
                }

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

                var statementLast = new HashSet<Instruction>(statements.Select(st => st.Last()));

                Func<IList<Instruction>, bool> hasUnknownSource;
                hasUnknownSource = instrs => instrs.Any(instr => {
                    if (trace.HasMultipleSources(instr.Offset))
                        return true;
                    List<Instruction> srcs;
                    if (trace.BrRefs.TryGetValue(instr.Offset, out srcs)) {
                        // Target of switch => assume unknown
                        if (srcs.Any(src => src.Operand is Instruction[]))
                            return true;

                        // Not within current instruction block / targeted in first statement
                        if (srcs.Any(src => src.Offset <= statements.First.Value.Last().Offset ||
                                            src.Offset >= block.Instructions.Last().Offset))
                            return true;

                        // Not targeted by the last of statements
                        if (srcs.Any(src => statementLast.Contains(src)))
                            return true;
                    }
                    return false;
                });

                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(Instruction.Create(OpCodes.Dup));
                switchHdr.Add(Instruction.Create(OpCodes.Stloc, local));
                switchHdr.Add(Instruction.Create(OpCodes.Ldc_I4, statements.Count));
                switchHdr.Add(Instruction.Create(OpCodes.Rem_Un));
                switchHdr.Add(switchInstr);

                if (trace.BeforeStack[statements.Last.Value[0].Offset] == 0)
                {
                    ctx.AddJump(switchHdr, statements.Last.Value[0]);
                }
                else
                {
                    ctx.AddJump(switchHdr, switchHdr[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(newStatement.Last().Offset) &&
                                statementKeys.TryGetValue(target, out brKey)) {

                                if (trace.BeforeStack[target.Offset] == 0)
                                {
                                    var targetKey = predicate != null ? predicate.GetSwitchKey(brKey) : brKey;
                                    var unkSrc = hasUnknownSource(newStatement);

                                    var initialBeforeStack = trace.BeforeStack[newStatement[0].Offset];
                                    newStatement.RemoveAt(newStatement.Count - 1);

                                    if (unkSrc || initialBeforeStack != 0) {
                                        newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
                                    }
                                    else {
                                        var thisKey = key[i];
                                        var r = ctx.Random.NextInt32();
                                        newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                        newStatement.Add(Instruction.CreateLdcI4(r));
                                        newStatement.Add(Instruction.Create(OpCodes.Mul));
                                        newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey * r) ^ targetKey));
                                        newStatement.Add(Instruction.Create(OpCodes.Xor));
                                    }

                                    ctx.AddJump(newStatement, switchHdr[1]);
                                    ctx.AddJunk(newStatement);
                                }

                                if (trace.BeforeStack[newStatement[0].Offset] == 0)
                                {
                                    operands[keyId[i]] = newStatement[0];
                                }

                                converted = true;
                            }
                        }
                        else if (newStatement.Last().IsConditionalBranch()) {
                            // Conditional

                            var target = (Instruction)newStatement.Last().Operand;
                            int brKey;
                            if (!trace.IsBranchTarget(newStatement.Last().Offset) &&
                                statementKeys.TryGetValue(target, out brKey)) {

                                if (trace.BeforeStack[target.Offset] == 0)
                                {
                                    bool unkSrc = hasUnknownSource(newStatement);
                                    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;
                                    }

                                    var thisKey = key[i];
                                    int r = 0, xorKey = 0;
                                    if (!unkSrc) {
                                        r = ctx.Random.NextInt32();
                                        xorKey = thisKey * r;
                                    }

                                    Instruction brKeyInstr = Instruction.CreateLdcI4(xorKey ^ (predicate != null ? predicate.GetSwitchKey(brKey) : brKey));
                                    Instruction nextKeyInstr = Instruction.CreateLdcI4(xorKey ^ (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);

                                    if (!unkSrc) {
                                        newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                        newStatement.Add(Instruction.CreateLdcI4(r));
                                        newStatement.Add(Instruction.Create(OpCodes.Mul));
                                        newStatement.Add(Instruction.Create(OpCodes.Xor));
                                    }

                                    ctx.AddJump(newStatement, switchHdr[1]);
                                    ctx.AddJunk(newStatement);

                                    converted = true;
                                }

                                if (trace.BeforeStack[newStatement[0].Offset] == 0)
                                {
                                    operands[keyId[i]] = newStatement[0];
                                }
                            }
                        }

                        if (!converted) {
                            // Normal

                            if (newStatement[newStatement.Count - 1].OpCode != OpCodes.Ret)
                            {
                                var nextStatement = current.Next;
                                if (trace.BeforeStack[nextStatement.Value[0].Offset] == 0)
                                {
                                    var targetKey = predicate != null ? predicate.GetSwitchKey(key[i + 1]) : key[i + 1];
                                    if (!hasUnknownSource(newStatement) && trace.BeforeStack[newStatement[0].Offset] == 0)
                                    {
                                        var thisKey = key[i];
                                        var r = ctx.Random.NextInt32();
                                        newStatement.Add(Instruction.Create(OpCodes.Ldloc, local));
                                        newStatement.Add(Instruction.CreateLdcI4(r));
                                        newStatement.Add(Instruction.Create(OpCodes.Mul));
                                        newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, (thisKey*r) ^ targetKey));
                                        newStatement.Add(Instruction.Create(OpCodes.Xor));
                                    }
                                    else
                                    {
                                        newStatement.Add(Instruction.Create(OpCodes.Ldc_I4, targetKey));
                                    }

                                    ctx.AddJump(newStatement, switchHdr[1]);
                                    ctx.AddJunk(newStatement);
                                }
                                else
                                {
                                    newStatement.Add(Instruction.Create(OpCodes.Br, nextStatement.Value[0]));
                                }
                            }

                            if (trace.BeforeStack[newStatement[0].Offset] == 0)
                            {
                                operands[keyId[i]] = newStatement[0];
                            }
                        }
                    }
                    else
                        operands[keyId[i]] = switchHdr[0];

                    current.Value = newStatement.ToArray();
                    current = current.Next;
                    i++;
                }

                if (trace.BeforeStack[current.Value[0].Offset] == 0)
                {
                    operands[keyId[i]] = current.Value[0];
                }

                for (i = 0; i < operands.Length; i++)
                {
                    if (operands[i] == null)
                    {
                        operands[i] = switchHdr[0];
                    }
                }

                switchInstr.Operand = operands;

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

                List<Instruction[]> newStatements = statements.Where(s => trace.BeforeStack[s[0].Offset] == 0).ToList();
                ctx.Random.Shuffle(newStatements);

                List<Instruction[]> newOrderedStatements = statements.Where(s => trace.BeforeStack[s[0].Offset] != 0).ToList();

                block.Instructions.Clear();
                block.Instructions.AddRange(first);
                block.Instructions.AddRange(switchHdr);
                foreach (var statement in newStatements)
                    block.Instructions.AddRange(statement);
                foreach (var statement in newOrderedStatements)
                    block.Instructions.AddRange(statement);
                block.Instructions.AddRange(last);
            }
        }
Exemplo n.º 9
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);
            }
        }
Exemplo n.º 10
0
        public static ScopeBlock ParseBody(CilBody body)
        {
            var ehScopes = new Dictionary <ExceptionHandler, Tuple <ScopeBlock, ScopeBlock, ScopeBlock> >();

            foreach (ExceptionHandler eh in body.ExceptionHandlers)
            {
                var tryBlock = new ScopeBlock(BlockType.Try, eh);

                var handlerType = BlockType.Handler;

                if (eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    handlerType = BlockType.Finally;
                }
                else if (eh.HandlerType == ExceptionHandlerType.Fault)
                {
                    handlerType = BlockType.Fault;
                }

                var handlerBlock = new ScopeBlock(handlerType, eh);

                if (eh.FilterStart != null)
                {
                    var filterBlock = new ScopeBlock(BlockType.Filter, eh);
                    ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, filterBlock);
                }
                else
                {
                    ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, (ScopeBlock)null);
                }
            }

            var root       = new ScopeBlock(BlockType.Normal, null);
            var scopeStack = new Stack <ScopeBlock>();

            scopeStack.Push(root);
            foreach (Instruction instr in body.Instructions)
            {
                foreach (ExceptionHandler eh in body.ExceptionHandlers)
                {
                    Tuple <ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh];

                    if (instr == eh.TryEnd)
                    {
                        scopeStack.Pop();
                    }

                    if (instr == eh.HandlerEnd)
                    {
                        scopeStack.Pop();
                    }

                    if (eh.FilterStart != null && instr == eh.HandlerStart)
                    {
                        // Filter must precede handler immediately
                        Debug.Assert(scopeStack.Peek().Type == BlockType.Filter);
                        scopeStack.Pop();
                    }
                }
                foreach (ExceptionHandler eh in body.ExceptionHandlers.Reverse())
                {
                    Tuple <ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh];
                    ScopeBlock parent = scopeStack.Count > 0 ? scopeStack.Peek() : null;

                    if (instr == eh.TryStart)
                    {
                        parent?.Children.Add(ehScope.Item1);
                        scopeStack.Push(ehScope.Item1);
                    }

                    if (instr == eh.HandlerStart)
                    {
                        parent?.Children.Add(ehScope.Item2);
                        scopeStack.Push(ehScope.Item2);
                    }

                    if (instr == eh.FilterStart)
                    {
                        parent?.Children.Add(ehScope.Item3);
                        scopeStack.Push(ehScope.Item3);
                    }
                }

                ScopeBlock scope = scopeStack.Peek();
                if (!(scope.Children.LastOrDefault() is InstrBlock block))
                {
                    scope.Children.Add(block = new InstrBlock());
                }
                block.Instructions.Add(instr);
            }
            foreach (ExceptionHandler eh in body.ExceptionHandlers)
            {
                if (eh.TryEnd == null)
                {
                    scopeStack.Pop();
                }
                if (eh.HandlerEnd == null)
                {
                    scopeStack.Pop();
                }
            }
            Debug.Assert(scopeStack.Count == 1);
            return(root);
        }
Exemplo n.º 11
0
 public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx);
Exemplo n.º 12
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);
            }
        }
Exemplo n.º 13
0
		public static ScopeBlock ParseBody(CilBody body) {
			var ehScopes = new Dictionary<ExceptionHandler, Tuple<ScopeBlock, ScopeBlock, ScopeBlock>>();
			foreach (ExceptionHandler eh in body.ExceptionHandlers) {
				var tryBlock = new ScopeBlock(BlockType.Try, eh);

				var handlerType = BlockType.Handler;

				if (eh.HandlerType == ExceptionHandlerType.Finally)
					handlerType = BlockType.Finally;
				else if (eh.HandlerType == ExceptionHandlerType.Fault)
					handlerType = BlockType.Fault;

				var handlerBlock = new ScopeBlock(handlerType, eh);

				if (eh.FilterStart != null) {
					var filterBlock = new ScopeBlock(BlockType.Filter, eh);
					ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, filterBlock);
				}
				else
					ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, (ScopeBlock)null);
			}

			var root = new ScopeBlock(BlockType.Normal, null);
			var scopeStack = new Stack<ScopeBlock>();

			scopeStack.Push(root);
			foreach (Instruction instr in body.Instructions) {
				foreach (ExceptionHandler eh in body.ExceptionHandlers) {
					Tuple<ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh];

					if (instr == eh.TryEnd)
						scopeStack.Pop();

					if (instr == eh.HandlerEnd)
						scopeStack.Pop();

					if (eh.FilterStart != null && instr == eh.HandlerStart) {
						// Filter must precede handler immediately
						Debug.Assert(scopeStack.Peek().Type == BlockType.Filter);
						scopeStack.Pop();
					}
				}
				foreach (ExceptionHandler eh in body.ExceptionHandlers.Reverse()) {
					Tuple<ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh];
					ScopeBlock parent = scopeStack.Count > 0 ? scopeStack.Peek() : null;

					if (instr == eh.TryStart) {
						if (parent != null)
							parent.Children.Add(ehScope.Item1);
						scopeStack.Push(ehScope.Item1);
					}

					if (instr == eh.HandlerStart) {
						if (parent != null)
							parent.Children.Add(ehScope.Item2);
						scopeStack.Push(ehScope.Item2);
					}

					if (instr == eh.FilterStart) {
						if (parent != null)
							parent.Children.Add(ehScope.Item3);
						scopeStack.Push(ehScope.Item3);
					}
				}

				ScopeBlock scope = scopeStack.Peek();
				var block = scope.Children.LastOrDefault() as InstrBlock;
				if (block == null)
					scope.Children.Add(block = new InstrBlock());
				block.Instructions.Add(instr);
			}
			foreach (ExceptionHandler eh in body.ExceptionHandlers) {
				if (eh.TryEnd == null)
					scopeStack.Pop();
				if (eh.HandlerEnd == null)
					scopeStack.Pop();
			}
			Debug.Assert(scopeStack.Count == 1);
			return root;
		}