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; }
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); } }
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; }
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); } }
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); } }
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); }
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); } }
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; }
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); }
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; } } }
public uint Encode(object data, CEContext ctx, uint id) { var encoding = (x86Encoding)data; return (uint)encoding.expCompiled((int)id); }
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); }
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); }
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; } } }
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)); } }
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); } }
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)); } }
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; }
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; } } }
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; } } }