Beispiel #1
0
        LinkedList <Instruction[]> SpiltStatements(InstrBlock block, Trace 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 shouldSpilt = i + 1 < block.Instructions.Count && trace.HasMultipleSources(block.Instructions[i + 1].Offset);
                switch (instr.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                case FlowControl.Cond_Branch:
                case FlowControl.Return:
                case FlowControl.Throw:
                    shouldSpilt = true;
                    break;
                }
                if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStack[instr.Offset] == 0) &&
                    (shouldSpilt || ctx.Intensity > ctx.Random.NextDouble()))
                {
                    statements.AddLast(currentStatement.ToArray());
                    currentStatement.Clear();
                }
            }

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

            return(statements);
        }
Beispiel #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();
            }
        }
        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;
        }
Beispiel #4
0
        private static ITypeDefOrRef sizeOf(CFContext ctx, out int value)
        {
            var aa = ctx.Random.NextInt32(0, 4);

            switch (aa)
            {
            case 0:
                value = 4;
                return(ctx.Method.Module.Import(typeof(int)));

            case 1:
                value = 1;
                return(ctx.Method.Module.Import(typeof(sbyte)));

            case 2:
                value = 16;
                return(ctx.Method.Module.Import(typeof(decimal)));

            case 3:
                value = 8;
                return(ctx.Method.Module.Import(typeof(ulong)));

            case 4:
                value = 8;
                return(ctx.Method.Module.Import(typeof(double)));

            default:
                value = 0;
                return(null);
            }
        }
Beispiel #5
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            body.MaxStack++;
            foreach (var block in GetAllBlocks(root))
            {
                var fragments = SpiltFragments(block, ctx);
                if (fragments.Count < 4)
                {
                    continue;
                }

                var 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;
                }
                var first = fragments.First.Value;
                fragments.RemoveFirst();
                var last = fragments.Last.Value;
                fragments.RemoveLast();

                var newFragments = fragments.ToList();
                ctx.Random.Shuffle(newFragments);

                block.Instructions = first
                                     .Concat(newFragments.SelectMany(fragment => fragment))
                                     .Concat(last).ToList();
            }
        }
Beispiel #6
0
        CFContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RandomGenerator random, bool disableOpti)
        {
            var ret = new CFContext
            {
                Type      = parameters.GetParameter(context, method, "type", CFType.Switch),
                Predicate = parameters.GetParameter(context, method, "predicate", PredicateType.Normal)
            };

            var rawIntensity = parameters.GetParameter(context, method, "intensity", 60);

            ret.Intensity = rawIntensity / 100.0;
            ret.Depth     = parameters.GetParameter(context, method, "depth", 4);

            ret.JunkCode = parameters.GetParameter(context, method, "junk", false) && !disableOpti;

            ret.Protection = (ControlFlowProtection)Parent;
            ret.Random     = random;
            ret.Method     = method;
            ret.Context    = context;
            ret.DynCipher  = context.Registry.GetService <IDynCipherService>();

            if (ret.Predicate == PredicateType.x86)
            {
                if ((context.CurrentModule.Cor20HeaderFlags & ComImageFlags.ILOnly) != 0)
                {
                    context.CurrentModuleWriterOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.ILOnly;
                }
            }

            return(ret);
        }
Beispiel #7
0
        private LinkedList<Instruction[]> SpiltFragments(InstrBlock block, CFContext ctx)
        {
            var fragments = new LinkedList<Instruction[]>();
            var currentFragment = new List<Instruction>();

            int skipCount = -1;
            for (int i = 0; i < block.Instructions.Count; i++) {
                if (skipCount != -1) {
                    if (skipCount > 0) {
                        currentFragment.Add(block.Instructions[i]);
                        skipCount--;
                        continue;
                    }
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();

                    skipCount = -1;
                }

                if (block.Instructions[i].OpCode.OpCodeType == OpCodeType.Prefix) {
                    skipCount = 1;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 2 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Dup &&
                    block.Instructions[i + 1].OpCode.Code == Code.Ldvirtftn &&
                    block.Instructions[i + 2].OpCode.Code == Code.Newobj) {
                    skipCount = 2;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 4 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Ldc_I4 &&
                    block.Instructions[i + 1].OpCode.Code == Code.Newarr &&
                    block.Instructions[i + 2].OpCode.Code == Code.Dup &&
                    block.Instructions[i + 3].OpCode.Code == Code.Ldtoken &&
                    block.Instructions[i + 4].OpCode.Code == Code.Call) // Array initializer
                {
                    skipCount = 4;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 1 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Ldftn &&
                    block.Instructions[i + 1].OpCode.Code == Code.Newobj) {
                    skipCount = 1;
                    currentFragment.Add(block.Instructions[i]);
                }
                currentFragment.Add(block.Instructions[i]);

                if (ctx.Intensity > ctx.Random.NextDouble()) {
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();
                }
            }

            if (currentFragment.Count > 0)
                fragments.AddLast(currentFragment.ToArray());

            return fragments;
        }
