Пример #1
0
 public uint Encode(object data, CEContext ctx, uint id)
 {
     var key = (Tuple<uint, uint>)data;
     uint ret = (id ^ key.Item2) * key.Item1;
     Debug.Assert(((ret * MathsUtils.modInv(key.Item1)) ^ key.Item2) == id);
     return ret;
 }
Пример #2
0
		public static void ReplaceReference(CEContext ctx, ProtectionParameters parameters) {
			foreach (var entry in ctx.ReferenceRepl) {
				if (parameters.GetParameter<bool>(ctx.Context, entry.Key, "cfg"))
					ReplaceCFG(entry.Key, entry.Value, ctx);
				else
					ReplaceNormal(entry.Key, entry.Value);
			}
		}
Пример #3
0
		public object CreateDecoder(MethodDef decoder, CEContext ctx) {
			var encoding = new x86Encoding();
			encoding.Compile(ctx);
			MutationHelper.ReplacePlaceholder(decoder, arg => {
				var repl = new List<Instruction>();
				repl.AddRange(arg);
				repl.Add(Instruction.Create(OpCodes.Call, encoding.native));
				return repl.ToArray();
			});
			return encoding;
		}
Пример #4
0
        protected override void Execute(ConfuserContext context, ProtectionParameters parameters)
        {
            if (parameters.Targets.Any()) {
                var compression = context.Registry.GetService<ICompressionService>();
                var name = context.Registry.GetService<INameService>();
                var marker = context.Registry.GetService<IMarkerService>();
                var rt = context.Registry.GetService<IRuntimeService>();
                var moduleCtx = new CEContext {
                    Random = context.Registry.GetService<IRandomService>().GetRandomGenerator(Parent.Id),
                    Context = context,
                    Module = context.CurrentModule,
                    Marker = marker,
                    DynCipher = context.Registry.GetService<IDynCipherService>(),
                    Name = name
                };

                // Extract parameters
                moduleCtx.Mode = parameters.GetParameter(context, context.CurrentModule, "mode", Mode.Normal);
                moduleCtx.DecoderCount = parameters.GetParameter(context, context.CurrentModule, "decoderCount", 5);

                switch (moduleCtx.Mode) {
                    case Mode.Normal:
                        moduleCtx.ModeHandler = new NormalMode();
                        break;
                    case Mode.Dynamic:
                        moduleCtx.ModeHandler = new DynamicMode();
                        break;
                    case Mode.x86:
                        moduleCtx.ModeHandler = new x86Mode();
                        if ((context.CurrentModule.Cor20HeaderFlags & ComImageFlags.ILOnly) != 0)
                            context.CurrentModuleWriterOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.ILOnly;
                        break;
                    default:
                        throw new UnreachableException();
                }

                // Inject helpers
                MethodDef decomp = compression.GetRuntimeDecompressor(context.CurrentModule, member => {
                    name.MarkHelper(member, marker);
                    if (member is MethodDef)
                        ProtectionParameters.GetParameters(context, member).Remove(Parent);
                });
                InjectHelpers(context, compression, rt, moduleCtx);

                // Mutate codes
                MutateInitializer(moduleCtx, decomp);

                MethodDef cctor = context.CurrentModule.GlobalType.FindStaticConstructor();
                cctor.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, moduleCtx.InitMethod));

                context.Annotations.Set(context.CurrentModule, ConstantProtection.ContextKey, moduleCtx);
            }
        }
Пример #5
0
		public IEnumerable<Instruction> EmitDecrypt(MethodDef init, CEContext ctx, Local block, Local key) {
			for (int i = 0; i < 0x10; i++) {
				yield return Instruction.Create(OpCodes.Ldloc, block);
				yield return Instruction.Create(OpCodes.Ldc_I4, i);
				yield return Instruction.Create(OpCodes.Ldloc, block);
				yield return Instruction.Create(OpCodes.Ldc_I4, i);
				yield return Instruction.Create(OpCodes.Ldelem_U4);
				yield return Instruction.Create(OpCodes.Ldloc, key);
				yield return Instruction.Create(OpCodes.Ldc_I4, i);
				yield return Instruction.Create(OpCodes.Ldelem_U4);
				yield return Instruction.Create(OpCodes.Xor);
				yield return Instruction.Create(OpCodes.Stelem_I4);
			}
		}
Пример #6
0
		public object CreateDecoder(MethodDef decoder, CEContext ctx) {
			uint k1 = ctx.Random.NextUInt32() | 1;
			uint k2 = ctx.Random.NextUInt32();
			MutationHelper.ReplacePlaceholder(decoder, arg => {
				var repl = new List<Instruction>();
				repl.AddRange(arg);
				repl.Add(Instruction.Create(OpCodes.Ldc_I4, (int)MathsUtils.modInv(k1)));
				repl.Add(Instruction.Create(OpCodes.Mul));
				repl.Add(Instruction.Create(OpCodes.Ldc_I4, (int)k2));
				repl.Add(Instruction.Create(OpCodes.Xor));
				return repl.ToArray();
			});
			return Tuple.Create(k1, k2);
		}
