private void Compile(RPContext ctx, CilBody body, out Func <int, int> expCompiled, out Expression inverse) { var var = new Variable("{VAR}"); var result = new Variable("{RESULT}"); Expression expression; ctx.DynCipher.GenerateExpressionPair( ctx.Random, new VariableExpression { Variable = var }, new VariableExpression { Variable = result }, ctx.Depth, out expression, out inverse); expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) }) .GenerateCIL(expression) .Compile <Func <int, int> >(); }
ControlFlowGraph(CilBody body) { try { this.body = body; instrBlocks = new int[body.Instructions.Count]; blocks = new List <ControlFlowBlock>(); indexMap = new Dictionary <Instruction, int>(); for (int i = 0; i < body.Instructions.Count; i++) { indexMap.Add(body.Instructions[i], i); } } catch { Console.WriteLine(" EXCCCCC "); } }
public static Instruction FindInstrSeqStart(this CilBody body, OpCode[] instrs, int startIndex = 0) { for (int i = startIndex; i <= body.Instructions.Count - instrs.Length; i++) { for (int j = 0; j < instrs.Length; j++) { if (!CodeEqIgnoreS(body.Instructions[i + j].OpCode.Code, instrs[j].Code)) { goto next_try; } } return(body.Instructions[i]); next_try: ; } return(null); }
/// <summary> /// Strips the given Type's method bodies and nested Types. /// </summary> private static void StripType(TypeDef type) { CilBody throwNullBody = new CilBody { Instructions = { new Instruction(OpCodes.Ldnull), new Instruction(OpCodes.Throw) } }; foreach (MethodDef method in type.Methods) { if (method.HasBody) { method.Body = throwNullBody; } } foreach (TypeDef nestedType in type.NestedTypes) { StripType(nestedType); } }
/// <summary> /// Replaces the specified instruction reference with another instruction. /// </summary> /// <param name="body">The method body.</param> /// <param name="target">The instruction to replace.</param> /// <param name="newInstr">The new instruction.</param> public static void ReplaceReference(this CilBody body, Instruction target, Instruction newInstr) { foreach (ExceptionHandler eh in body.ExceptionHandlers) { if (eh.TryStart == target) { eh.TryStart = newInstr; } if (eh.TryEnd == target) { eh.TryEnd = newInstr; } if (eh.HandlerStart == target) { eh.HandlerStart = newInstr; } if (eh.HandlerEnd == target) { eh.HandlerEnd = newInstr; } } foreach (Instruction instr in body.Instructions) { if (instr.Operand == target) { instr.Operand = newInstr; } else if (instr.Operand is Instruction[]) { var targets = (Instruction[])instr.Operand; for (int i = 0; i < targets.Length; i++) { if (targets[i] == target) { targets[i] = newInstr; } } } } }
void AddSequencePoints(CilBody body, SymbolMethod method) { int instrIndex = 0; foreach (var sp in method.SequencePoints) { var instr = GetInstruction(body.Instructions, sp.Offset, ref instrIndex); if (instr == null) { continue; } var seqPoint = new SequencePoint() { Document = Add_NoLock(new PdbDocument(sp.Document)), StartLine = sp.Line, StartColumn = sp.Column, EndLine = sp.EndLine, EndColumn = sp.EndColumn, }; instr.SequencePoint = seqPoint; } }
private void EncodeNumeric(SpectreContext spctx, MethodDef method, int i) { body = method.Body; int key = LeetRandom.rnd.Next(0, int.MaxValue); FieldDef field = new FieldDefUser(Guid.NewGuid().ToString(), new FieldSig(spctx.ManifestModule.CorLibTypes.Int32), FieldAttributes.Public | FieldAttributes.Static); //Add Field spctx.GlobalType.Fields.Add(field); int cctorbdycount = spctx.cctor.Body.Instructions.Count; //Init Field spctx.cctor.Body.Instructions.Insert(cctorbdycount - 1, Instruction.Create(OpCodes.Stsfld, field)); spctx.cctor.Body.Instructions.Insert(cctorbdycount - 1, Instruction.CreateLdcI4(key)); int operand = body.Instructions[i].GetLdcI4Value(); int newoperand = EncodeNum(operand, key); body.Instructions[i] = Instruction.CreateLdcI4(newoperand); body.Instructions.Insert(i + 1, Instruction.Create(OpCodes.Ldsfld, field)); // insert int field body.Instructions.Insert(i + 2, Instruction.Create(OpCodes.Call, decryptionmethod)); }
static List <BasicBlock <CILInstrList> > SplitBlocks(CilBody body, HashSet <Instruction> headers, HashSet <Instruction> entries) { int nextBlockId = 0; int currentBlockId = -1; Instruction currentBlockHdr = null; var blocks = new List <BasicBlock <CILInstrList> >(); var instrList = new CILInstrList(); for (int i = 0; i < body.Instructions.Count; i++) { Instruction instr = body.Instructions[i]; if (headers.Contains(instr)) { if (currentBlockHdr != null) { Instruction footer = body.Instructions[i - 1]; Debug.Assert(instrList.Count > 0); blocks.Add(new BasicBlock <CILInstrList>(currentBlockId, instrList)); instrList = new CILInstrList(); } currentBlockId = nextBlockId++; currentBlockHdr = instr; } instrList.Add(instr); } if (blocks.Count == 0 || blocks[blocks.Count - 1].Id != currentBlockId) { Instruction footer = body.Instructions[body.Instructions.Count - 1]; Debug.Assert(instrList.Count > 0); blocks.Add(new BasicBlock <CILInstrList>(currentBlockId, instrList)); } return(blocks); }
//https://github.com/0xd4d/dnlib/blob/master/Examples/Example3.cs public static void Run(string encrypted, string writedir) { //create module var mod = new ModuleDefUser(RandomString()); mod.Kind = ModuleKind.Console; // create and add asm in module var asm = new AssemblyDefUser(RandomString(), new Version(random.Next(1, 9), random.Next(1, 9), random.Next(1, 9), random.Next(1, 9))); asm.Modules.Add(mod); // create startup class for ep var startUpType = new TypeDefUser(RandomString(), RandomString(), mod.CorLibTypes.Object.TypeDefOrRef); startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; mod.Types.Add(startUpType); //create ep method main(string[] args) var entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Void, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); startUpType.Methods.Add(entryPoint); mod.EntryPoint = entryPoint; var epBody = new CilBody(); entryPoint.Body = epBody; // add instructions in ep method epBody.Instructions.Add(OpCodes.Nop.ToInstruction()); epBody.Instructions.Add(OpCodes.Ldstr.ToInstruction(encrypted)); epBody.Instructions.Add(OpCodes.Call.ToInstruction(entryPoint.Module.Import(typeof(System.Convert).GetMethod("FromBase64String", new Type[] { typeof(string) })))); epBody.Instructions.Add(OpCodes.Call.ToInstruction(entryPoint.Module.Import(typeof(System.Reflection.Assembly).GetMethod("Load", new Type[] { typeof(byte[]) })))); epBody.Instructions.Add(OpCodes.Callvirt.ToInstruction(entryPoint.Module.Import(typeof(System.Reflection.Assembly).GetMethod("get_EntryPoint", new Type[0])))); epBody.Instructions.Add(OpCodes.Ldnull.ToInstruction()); epBody.Instructions.Add(OpCodes.Ldc_I4_1.ToInstruction()); epBody.Instructions.Add(OpCodes.Newarr.ToInstruction(entryPoint.Module.Import(typeof(System.Object)))); epBody.Instructions.Add(OpCodes.Callvirt.ToInstruction(entryPoint.Module.Import(typeof(System.Reflection.MethodBase).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) })))); epBody.Instructions.Add(OpCodes.Pop.ToInstruction()); epBody.Instructions.Add(OpCodes.Ret.ToInstruction()); // save new file mod.Write(writedir.Replace(".exe", "_packed.exe")); }
void Compile(CilBody body) { var var = new Variable("{VAR}"); var result = new Variable("{RESULT}"); ctx.DynCipher.GenerateExpressionPair( ctx.Random, new VariableExpression { Variable = var }, new VariableExpression { Variable = result }, ctx.Depth, out expression, out inverse); expCompiled = new DMCodeGen(typeof(int), new[] { Tuple.Create("{VAR}", typeof(int)) }) .GenerateCIL(expression) .Compile <Func <int, int> >(); invCompiled = new List <Instruction>(); new CodeGen(stateVar, ctx, invCompiled).GenerateCIL(inverse); body.MaxStack += (ushort)ctx.Depth; }
void IProtector.ProtectionPhase(Context krawk) { foreach (ModuleDef module in krawk.Assembly.Modules) { foreach (TypeDef type in module.Types) { foreach (MethodDef method in type.Methods) { if (!method.HasBody) { continue; } if (method.HasBody) { if (!method.Body.HasInstructions) { continue; } } body = method.Body; for (int i = 0; i < body.Instructions.Count; i++) { if (method.Body.Instructions[i].OpCode == OpCodes.Ldstr) { Mutate(krawk, method, i, "String"); i += 2; } if (method.Body.Instructions[i].IsLdcI4()) { Mutate(krawk, method, i, "Int"); } } body.SimplifyBranches(); body.OptimizeBranches(); } } } }
/// <summary> /// Inserts a group of instructions into the method as the arbitrary last. /// </summary> public static void AppendLast(this CilBody body, IEnumerable <Instruction> instructions) { if (body == null) { throw new ArgumentNullException(nameof(body)); } if (instructions == null) { throw new ArgumentNullException(nameof(instructions)); } var ret = body.Instructions.Last(); if (ret == null || ret.OpCode != OpCodes.Ret) { throw new ArgumentOutOfRangeException(nameof(body)); } var list = instructions.ToList(); if (!list.Any()) { return; } var first = list.First(); ret.OpCode = first.OpCode; ret.Operand = first.Operand; list.Remove(first); list.Add(OpCodes.Ret.ToInstruction()); foreach (var instruction in list) { body.Instructions.Add(instruction); } }
/// <summary> /// Constructs a CFG from the specified method body. /// </summary> /// <param name="body">The method body.</param> /// <returns>The CFG of the given method body.</returns> public static ControlFlowGraph Construct(CilBody body) { var graph = new ControlFlowGraph(body); if (body.Instructions.Count == 0) { return(graph); } // Populate block headers var blockHeaders = new HashSet <Instruction>(); var entryHeaders = new HashSet <Instruction>(); graph.PopulateBlockHeaders(blockHeaders, entryHeaders); // Split blocks graph.SplitBlocks(blockHeaders, entryHeaders); // Link blocks graph.LinkBlocks(); return(graph); }
/// <summary> /// Finds all branches. Returns list of source offset->target offset mapping. /// Multiple entries for the same source offset are possible (switch statements). /// The result is sorted by source offset. /// </summary> List <KeyValuePair <Instruction, Instruction> > FindAllBranches(CilBody body) { var result = new List <KeyValuePair <Instruction, Instruction> >(); foreach (Instruction inst in body.Instructions) { switch (inst.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: result.Add(new KeyValuePair <Instruction, Instruction>(inst, (Instruction)inst.Operand)); break; case OperandType.InlineSwitch: foreach (Instruction target in (Instruction[])inst.Operand) { result.Add(new KeyValuePair <Instruction, Instruction>(inst, target)); } break; } } return(result); }
void ProcessMethod(CilBody body, CFContext ctx) { if (!MaxStackCalculator.GetMaxStack(body.Instructions, body.ExceptionHandlers, out var maxStack)) { ctx.Context.Logger.Error("Failed to calcuate maxstack."); throw new ConfuserException(null); } body.MaxStack = (ushort)maxStack; var root = BlockParser.ParseBody(body); GetMangler(ctx.Type).Mangle(body, root, ctx); body.Instructions.Clear(); root.ToBody(body); foreach (var 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; }
public CfGraph(CilBody body) { _body = body; var c = body.Instructions.Count; _instrBlocks = new int[c]; _blocks = new List <CfBlock>(); _indexMap = new Dictionary <Instruction, int>(); for (var i = 0; i < c; i++) { _indexMap.Add(body.Instructions[i], i); } if (c > 0) { var blockHeaders = new HashSet <Instruction>(); var entryHeaders = new HashSet <Instruction>(); PopulateBlockHeaders(blockHeaders, entryHeaders); SplitBlocks(blockHeaders, entryHeaders); LinkBlocks(); MapHandlers(); } }
private static MethodDefUser AddPropertySetter(TypeSig propertyType, string setterName, MethodAttributes attributes, IField backingField, ModuleDef module) { var methodSig = new MethodSig(CallingConvention.HasThis, 0, module.CorLibTypes.Void); methodSig.Params.Add(propertyType); var setter = new MethodDefUser(setterName, methodSig, MethodImplAttributes.Managed | MethodImplAttributes.IL, attributes); var body = new CilBody(); body.Instructions.Emit(OpCodes.Ldarg_0); body.Instructions.Emit(OpCodes.Ldarg_1); body.Instructions.Emit(OpCodes.Stfld, backingField); body.Instructions.Emit(OpCodes.Ret); setter.Body = body; return(setter); }
private 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) { eh.TryEnd = body.Instructions[body.Instructions.IndexOf(eh.TryEnd) + 1]; eh.HandlerEnd = body.Instructions[body.Instructions.IndexOf(eh.HandlerEnd) + 1]; } body.KeepOldMaxStack = true; }
private void btnDeobf_Click(object sender, EventArgs e) { ModuleDefMD md = ModuleDefMD.Load(tbin.Text); if (!IsObfuscator(md)) { MessageBox.Show(null, "This Assembly is not protected with Orange Heap!", NAME, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { foreach (var type in md.Types) { foreach (var method in type.Methods) { if (!method.HasBody) { continue; } CilBody body = method.Body; body.KeepOldMaxStack = true; for (int i = 0; i < body.Instructions.Count; i++) { if (body.Instructions[i].OpCode == OpCodes.Ldstr && body.Instructions[i + 1].OpCode == OpCodes.Call && body.Instructions[i + 1].Operand == target) { body.Instructions[i].Operand = decryptstring(body.Instructions[i].Operand.ToString()); body.Instructions[i + 1].Operand = null; body.Instructions[i + 1].OpCode = OpCodes.Nop; } } } } md.Write(tbout.Text); MessageBox.Show(null, "Saved Assembly to: " + tbout.Text, NAME, MessageBoxButtons.OK, MessageBoxIcon.Information); } }
/// <summary> /// /// </summary> /// <param name="module">The .NET protected ModuleDefMD</param> /// <param name="Methoddecryption">The method which decrypt the strings</param> public static void DecryptStringsInMethod(ModuleDefMD module, MethodDef Methoddecryption) { foreach (TypeDef type in module.Types) { foreach (MethodDef method in type.Methods) { if (!method.HasBody) { break; } for (int i = 0; i < method.Body.Instructions.Count; i++) { if (method.Body.Instructions[i].OpCode == OpCodes.Call) { if (method.Body.Instructions[i].Operand.ToString().ToLower().Contains(Typedecryption.Name.ToLower())) { Type2Remove.Add(Typedecryption); var CalledDecMethod = (MethodDef)method.Body.Instructions[i].Operand; var decryptedstring = ExtractStringFromMethod(CalledDecMethod); if (decryptedstring == "[DEObfuscar] Error") { // } else { CilBody body = method.Body; body.Instructions[i].OpCode = OpCodes.Ldstr; body.Instructions[i].Operand = decryptedstring; DeobedStringNumber = DeobedStringNumber + 1; } } } } } } }
static void Main(string[] args) { string[] file = File.ReadAllLines("precomp.psnbin"); ModuleDefUser mod = newmod("PointySnakeModule"); MethodDefUser entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); startUpType = new TypeDefUser("PointySnake", "Program", mod.CorLibTypes.Object.TypeDefOrRef); mod.Types.Add(startUpType); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed | MethodImplAttributes.AggressiveOptimization; entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); var epBody = new CilBody(); entryPoint.Body = epBody; startUpType.Attributes = TypeAttributes.Public; startUpType.Methods.Add(entryPoint); mod.EntryPoint = entryPoint; currentfunc = mod.EntryPoint; foreach (string line in file) { WriteInstruction(line, mod, currentfunc.Body); } if (epBody.Instructions.Count == 0 || epBody.Instructions[epBody.Instructions.Count - 1].OpCode != OpCodes.Ret) { entryPoint.Body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); entryPoint.Body.Instructions.Add(OpCodes.Ret.ToInstruction()); } entryPoint.Body.OptimizeBranches(); entryPoint.Body.OptimizeMacros(); Console.WriteLine("done"); var options = new ModuleWriterOptions(mod); options.PEHeadersOptions.Machine = dnlib.PE.Machine.AMD64; mod.Write("executable.exe", options); awaitbutton(); }
private void ResolveBody(MethodDef methodDef, MosaMethod.Mutator method, CilBody body, GenericArgumentResolver resolver) { method.LocalVariables.Clear(); int index = 0; foreach (var variable in body.Variables) { method.LocalVariables.Add(new MosaLocal( variable.Name ?? "V_" + index, metadata.Loader.GetType(resolver.Resolve(variable.Type)), variable.Type.IsPinned)); index++; } method.ExceptionBlocks.Clear(); foreach (var eh in body.ExceptionHandlers) { method.ExceptionBlocks.Add(new MosaExceptionHandler( (ExceptionHandlerType)eh.HandlerType, ResolveOffset(body, eh.TryStart), ResolveOffset(body, eh.TryEnd), ResolveOffset(body, eh.HandlerStart), ResolveOffset(body, eh.HandlerEnd), eh.CatchType == null ? null : metadata.Loader.GetType(resolver.Resolve(eh.CatchType.ToTypeSig())), eh.FilterStart == null ? null : (int?)eh.FilterStart.Offset )); } method.MaxStack = methodDef.Body.MaxStack; method.Code.Clear(); for (int i = 0; i < body.Instructions.Count; i++) { method.Code.Add(ResolveInstruction(methodDef, body, i, resolver)); } }
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); if (body.PdbMethod != null) { body.PdbMethod = new PdbMethod() { Scope = new PdbScope() { Start = body.Instructions.First(), End = body.Instructions.Last() } }; } 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; }
/// <summary> /// Initializes a <see cref="CilBody"/> with information found in the PDB file. The /// instructions in <paramref name="body"/> must have valid offsets. This method is /// automatically called by <see cref="ModuleDefMD"/> and you don't need to explicitly call /// it. /// </summary> /// <param name="body">Method body</param> /// <param name="methodRid">Method row ID</param> public void InitializeDontCall(CilBody body, uint methodRid) { if (reader == null || body == null) { return; } var token = new SymbolToken((int)(0x06000000 + methodRid)); ISymbolMethod method; #if THREAD_SAFE theLock.EnterWriteLock(); try { #endif method = reader.GetMethod(token); if (method != null) { body.Scope = CreateScope(body, method.RootScope); AddSequencePoints(body, method); } //TODO: reader.GetSymAttribute() #if THREAD_SAFE } finally { theLock.ExitWriteLock(); } #endif }
public abstract void ToBody(CilBody body);
static PdbScope CreateScope(CilBody body, ISymbolScope symScope) { if (symScope == null) { return(null); } // Don't use recursive calls var stack = new Stack <CreateScopeState>(); var state = new CreateScopeState() { SymScope = symScope }; recursive_call: int instrIndex = 0; state.PdbScope = new PdbScope() { Start = GetInstruction(body.Instructions, state.SymScope.StartOffset, ref instrIndex), End = GetInstruction(body.Instructions, state.SymScope.EndOffset, ref instrIndex), }; foreach (var symLocal in state.SymScope.GetLocals()) { if (symLocal.AddressKind != SymAddressKind.ILOffset) { continue; } int localIndex = symLocal.AddressField1; if ((uint)localIndex >= (uint)body.Variables.Count) { continue; } var local = body.Variables[localIndex]; local.Name = symLocal.Name; var attributes = symLocal.Attributes; if (attributes is int) { local.PdbAttributes = (int)attributes; } state.PdbScope.Variables.Add(local); } foreach (var ns in state.SymScope.GetNamespaces()) { state.PdbScope.Namespaces.Add(ns.Name); } // Here's the now somewhat obfuscated for loop state.ChildrenIndex = 0; state.Children = state.SymScope.GetChildren(); do_return: if (state.ChildrenIndex < state.Children.Length) { var child = state.Children[state.ChildrenIndex]; stack.Push(state); state = new CreateScopeState() { SymScope = child }; goto recursive_call; } if (stack.Count == 0) { return(state.PdbScope); } // Return from recursive call, and execute the last part of the for loop var newPdbScope = state.PdbScope; state = stack.Pop(); state.PdbScope.Scopes.Add(newPdbScope); state.ChildrenIndex++; goto do_return; }
public Trace(CilBody body, bool hasReturnValue) { RefCount = new Dictionary <uint, int>(); BrRefs = new Dictionary <uint, List <Instruction> >(); BeforeStack = new Dictionary <uint, int>(); AfterStack = new Dictionary <uint, int>(); body.UpdateInstructionOffsets(); foreach (ExceptionHandler eh in body.ExceptionHandlers) { BeforeStack[eh.TryStart.Offset] = 0; BeforeStack[eh.HandlerStart.Offset] = (eh.HandlerType != ExceptionHandlerType.Finally ? 1 : 0); if (eh.FilterStart != null) { BeforeStack[eh.FilterStart.Offset] = 1; } } int currentStack = 0; for (int i = 0; i < body.Instructions.Count; i++) { var instr = body.Instructions[i]; if (BeforeStack.ContainsKey(instr.Offset)) { currentStack = BeforeStack[instr.Offset]; } BeforeStack[instr.Offset] = currentStack; instr.UpdateStack(ref currentStack, hasReturnValue); AfterStack[instr.Offset] = currentStack; uint offset; switch (instr.OpCode.FlowControl) { case FlowControl.Branch: offset = ((Instruction)instr.Operand).Offset; if (!BeforeStack.ContainsKey(offset)) { BeforeStack[offset] = currentStack; } Increment(RefCount, offset); BrRefs.AddListEntry(offset, instr); currentStack = 0; continue; case FlowControl.Call: if (instr.OpCode.Code == Code.Jmp) { currentStack = 0; } break; case FlowControl.Cond_Branch: if (instr.OpCode.Code == Code.Switch) { foreach (Instruction target in (Instruction[])instr.Operand) { if (!BeforeStack.ContainsKey(target.Offset)) { BeforeStack[target.Offset] = currentStack; } Increment(RefCount, target.Offset); BrRefs.AddListEntry(target.Offset, instr); } } else { offset = ((Instruction)instr.Operand).Offset; if (!BeforeStack.ContainsKey(offset)) { BeforeStack[offset] = currentStack; } Increment(RefCount, offset); BrRefs.AddListEntry(offset, instr); } break; case FlowControl.Meta: case FlowControl.Next: case FlowControl.Break: break; case FlowControl.Return: case FlowControl.Throw: continue; default: throw new UnreachableException(); } if (i + 1 < body.Instructions.Count) { offset = body.Instructions[i + 1].Offset; Increment(RefCount, offset); } } }
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); } }
(string methodName, DkmClrCompilationResultFlags flags) AddMethod(TypeSig type, int index, bool isLocal) { var methodName = methodNamePrefix + methodNameIndex++.ToString(); var callConv = CallingConvention.Default; if (sourceMethod.MethodSig.Generic) { callConv |= CallingConvention.Generic; } var methodSig = new MethodSig(callConv, sourceMethod.MethodSig.GenParamCount); methodSig.RetType = generatedModule.Import(type.RemovePinnedAndModifiers()); if (methodSig.RetType.IsByRef) { methodSig.RetType = methodSig.RetType.Next.RemovePinnedAndModifiers(); } if (lastMethodSig != null) { foreach (var p in lastMethodSig.Params) { methodSig.Params.Add(p); } } else { if (sourceMethod.MethodSig.HasThis) { methodSig.Params.Add(generatedModule.Import(sourceMethod.DeclaringType).ToTypeSig()); } foreach (var p in sourceMethod.MethodSig.Params) { methodSig.Params.Add(generatedModule.Import(p)); } } const MethodImplAttributes methodImplFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed; const MethodAttributes methodFlags = MethodAttributes.Assembly | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.ReuseSlot; var method = new MethodDefUser(methodName, methodSig, methodImplFlags, methodFlags); getLocalsType.Methods.Add(method); foreach (var gp in sourceMethod.GenericParameters) { method.GenericParameters.Add(Clone(gp)); } var body = new CilBody(); method.Body = body; body.InitLocals = true; if (sourceMethod.Body != null) { foreach (var l in sourceMethod.Body.Variables) { body.Variables.Add(new Local(generatedModule.Import(l.Type), l.Name)); } } body.Instructions.Add(CreateLoadVariable(method, body.Variables, index, isLocal)); if (type.RemovePinnedAndModifiers().GetElementType() == ElementType.ByRef) { body.Instructions.Add(LoadIndirect(type.RemovePinnedAndModifiers().Next.RemovePinnedAndModifiers())); } body.Instructions.Add(Instruction.Create(OpCodes.Ret)); lastMethodSig = methodSig; var flags = DkmClrCompilationResultFlags.None; if (methodSig.RetType.RemovePinnedAndModifiers().GetElementType() == ElementType.Boolean) { flags |= DkmClrCompilationResultFlags.BoolResult; } return(methodName, flags); }
public void Write(CilBody body) { body.Instructions.Clear(); Commit(body); }