Beispiel #8
0
        LinkedList <Instruction[]> SpiltStatements(InstrBlock block, Trace trace, CFContext ctx)
        {
            var statements       = new LinkedList <Instruction[]>();
            var currentStatement = new List <Instruction>();

            // Instructions that must be included in the ccurrent statement to ensure all outgoing
            // branches have stack = 0
            var requiredInstr = new HashSet <Instruction>();

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

                bool shouldSpilt = i + 1 < block.Instructions.Count && trace.HasMultipleSources(block.Instructions[i + 1].Offset);
                switch (instr.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                case FlowControl.Cond_Branch:
                case FlowControl.Return:
                case FlowControl.Throw:
                    if (trace.AfterStack[instr.Offset] != 0)
                    {
                        if (instr.Operand is Instruction)
                        {
                            requiredInstr.Add((Instruction)instr.Operand);
                        }
                        else
                        {
                            foreach (var target in (Instruction[])instr.Operand)
                            {
                                requiredInstr.Add(target);
                            }
                            shouldSpilt = false;
                        }
                    }
                    shouldSpilt = true;
                    break;
                }
                requiredInstr.Remove(instr);
                if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStack[instr.Offset] == 0 &&
                     requiredInstr.Count == 0) &&
                    (shouldSpilt || ctx.Intensity > ctx.Random.NextDouble()))
                {
                    statements.AddLast(currentStatement.ToArray());
                    currentStatement.Clear();
                }
            }

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

            return(statements);
        }
Beispiel #9
0
        LinkedList <Instruction[]> SpiltFragments(InstrBlock block, CFContext ctx)
        {
            var fragments       = new LinkedList <Instruction[]>();
            var currentFragment = new List <Instruction>();

            int skipCount = -1;

            for (int i = 0; i < block.Instructions.Count; i++)
            {
                if (skipCount != -1)
                {
                    if (skipCount > 0)
                    {
                        currentFragment.Add(block.Instructions[i]);
                        skipCount--;
                        continue;
                    }
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();

                    skipCount = -1;
                }

                if (block.Instructions[i].OpCode.OpCodeType == OpCodeType.Prefix)
                {
                    skipCount = 1;
                }
                else if (HasInstructionSeq(block.Instructions, i, Code.Dup, Code.Ldvirtftn, Code.Newobj))
                {
                    skipCount = 2;
                }
                else if (HasInstructionSeq(block.Instructions, i, Code.Ldc_I4, Code.Newarr, Code.Dup, Code.Ldtoken, Code.Call))                  // Array initializer
                {
                    skipCount = 4;
                }
                else if (HasInstructionSeq(block.Instructions, i, Code.Ldftn, Code.Newobj))                  // Create delegate to function
                {
                    skipCount = 1;
                }
                currentFragment.Add(block.Instructions[i]);

                if (skipCount == -1 && ctx.Intensity > ctx.Random.NextDouble())
                {
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();
                }
            }

            if (currentFragment.Count > 0)
            {
                fragments.AddLast(currentFragment.ToArray());
            }

            return(fragments);
        }
Beispiel #10
0
            public void Compile(CFContext ctx)
            {
                var var    = new Variable("{VAR}");
                var result = new Variable("{RESULT}");

                var int32 = ctx.Method.Module.CorLibTypes.Int32;

                native = new MethodDefUser(ctx.Context.Registry.GetService <INameService>().RandomName(), MethodSig.CreateStatic(int32, int32), MethodAttributes.PinvokeImpl | MethodAttributes.PrivateScope | MethodAttributes.Static)
                {
                    ImplAttributes = MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.PreserveSig
                };
                // Attempt to improve performance --- failed with StackOverflowException... :/
                //var suppressAttr = ctx.Method.Module.CorLibTypes.GetTypeRef("System.Security", "SuppressUnmanagedCodeSecurityAttribute").ResolveThrow();
                //native.CustomAttributes.Add(new CustomAttribute((MemberRef)ctx.Method.Module.Import(suppressAttr.FindDefaultConstructor())));
                //native.HasSecurity = true;
                ctx.Method.Module.GlobalType.Methods.Add(native);

                ctx.Context.Registry.GetService <IMarkerService>().Mark(native, ctx.Protection);
                ctx.Context.Registry.GetService <INameService>().SetCanRename(native, false);

                x86Register?reg;
                var         codeGen = new x86CodeGen();

                do
                {
                    ctx.DynCipher.GenerateExpressionPair(
                        ctx.Random,
                        new VariableExpression {
                        Variable = var
                    }, new VariableExpression {
                        Variable = result
                    },
                        ctx.Depth, out expression, out inverse);

                    reg = codeGen.GenerateX86(inverse, (v, r) => { return(new[] { x86Instruction.Create(x86OpCode.POP, new x86RegisterOperand(r)) }); });
                } while (reg == null);

                code = CodeGenUtils.AssembleCode(codeGen, reg.Value);

                expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) })
                              .GenerateCIL(expression)
                              .Compile <Func <int, int> >();


                ctx.Context.CurrentModuleWriterListener.OnWriterEvent += InjectNativeCode;
            }