Пример #7
0
        static void InjectStateType(CEContext ctx)
        {
            if (ctx.CfgCtxType == null) {
                var type = ctx.Context.Registry.GetService<IRuntimeService>().GetRuntimeType("Confuser.Runtime.CFGCtx");
                ctx.CfgCtxType = InjectHelper.Inject(type, ctx.Module);
                ctx.Module.Types.Add(ctx.CfgCtxType);
                ctx.CfgCtxCtor = ctx.CfgCtxType.FindMethod(".ctor");
                ctx.CfgCtxNext = ctx.CfgCtxType.FindMethod("Next");

                ctx.Name.MarkHelper(ctx.CfgCtxType, ctx.Marker, ctx.Protection);
                foreach (var def in ctx.CfgCtxType.Fields)
                    ctx.Name.MarkHelper(def, ctx.Marker, ctx.Protection);
                foreach (var def in ctx.CfgCtxType.Methods)
                    ctx.Name.MarkHelper(def, ctx.Marker, ctx.Protection);
            }
        }
Пример #8
0
		public IEnumerable<Instruction> EmitDecrypt(MethodDef init, CEContext ctx, Local block, Local key) {
			StatementBlock encrypt, decrypt;
			ctx.DynCipher.GenerateCipherPair(ctx.Random, out encrypt, out decrypt);
			var ret = new List<Instruction>();

			var codeGen = new CodeGen(block, key, init, ret);
			codeGen.GenerateCIL(decrypt);
			codeGen.Commit(init.Body);

			var dmCodeGen = new DMCodeGen(typeof(void), new[] {
				Tuple.Create("{BUFFER}", typeof(uint[])),
				Tuple.Create("{KEY}", typeof(uint[]))
			});
			dmCodeGen.GenerateCIL(encrypt);
			encryptFunc = dmCodeGen.Compile<Action<uint[], uint[]>>();

			return ret;
		}
Пример #9
0
 private void MutateInitializer(CEContext moduleCtx, MethodDef decomp)
 {
     moduleCtx.InitMethod.Body.SimplifyMacros(moduleCtx.InitMethod.Parameters);
     List<Instruction> instrs = moduleCtx.InitMethod.Body.Instructions.ToList();
     for (int i = 0; i < instrs.Count; i++) {
         Instruction instr = instrs[i];
         var method = instr.Operand as IMethod;
         if (instr.OpCode == OpCodes.Call) {
             if (method.DeclaringType.Name == "Mutation" &&
                 method.Name == "Crypt") {
                 Instruction ldBlock = instrs[i - 2];
                 Instruction ldKey = instrs[i - 1];
                 Debug.Assert(ldBlock.OpCode == OpCodes.Ldloc && ldKey.OpCode == OpCodes.Ldloc);
                 instrs.RemoveAt(i);
                 instrs.RemoveAt(i - 1);
                 instrs.RemoveAt(i - 2);
                 instrs.InsertRange(i - 2, moduleCtx.ModeHandler.EmitDecrypt(moduleCtx.InitMethod, moduleCtx, (Local)ldBlock.Operand, (Local)ldKey.Operand));
             }
             else if (method.DeclaringType.Name == "Lzma" &&
                      method.Name == "Decompress") {
                 instr.Operand = decomp;
             }
         }
     }
     moduleCtx.InitMethod.Body.Instructions.Clear();
     foreach (Instruction instr in instrs)
         moduleCtx.InitMethod.Body.Instructions.Add(instr);
 }
