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); }
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; }
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); } }
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(); } }
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); }
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; }
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); }
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); }
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; }
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; }
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; }
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); } }
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; }
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; }
public abstract void Mangle(CilBody body, ScopeBlock root, CFContext ctx);
public x86Predicate(CFContext ctx) { this.ctx = ctx; }
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; }
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); } }
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 CodeGen(Local state, CFContext ctx, IList<Instruction> instrs) : base(ctx.Method, instrs) { this.state = state; }
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); } }