Beispiel #11
0
		CFContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RandomGenerator random, bool disableOpti) {
			var ret = new CFContext();
			ret.Type = parameters.GetParameter(context, method, "type", CFType.Switch);
			ret.Predicate = parameters.GetParameter(context, method, "predicate", PredicateType.Normal);

			int rawIntensity = parameters.GetParameter(context, method, "intensity", 60);
			ret.Intensity = rawIntensity / 100.0;
			ret.Depth = parameters.GetParameter(context, method, "depth", 4);

			ret.JunkCode = parameters.GetParameter(context, method, "junk", false) && !disableOpti;

			ret.Protection = (ControlFlowProtection)Parent;
			ret.Random = random;
			ret.Method = method;
			ret.Context = context;
			ret.DynCipher = context.Registry.GetService<IDynCipherService>();

			if (ret.Predicate == PredicateType.x86) {
				if ((context.CurrentModule.Cor20HeaderFlags & ComImageFlags.ILOnly) != 0)
					context.CurrentModuleWriterOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.ILOnly;
			}

			return ret;
		}
Beispiel #12
0
			public void Compile(CFContext ctx) {
				var var = new Variable("{VAR}");
				var result = new Variable("{RESULT}");

				CorLibTypeSig int32 = ctx.Method.Module.CorLibTypes.Int32;
				native = new MethodDefUser(ctx.Context.Registry.GetService<INameService>().RandomName(), MethodSig.CreateStatic(int32, int32), MethodAttributes.PinvokeImpl | MethodAttributes.PrivateScope | MethodAttributes.Static);
				native.ImplAttributes = MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.PreserveSig;
				// Attempt to improve performance --- failed with StackOverflowException... :/
				//var suppressAttr = ctx.Method.Module.CorLibTypes.GetTypeRef("System.Security", "SuppressUnmanagedCodeSecurityAttribute").ResolveThrow();
				//native.CustomAttributes.Add(new CustomAttribute((MemberRef)ctx.Method.Module.Import(suppressAttr.FindDefaultConstructor())));
				//native.HasSecurity = true;
				ctx.Method.Module.GlobalType.Methods.Add(native);

				ctx.Context.Registry.GetService<IMarkerService>().Mark(native, ctx.Protection);
				ctx.Context.Registry.GetService<INameService>().SetCanRename(native, false);

				x86Register? reg;
				var codeGen = new x86CodeGen();
				do {
					ctx.DynCipher.GenerateExpressionPair(
						ctx.Random,
						new VariableExpression { Variable = var }, new VariableExpression { Variable = result },
						ctx.Depth, out expression, out inverse);

					reg = codeGen.GenerateX86(inverse, (v, r) => { return new[] { x86Instruction.Create(x86OpCode.POP, new x86RegisterOperand(r)) }; });
				} while (reg == null);

				code = CodeGenUtils.AssembleCode(codeGen, reg.Value);

				expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) })
					.GenerateCIL(expression)
					.Compile<Func<int, int>>();


				ctx.Context.CurrentModuleWriterListener.OnWriterEvent += InjectNativeCode;
			}