Пример #10
0
        static void ReplaceCFG(MethodDef method, List<Tuple<Instruction, uint, IMethod>> instrs, CEContext ctx)
        {
            InjectStateType(ctx);

            var graph = ControlFlowGraph.Construct(method.Body);
            var sequence = KeySequence.ComputeKeys(graph, null);

            var cfgCtx = new CFGContext {
                Ctx = ctx,
                Graph = graph,
                Keys = sequence,
                StatesMap = new Dictionary<uint, CFGState>(),
                Random = ctx.Random
            };

            cfgCtx.StateVariable = new Local(ctx.CfgCtxType.ToTypeSig());
            method.Body.Variables.Add(cfgCtx.StateVariable);
            method.Body.InitLocals = true;

            var blockReferences = new Dictionary<int, SortedList<int, Tuple<Instruction, uint, IMethod>>>();
            foreach (var instr in instrs) {
                var index = graph.IndexOf(instr.Item1);
                var block = graph.GetContainingBlock(index);

                SortedList<int, Tuple<Instruction, uint, IMethod>> list;
                if (!blockReferences.TryGetValue(block.Id, out list))
                    list = blockReferences[block.Id] = new SortedList<int, Tuple<Instruction, uint, IMethod>>();

                list.Add(index, instr);
            }

            // Update state for blocks not in use
            for (int i = 0; i < graph.Count; i++) {
                if (blockReferences.ContainsKey(i))
                    continue;
                InsertEmptyStateUpdate(cfgCtx, graph[i]);
            }

            // Update references
            foreach (var blockRef in blockReferences) {
                var key = sequence[blockRef.Key];
                CFGState currentState;
                if (!cfgCtx.StatesMap.TryGetValue(key.EntryState, out currentState)) {
                    Debug.Assert((graph[blockRef.Key].Type & ControlFlowBlockType.Entry) != 0);
                    Debug.Assert(key.Type == BlockKeyType.Explicit);

                    // Create new entry state
                    uint blockSeed = ctx.Random.NextUInt32();
                    currentState = new CFGState(blockSeed);
                    cfgCtx.StatesMap[key.EntryState] = currentState;

                    var index = graph.Body.Instructions.IndexOf(graph[blockRef.Key].Header);
                    Instruction newHeader;
                    method.Body.Instructions.Insert(index++, newHeader = Instruction.Create(OpCodes.Ldloca, cfgCtx.StateVariable));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, (int)blockSeed));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Call, ctx.CfgCtxCtor));
                    method.Body.ReplaceReference(graph[blockRef.Key].Header, newHeader);
                    key.Type = BlockKeyType.Incremental;
                }
                var type = key.Type;

                for (int i = 0; i < blockRef.Value.Count; i++) {
                    var refEntry = blockRef.Value.Values[i];

                    CFGState? targetState = null;
                    if (i == blockRef.Value.Count - 1) {
                        CFGState exitState;
                        if (cfgCtx.StatesMap.TryGetValue(key.ExitState, out exitState))
                            targetState = exitState;
                    }

                    var index = graph.Body.Instructions.IndexOf(refEntry.Item1) + 1;
                    var value = InsertStateGetAndUpdate(cfgCtx, ref index, type, ref currentState, targetState);

                    refEntry.Item1.OpCode = OpCodes.Ldc_I4;
                    refEntry.Item1.Operand = (int)(refEntry.Item2 ^ value);
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Xor));
                    method.Body.Instructions.Insert(index, Instruction.Create(OpCodes.Call, refEntry.Item3));

                    if (i == blockRef.Value.Count - 1 && targetState == null) {
                        cfgCtx.StatesMap[key.ExitState] = currentState;
                    }

                    type = BlockKeyType.Incremental;
                }
            }
        }
Пример #11
0
		public uint Encode(object data, CEContext ctx, uint id) {
			var encoding = (x86Encoding)data;
			return (uint)encoding.expCompiled((int)id);
		}
Пример #12
0
        void EncodeString(CEContext moduleCtx, string value, List <Tuple <MethodDef, Instruction> > references)
        {
            int buffIndex = EncodeByteArray(moduleCtx, Encoding.UTF8.GetBytes(value));

            UpdateReference(moduleCtx, moduleCtx.Module.CorLibTypes.String, references, buffIndex, desc => desc.StringID);
        }
Пример #13
0
        void ExtractConstants(
            ConfuserContext context, ProtectionParameters parameters, CEContext moduleCtx,
            Dictionary <object, List <Tuple <MethodDef, Instruction> > > ldc,
            Dictionary <byte[], List <Tuple <MethodDef, Instruction> > > ldInit)
        {
            var dataFields = new HashSet <FieldDef>();
            var fieldRefs  = new HashSet <Instruction>();

            foreach (MethodDef method in parameters.Targets.OfType <MethodDef>().WithProgress(context.Logger))
            {
                if (!method.HasBody)
                {
                    continue;
                }

                moduleCtx.Elements = 0;
                string elements = parameters.GetParameter(context, method, "elements", "SI");
                foreach (char elem in elements)
                {
                    switch (elem)
                    {
                    case 'S':
                    case 's':
                        moduleCtx.Elements |= EncodeElements.Strings;
                        break;

                    case 'N':
                    case 'n':
                        moduleCtx.Elements |= EncodeElements.Numbers;
                        break;

                    case 'P':
                    case 'p':
                        moduleCtx.Elements |= EncodeElements.Primitive;
                        break;

                    case 'I':
                    case 'i':
                        moduleCtx.Elements |= EncodeElements.Initializers;
                        break;
                    }
                }

                if (moduleCtx.Elements == 0)
                {
                    continue;
                }

                foreach (Instruction instr in method.Body.Instructions)
                {
                    bool eligible = false;
                    if (instr.OpCode == OpCodes.Ldstr && (moduleCtx.Elements & EncodeElements.Strings) != 0)
                    {
                        var operand = (string)instr.Operand;
                        if (string.IsNullOrEmpty(operand) && (moduleCtx.Elements & EncodeElements.Primitive) == 0)
                        {
                            continue;
                        }
                        eligible = true;
                    }
                    else if (instr.OpCode == OpCodes.Call && (moduleCtx.Elements & EncodeElements.Initializers) != 0)
                    {
                        var operand = (IMethod)instr.Operand;
                        if (operand.DeclaringType.DefinitionAssembly.IsCorLib() &&
                            operand.DeclaringType.Namespace == "System.Runtime.CompilerServices" &&
                            operand.DeclaringType.Name == "RuntimeHelpers" &&
                            operand.Name == "InitializeArray")
                        {
                            IList <Instruction> instrs = method.Body.Instructions;
                            int i = instrs.IndexOf(instr);
                            if (instrs[i - 1].OpCode != OpCodes.Ldtoken)
                            {
                                continue;
                            }
                            if (instrs[i - 2].OpCode != OpCodes.Dup)
                            {
                                continue;
                            }
                            if (instrs[i - 3].OpCode != OpCodes.Newarr)
                            {
                                continue;
                            }
                            if (instrs[i - 4].OpCode != OpCodes.Ldc_I4)
                            {
                                continue;
                            }

                            var dataField = instrs[i - 1].Operand as FieldDef;
                            if (dataField == null)
                            {
                                continue;
                            }
                            if (!dataField.HasFieldRVA || dataField.InitialValue == null)
                            {
                                continue;
                            }

                            // Prevent array length from being encoded
                            var arrLen = (int)instrs[i - 4].Operand;
                            if (ldc.ContainsKey(arrLen))
                            {
                                List <Tuple <MethodDef, Instruction> > list = ldc[arrLen];
                                list.RemoveWhere(entry => entry.Item2 == instrs[i - 4]);
                                if (list.Count == 0)
                                {
                                    ldc.Remove(arrLen);
                                }
                            }

                            dataFields.Add(dataField);
                            fieldRefs.Add(instrs[i - 1]);

                            var value = new byte[dataField.InitialValue.Length + 4];
                            value[0] = (byte)(arrLen >> 0);
                            value[1] = (byte)(arrLen >> 8);
                            value[2] = (byte)(arrLen >> 16);
                            value[3] = (byte)(arrLen >> 24);
                            Buffer.BlockCopy(dataField.InitialValue, 0, value, 4, dataField.InitialValue.Length);
                            ldInit.AddListEntry(value, Tuple.Create(method, instr));
                        }
                    }
                    else if ((moduleCtx.Elements & EncodeElements.Numbers) != 0)
                    {
                        if (instr.OpCode == OpCodes.Ldc_I4)
                        {
                            var operand = (int)instr.Operand;
                            if ((operand >= -1 && operand <= 8) && (moduleCtx.Elements & EncodeElements.Primitive) == 0)
                            {
                                continue;
                            }
                            eligible = true;
                        }
                        else if (instr.OpCode == OpCodes.Ldc_I8)
                        {
                            var operand = (long)instr.Operand;
                            if ((operand >= -1 && operand <= 1) && (moduleCtx.Elements & EncodeElements.Primitive) == 0)
                            {
                                continue;
                            }
                            eligible = true;
                        }
                        else if (instr.OpCode == OpCodes.Ldc_R4)
                        {
                            var operand = (float)instr.Operand;
                            if ((operand == -1 || operand == 0 || operand == 1) && (moduleCtx.Elements & EncodeElements.Primitive) == 0)
                            {
                                continue;
                            }
                            eligible = true;
                        }
                        else if (instr.OpCode == OpCodes.Ldc_R8)
                        {
                            var operand = (double)instr.Operand;
                            if ((operand == -1 || operand == 0 || operand == 1) && (moduleCtx.Elements & EncodeElements.Primitive) == 0)
                            {
                                continue;
                            }
                            eligible = true;
                        }
                    }

                    if (eligible)
                    {
                        ldc.AddListEntry(instr.Operand, Tuple.Create(method, instr));
                    }
                }

                context.CheckCancellation();
            }
            RemoveDataFieldRefs(context, dataFields, fieldRefs);
        }