Beispiel #13
0
        LinkedList<Instruction[]> SpiltStatements(InstrBlock block, Trace trace, CFContext ctx)
        {
            var statements = new LinkedList<Instruction[]>();
            var currentStatement = new List<Instruction>();

            // Instructions that must be included in the ccurrent statement to ensure all outgoing
            // branches have stack = 0
            var requiredInstr = new HashSet<Instruction>();

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

                bool shouldSpilt = i + 1 < block.Instructions.Count && trace.HasMultipleSources(block.Instructions[i + 1].Offset);
                switch (instr.OpCode.FlowControl) {
                    case FlowControl.Branch:
                    case FlowControl.Cond_Branch:
                    case FlowControl.Return:
                    case FlowControl.Throw:
                        if (trace.AfterStack[instr.Offset] != 0) {
                            if (instr.Operand is Instruction)
                                requiredInstr.Add((Instruction)instr.Operand);
                            else if (instr.Operand is Instruction[]) {
                                foreach (var target in (Instruction[])instr.Operand)
                                    requiredInstr.Add(target);
                                shouldSpilt = false;
                            }
                        }
                        shouldSpilt = true;
                        break;
                }
                requiredInstr.Remove(instr);
                if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStack[instr.Offset] == 0 &&
                     requiredInstr.Count == 0) &&
                    (shouldSpilt || ctx.Intensity > ctx.Random.NextDouble())) {
                    statements.AddLast(currentStatement.ToArray());
                    currentStatement.Clear();
                }
            }

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

            return statements;
        }
        LinkedList<Instruction[]> SpiltStatements(InstrBlock block, Trace 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 shouldSpilt = i + 1 < block.Instructions.Count && trace.HasMultipleSources(block.Instructions[i + 1].Offset);
                switch (instr.OpCode.FlowControl) {
                    case FlowControl.Branch:
                    case FlowControl.Cond_Branch:
                    case FlowControl.Return:
                    case FlowControl.Throw:
                        shouldSpilt = true;
                        break;
                }
                if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && (trace.AfterStack[instr.Offset] == 0 || instr.IsBr())) &&
                    (shouldSpilt || ctx.Intensity > ctx.Random.NextDouble())) {
                    statements.AddLast(currentStatement.ToArray());
                    currentStatement.Clear();
                }
            }

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

            return statements;
        }
        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);
            }
        }
Beispiel #16
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);
            }
        }
 public NormalPredicate(CFContext ctx)
 {
     this.ctx = ctx;
 }
Beispiel #18
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);
        }
 public ExpressionPredicate(CFContext ctx)
 {
     this.ctx = ctx;
 }
Beispiel #20
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;
		}
Beispiel #21
0
 public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx);
Beispiel #22
0
 public x86Predicate(CFContext ctx)
 {
     this.ctx = ctx;
 }
Beispiel #23
0
        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;
        }
 public CodeGen(Local state, CFContext ctx, IList <Instruction> instrs)
     : base(ctx.Method, instrs)
 {
     this.state = state;
 }
Beispiel #25
0
		public NormalPredicate(CFContext ctx) {
			this.ctx = ctx;
		}
Beispiel #26
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);
            }
        }
Beispiel #27
0
 public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx);
Beispiel #28
0
        LinkedList <Instruction[]> SpiltFragments(InstrBlock block, CFContext ctx)
        {
            var fragments       = new LinkedList <Instruction[]>();
            var currentFragment = new List <Instruction>();

            var skipCount = -1;

            for (var i = 0; i < block.Instructions.Count; i++)
            {
                if (skipCount != -1)
                {
                    if (skipCount > 0)
                    {
                        currentFragment.Add(block.Instructions[i]);
                        skipCount--;
                        continue;
                    }
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();

                    skipCount = -1;
                }

                if (block.Instructions[i].OpCode.OpCodeType == OpCodeType.Prefix)
                {
                    skipCount = 1;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 2 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Dup &&
                    block.Instructions[i + 1].OpCode.Code == Code.Ldvirtftn &&
                    block.Instructions[i + 2].OpCode.Code == Code.Newobj)
                {
                    skipCount = 2;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 4 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Ldc_I4 &&
                    block.Instructions[i + 1].OpCode.Code == Code.Newarr &&
                    block.Instructions[i + 2].OpCode.Code == Code.Dup &&
                    block.Instructions[i + 3].OpCode.Code == Code.Ldtoken &&
                    block.Instructions[i + 4].OpCode.Code == Code.Call)                 // Array initializer
                {
                    skipCount = 4;
                    currentFragment.Add(block.Instructions[i]);
                }
                if (i + 1 < block.Instructions.Count &&
                    block.Instructions[i + 0].OpCode.Code == Code.Ldftn &&
                    block.Instructions[i + 1].OpCode.Code == Code.Newobj)
                {
                    skipCount = 1;
                    currentFragment.Add(block.Instructions[i]);
                }
                currentFragment.Add(block.Instructions[i]);

                if (ctx.Intensity > ctx.Random.NextDouble())
                {
                    fragments.AddLast(currentFragment.ToArray());
                    currentFragment.Clear();
                }
            }

            if (currentFragment.Count > 0)
            {
                fragments.AddLast(currentFragment.ToArray());
            }

            return(fragments);
        }
		public ExpressionPredicate(CFContext ctx) {
			this.ctx = ctx;
		}
			public CodeGen(Local state, CFContext ctx, IList<Instruction> instrs)
				: base(ctx.Method, instrs) {
				this.state = state;
			}
Beispiel #31
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);
            }
        }
Beispiel #32
0
		public x86Predicate(CFContext ctx) {
			this.ctx = ctx;
		}