Пример #14
0
        static void ReplaceCFG(MethodDef method, List <Tuple <Instruction, uint, IMethod> > instrs, CEContext ctx)
        {
            InjectStateType(ctx);

            var graph    = ControlFlowGraph.Construct(method.Body);
            var sequence = KeySequence.ComputeKeys(graph, null);

            var cfgCtx = new CFGContext {
                Ctx       = ctx,
                Graph     = graph,
                Keys      = sequence,
                StatesMap = new Dictionary <uint, CFGState>(),
                Random    = ctx.Random
            };

            cfgCtx.StateVariable = new Local(ctx.CfgCtxType.ToTypeSig());
            method.Body.Variables.Add(cfgCtx.StateVariable);
            method.Body.InitLocals = true;

            var blockReferences = new Dictionary <int, SortedList <int, Tuple <Instruction, uint, IMethod> > >();

            foreach (var instr in instrs)
            {
                var index = graph.IndexOf(instr.Item1);
                var block = graph.GetContainingBlock(index);

                SortedList <int, Tuple <Instruction, uint, IMethod> > list;
                if (!blockReferences.TryGetValue(block.Id, out list))
                {
                    list = blockReferences[block.Id] = new SortedList <int, Tuple <Instruction, uint, IMethod> >();
                }

                list.Add(index, instr);
            }

            // Update state for blocks not in use
            for (int i = 0; i < graph.Count; i++)
            {
                var block = graph[i];
                if (blockReferences.ContainsKey(block.Id))
                {
                    continue;
                }
                InsertEmptyStateUpdate(cfgCtx, block);
            }

            // Update references
            foreach (var blockRef in blockReferences)
            {
                var      key = sequence[blockRef.Key];
                CFGState currentState;
                if (!cfgCtx.StatesMap.TryGetValue(key.EntryState, out currentState))
                {
                    Debug.Assert((graph[blockRef.Key].Type & ControlFlowBlockType.Entry) != 0);
                    Debug.Assert(key.Type == BlockKeyType.Explicit);

                    // Create new entry state
                    uint blockSeed = ctx.Random.NextUInt32();
                    currentState = new CFGState(blockSeed);
                    cfgCtx.StatesMap[key.EntryState] = currentState;

                    var         index = graph.Body.Instructions.IndexOf(graph[blockRef.Key].Header);
                    Instruction newHeader;
                    method.Body.Instructions.Insert(index++, newHeader = Instruction.Create(OpCodes.Ldloca, cfgCtx.StateVariable));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, (int)blockSeed));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Call, ctx.CfgCtxCtor));
                    method.Body.ReplaceReference(graph[blockRef.Key].Header, newHeader);
                    key.Type = BlockKeyType.Incremental;
                }
                var type = key.Type;

                for (int i = 0; i < blockRef.Value.Count; i++)
                {
                    var refEntry = blockRef.Value.Values[i];

                    CFGState?targetState = null;
                    if (i == blockRef.Value.Count - 1)
                    {
                        CFGState exitState;
                        if (cfgCtx.StatesMap.TryGetValue(key.ExitState, out exitState))
                        {
                            targetState = exitState;
                        }
                    }

                    var index = graph.Body.Instructions.IndexOf(refEntry.Item1) + 10000;
                    var value = InsertStateGetAndUpdate(cfgCtx, ref index, type, ref currentState, targetState);
                    refEntry.Item1.OpCode  = OpCodes.Ldstr;
                    refEntry.Item1.Operand = "Rzy-Protector";
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, (int)refEntry.Item2 - new Random().Next(10000, 100000)));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, (int)(refEntry.Item2 ^ value)));
                    method.Body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, new Random().Next(10000, 100000)));

                    method.Body.Instructions.Insert(index, Instruction.Create(OpCodes.Call, refEntry.Item3));
                    if (i == blockRef.Value.Count - 10 && targetState == null)
                    {
                        cfgCtx.StatesMap[key.ExitState] = currentState;
                    }

                    type = BlockKeyType.Incremental;
                }
            }
        }
Пример #15
0
        void InjectHelpers(ConfuserContext context, ICompressionService compression, IRuntimeService rt, CEContext moduleCtx)
        {
            IEnumerable <IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Constant"), context.CurrentModule.GlobalType, context.CurrentModule);

            foreach (IDnlibDef member in members)
            {
                if (member.Name == "Get")
                {
                    context.CurrentModule.GlobalType.Remove((MethodDef)member);
                    continue;
                }
                if (member.Name == "buffer")
                {
                    moduleCtx.BufferField = (FieldDef)member;
                }
                else if (member.Name == "Initialize")
                {
                    moduleCtx.InitMethod = (MethodDef)member;
                }
                moduleCtx.Name.MarkHelper(member, moduleCtx.Marker, (Protection)Parent);
            }
            ProtectionParameters.GetParameters(context, moduleCtx.InitMethod).Remove(Parent);

            var dataType = new TypeDefUser("", moduleCtx.Name.RandomName(), context.CurrentModule.CorLibTypes.GetTypeRef("System", "ValueType"));

            dataType.Layout     = TypeAttributes.ExplicitLayout;
            dataType.Visibility = TypeAttributes.NestedPrivate;
            dataType.IsSealed   = true;
            moduleCtx.DataType  = dataType;
            context.CurrentModule.GlobalType.NestedTypes.Add(dataType);
            moduleCtx.Name.MarkHelper(dataType, moduleCtx.Marker, (Protection)Parent);

            moduleCtx.DataField = new FieldDefUser(moduleCtx.Name.RandomName(), new FieldSig(dataType.ToTypeSig()))
            {
                IsStatic = true,
                Access   = FieldAttributes.CompilerControlled
            };
            context.CurrentModule.GlobalType.Fields.Add(moduleCtx.DataField);
            moduleCtx.Name.MarkHelper(moduleCtx.DataField, moduleCtx.Marker, (Protection)Parent);

            MethodDef decoder = rt.GetRuntimeType("Confuser.Runtime.Constant").FindMethod("Get");

            moduleCtx.Decoders = new List <Tuple <MethodDef, DecoderDesc> >();
            for (int i = 0; i < moduleCtx.DecoderCount; i++)
            {
                MethodDef decoderInst = InjectHelper.Inject(decoder, context.CurrentModule);
                for (int j = 0; j < decoderInst.Body.Instructions.Count; j++)
                {
                    Instruction instr  = decoderInst.Body.Instructions[j];
                    var         method = instr.Operand as IMethod;
                    var         field  = instr.Operand as IField;
                    if (instr.OpCode == OpCodes.Call &&
                        method.DeclaringType.Name == "Mutation" &&
                        method.Name == "Value")
                    {
                        decoderInst.Body.Instructions[j] = Instruction.Create(OpCodes.Sizeof, new GenericMVar(0).ToTypeDefOrRef());
                    }
                    else if (instr.OpCode == OpCodes.Ldsfld &&
                             method.DeclaringType.Name == "Constant")
                    {
                        if (field.Name == "buffer")
                        {
                            instr.Operand = moduleCtx.BufferField;
                        }
                        else
                        {
                            throw new UnreachableException();
                        }
                    }
                }
                context.CurrentModule.GlobalType.Methods.Add(decoderInst);
                moduleCtx.Name.MarkHelper(decoderInst, moduleCtx.Marker, (Protection)Parent);
                ProtectionParameters.GetParameters(context, decoderInst).Remove(Parent);

                var decoderDesc = new DecoderDesc();

                decoderDesc.StringID = (byte)(moduleCtx.Random.NextByte() & 3);

                do
                {
                    decoderDesc.NumberID = (byte)(moduleCtx.Random.NextByte() & 3);
                } while (decoderDesc.NumberID == decoderDesc.StringID);

                do
                {
                    decoderDesc.InitializerID = (byte)(moduleCtx.Random.NextByte() & 3);
                } while (decoderDesc.InitializerID == decoderDesc.StringID || decoderDesc.InitializerID == decoderDesc.NumberID);

                MutationHelper.InjectKeys(decoderInst,
                                          new[] { 0, 1, 2 },
                                          new int[] { decoderDesc.StringID, decoderDesc.NumberID, decoderDesc.InitializerID });
                decoderDesc.Data = moduleCtx.ModeHandler.CreateDecoder(decoderInst, moduleCtx);
                moduleCtx.Decoders.Add(Tuple.Create(decoderInst, decoderDesc));
            }
        }
Пример #16
0
        protected override void Execute(ConfuserContext context, ProtectionParameters parameters)
        {
            if (parameters.Targets.Any())
            {
                var compression = context.Registry.GetService <ICompressionService>();
                var name        = context.Registry.GetService <INameService>();
                var marker      = context.Registry.GetService <IMarkerService>();
                var rt          = context.Registry.GetService <IRuntimeService>();
                var moduleCtx   = new CEContext {
                    Protection = (ConstantProtection)Parent,
                    Random     = context.Registry.GetService <IRandomService>().GetRandomGenerator(Parent.Id),
                    Context    = context,
                    Module     = context.CurrentModule,
                    Marker     = marker,
                    DynCipher  = context.Registry.GetService <IDynCipherService>(),
                    Name       = name
                };

                // Extract parameters
                moduleCtx.Mode         = parameters.GetParameter(context, context.CurrentModule, "mode", Mode.Normal);
                moduleCtx.DecoderCount = parameters.GetParameter(context, context.CurrentModule, "decoderCount", 5);

                switch (moduleCtx.Mode)
                {
                case Mode.Normal:
                    moduleCtx.ModeHandler = new NormalMode();
                    break;

                case Mode.Dynamic:
                    moduleCtx.ModeHandler = new DynamicMode();
                    break;

                case Mode.x86:
                    moduleCtx.ModeHandler = new x86Mode();
                    if ((context.CurrentModule.Cor20HeaderFlags & ComImageFlags.ILOnly) != 0)
                    {
                        context.CurrentModuleWriterOptions.Cor20HeaderOptions.Flags &= ~ComImageFlags.ILOnly;
                    }
                    break;

                default:
                    throw new UnreachableException();
                }

                // Inject helpers
                MethodDef decomp = compression.GetRuntimeDecompressor(context.CurrentModule, member => {
                    name.MarkHelper(member, marker, (Protection)Parent);
                    if (member is MethodDef)
                    {
                        ProtectionParameters.GetParameters(context, member).Remove(Parent);
                    }
                });
                InjectHelpers(context, compression, rt, moduleCtx);

                // Mutate codes
                MutateInitializer(moduleCtx, decomp);

                MethodDef cctor = context.CurrentModule.GlobalType.FindStaticConstructor();
                cctor.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, moduleCtx.InitMethod));

                context.Annotations.Set(context.CurrentModule, ConstantProtection.ContextKey, moduleCtx);
            }
        }
Пример #17
0
        private void InjectHelpers(ConfuserContext context, ICompressionService compression, IRuntimeService rt, CEContext moduleCtx)
        {
            IEnumerable<IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Constant"), context.CurrentModule.GlobalType, context.CurrentModule);
            foreach (IDnlibDef member in members) {
                if (member.Name == "Get") {
                    context.CurrentModule.GlobalType.Remove((MethodDef)member);
                    continue;
                }
                if (member.Name == "b")
                    moduleCtx.BufferField = (FieldDef)member;
                else if (member.Name == "Initialize")
                    moduleCtx.InitMethod = (MethodDef)member;
                moduleCtx.Name.MarkHelper(member, moduleCtx.Marker);
            }
            ProtectionParameters.GetParameters(context, moduleCtx.InitMethod).Remove(Parent);

            var dataType = new TypeDefUser("", moduleCtx.Name.RandomName(), context.CurrentModule.CorLibTypes.GetTypeRef("System", "ValueType"));
            dataType.Layout = TypeAttributes.ExplicitLayout;
            dataType.Visibility = TypeAttributes.NestedPrivate;
            dataType.IsSealed = true;
            moduleCtx.DataType = dataType;
            context.CurrentModule.GlobalType.NestedTypes.Add(dataType);
            moduleCtx.Name.MarkHelper(dataType, moduleCtx.Marker);

            moduleCtx.DataField = new FieldDefUser(moduleCtx.Name.RandomName(), new FieldSig(dataType.ToTypeSig())) {
                IsStatic = true,
                Access = FieldAttributes.CompilerControlled
            };
            context.CurrentModule.GlobalType.Fields.Add(moduleCtx.DataField);
            moduleCtx.Name.MarkHelper(moduleCtx.DataField, moduleCtx.Marker);

            MethodDef decoder = rt.GetRuntimeType("Confuser.Runtime.Constant").FindMethod("Get");
            moduleCtx.Decoders = new List<Tuple<MethodDef, DecoderDesc>>();
            for (int i = 0; i < moduleCtx.DecoderCount; i++) {
                MethodDef decoderInst = InjectHelper.Inject(decoder, context.CurrentModule);
                for (int j = 0; j < decoderInst.Body.Instructions.Count; j++) {
                    Instruction instr = decoderInst.Body.Instructions[j];
                    var method = instr.Operand as IMethod;
                    var field = instr.Operand as IField;
                    if (instr.OpCode == OpCodes.Call &&
                        method.DeclaringType.Name == "Mutation" &&
                        method.Name == "Value") {
                        decoderInst.Body.Instructions[j] = Instruction.Create(OpCodes.Sizeof, new GenericMVar(0).ToTypeDefOrRef());
                    }
                    else if (instr.OpCode == OpCodes.Ldsfld &&
                             method.DeclaringType.Name == "Constant") {
                        if (field.Name == "b") instr.Operand = moduleCtx.BufferField;
                        else throw new UnreachableException();
                    }
                }
                context.CurrentModule.GlobalType.Methods.Add(decoderInst);
                moduleCtx.Name.MarkHelper(decoderInst, moduleCtx.Marker);
                ProtectionParameters.GetParameters(context, decoderInst).Remove(Parent);

                var decoderDesc = new DecoderDesc();

                decoderDesc.StringID = (byte)(moduleCtx.Random.NextByte() & 3);

                do decoderDesc.NumberID = (byte)(moduleCtx.Random.NextByte() & 3); while (decoderDesc.NumberID == decoderDesc.StringID);

                do decoderDesc.InitializerID = (byte)(moduleCtx.Random.NextByte() & 3); while (decoderDesc.InitializerID == decoderDesc.StringID || decoderDesc.InitializerID == decoderDesc.NumberID);

                MutationHelper.InjectKeys(decoderInst,
                                          new[] { 0, 1, 2 },
                                          new int[] { decoderDesc.StringID, decoderDesc.NumberID, decoderDesc.InitializerID });
                decoderDesc.Data = moduleCtx.ModeHandler.CreateDecoder(decoderInst, moduleCtx);
                moduleCtx.Decoders.Add(Tuple.Create(decoderInst, decoderDesc));
            }
        }
Пример #18
0
			public void Compile(CEContext ctx) {
				var var = new Variable("{VAR}");
				var result = new Variable("{RESULT}");

				CorLibTypeSig int32 = ctx.Module.CorLibTypes.Int32;
				native = new MethodDefUser("", 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.Module.GlobalType.Methods.Add(native);

				ctx.Name.MarkHelper(native, ctx.Marker, ctx.Protection);

				x86Register? reg;
				var codeGen = new x86CodeGen();
				do {
					ctx.DynCipher.GenerateExpressionPair(
						ctx.Random,
						new VariableExpression { Variable = var }, new VariableExpression { Variable = result },
						4, 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;
			}
Пример #19
0
        static void ReplaceCFG(MethodDef method, List<Tuple<Instruction, uint, IMethod>> instrs, CEContext ctx)
        {
            var graph = ControlFlowGraph.Construct(method.Body);
            var sequence = KeySequence.ComputeKeys(graph, ctx.Random);

            var cfgCtx = new CFGContext {
                Graph = graph,
                Keys = sequence,
                Random = ctx.Random
            };
            var blockReferences = new Dictionary<int, SortedList<int, Tuple<Instruction, uint, IMethod>>>();
            foreach (var instr in instrs) {
                var index = graph.IndexOf(instr.Item1);
                var block = graph.GetContainingBlock(index);

                SortedList<int, Tuple<Instruction, uint, IMethod>> list;
                if (!blockReferences.TryGetValue(block.Id, out list))
                    list = blockReferences[block.Id] = new SortedList<int, Tuple<Instruction, uint, IMethod>>();

                list.Add(index, instr);
            }

            cfgCtx.StateVariable = new Local(method.Module.CorLibTypes.UInt32);
            method.Body.Variables.Add(cfgCtx.StateVariable);
            method.Body.InitLocals = true;

            // Update state for blocks not in use
            for (int i = 0; i < graph.Count; i++) {
                if (blockReferences.ContainsKey(i))
                    continue;
                InsertEmptyStateUpdate(cfgCtx, graph[i]);
            }

            // Update references
            foreach (var blockRef in blockReferences) {
                var key = sequence[blockRef.Key];
                var currentState = key.EntryState;
                var type = key.Type;

                for (int i = 0; i < blockRef.Value.Count; i++) {
                    var entry = blockRef.Value.Values[i];
                    var targetState = i == blockRef.Value.Count - 1 ? key.ExitState : cfgCtx.Random.NextUInt32();
                    var index = graph.Body.Instructions.IndexOf(entry.Item1);
                    var id = entry.Item2 ^ currentState;

                    entry.Item1.OpCode = OpCodes.Ldc_I4;
                    entry.Item1.Operand = (int)id;
                    index = InsertStateGetAndUpdate(cfgCtx, index + 1, type, currentState, targetState);
                    method.Body.Instructions.Insert(index + 0, Instruction.Create(OpCodes.Xor));
                    method.Body.Instructions.Insert(index + 1, Instruction.Create(OpCodes.Call, entry.Item3));

                    type = BlockKeyType.Incremental;
                    currentState = targetState;
                }
            }
        }
Пример #20
0
        private static void ReplaceCFG(MethodDef method, List <Tuple <Instruction, uint, IMethod> > instrs, CEContext ctx)
        {
            if (method.Name == "GetCpuName")
            {
                Debugger.Break();
            }
            var graph    = ControlFlowGraph.Construct(method.Body);
            var sequence = KeySequence.ComputeKeys(graph, ctx.Random);

            var cfgCtx = new CFGContext {
                Graph  = graph,
                Keys   = sequence,
                Random = ctx.Random
            };
            var blockReferences = new Dictionary <int, SortedList <int, Tuple <Instruction, uint, IMethod> > >();

            foreach (var instr in instrs)
            {
                var index = graph.IndexOf(instr.Item1);
                var block = graph.GetContainingBlock(index);

                SortedList <int, Tuple <Instruction, uint, IMethod> > list;
                if (!blockReferences.TryGetValue(block.Id, out list))
                {
                    list = blockReferences[block.Id] = new SortedList <int, Tuple <Instruction, uint, IMethod> >();
                }

                list.Add(index, instr);
            }

            cfgCtx.StateVariable = new Local(method.Module.CorLibTypes.UInt32);
            method.Body.Variables.Add(cfgCtx.StateVariable);
            method.Body.InitLocals = true;

            // Update state for blocks not in use
            for (int i = 0; i < graph.Count; i++)
            {
                if (blockReferences.ContainsKey(i))
                {
                    continue;
                }
                InsertEmptyStateUpdate(cfgCtx, graph[i]);
            }

            // Update references
            foreach (var blockRef in blockReferences)
            {
                var key          = sequence[blockRef.Key];
                var currentState = key.EntryState;
                var type         = key.Type;

                for (int i = 0; i < blockRef.Value.Count; i++)
                {
                    var entry       = blockRef.Value.Values[i];
                    var targetState = i == blockRef.Value.Count - 1 ? key.ExitState : cfgCtx.Random.NextUInt32();
                    var index       = graph.Body.Instructions.IndexOf(entry.Item1);
                    var id          = entry.Item2 ^ currentState;

                    entry.Item1.OpCode  = OpCodes.Ldc_I4;
                    entry.Item1.Operand = (int)id;
                    index = InsertStateGetAndUpdate(cfgCtx, index + 1, type, currentState, targetState);
                    method.Body.Instructions.Insert(index + 0, Instruction.Create(OpCodes.Xor));
                    method.Body.Instructions.Insert(index + 1, Instruction.Create(OpCodes.Call, entry.Item3));

                    type         = BlockKeyType.Incremental;
                    currentState = targetState;
                }
            }
        }