Пример #1
0
 public void EmulateUntil(Instruction instruction, CilBody body, Instruction starter)
 {
     Snapshots.Add(new Snapshot(new Stack<StackEntry>(Stack), new Dictionary<int, LocalEntry>(_locals),
                                instruction, _methodBody, null));
     _instructionPointer = starter.GetInstructionIndex(body.Instructions) - 1;
     Trace(() => _methodBody.Instructions[_instructionPointer] != instruction);
 }
Пример #2
0
 public static bool FollowsPattern(
     this Instruction instr,
     CilBody body,
     out Instruction ender,
     List<Predicate<Instruction>> preds,
     int minPatternSize,
     out int patternSize)
 {
     var curInstr = instr;
     ender = null;
     var correct = 0;
     patternSize = 0;
     while (curInstr.Next(body) != null && preds.Any(p => p(curInstr.Next(body))))
     {
         curInstr = curInstr.Next(body);
         correct++;
     }
     if (correct >= minPatternSize)
     {
         patternSize = correct + 1;
         ender = curInstr;
         return true;
     }
     return false;
 }
Пример #3
0
		public void Init(CilBody body) {
			if (inited)
				return;

			xorKey = ctx.Random.NextInt32();
			inited = true;
		}
Пример #4
0
 public void Commit(CilBody body)
 {
     foreach (Local i in localMap.Values) {
         body.InitLocals = true;
         body.Variables.Add(i);
     }
 }
Пример #5
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            body.MaxStack++;
            foreach (InstrBlock block in GetAllBlocks(root)) {
                LinkedList<Instruction[]> fragments = SpiltFragments(block, ctx);
                if (fragments.Count < 4) continue;

                LinkedListNode<Instruction[]> current = fragments.First;
                while (current.Next != null) {
                    var newFragment = new List<Instruction>(current.Value);
                    ctx.AddJump(newFragment, current.Next.Value[0]);
                    ctx.AddJunk(newFragment);
                    current.Value = newFragment.ToArray();
                    current = current.Next;
                }
                Instruction[] first = fragments.First.Value;
                fragments.RemoveFirst();
                Instruction[] last = fragments.Last.Value;
                fragments.RemoveLast();

                List<Instruction[]> newFragments = fragments.ToList();
                ctx.Random.Shuffle(newFragments);

                block.Instructions = first
                    .Concat(newFragments.SelectMany(fragment => fragment))
                    .Concat(last).ToList();
            }
        }
Пример #6
0
 public static IEnumerable<Instruction> FindAllReferences(this Instruction instr, CilBody body)
 {
     foreach (var @ref in body.Instructions.Where(x => (x.IsConditionalBranch() || x.IsBr())))
     {
         if ((@ref.Operand as Instruction) == instr)
             yield return @ref;
     }
 }
Пример #7
0
		public void Init(CilBody body) {
			if (inited)
				return;
			stateVar = new Local(ctx.Method.Module.CorLibTypes.Int32);
			body.Variables.Add(stateVar);
			body.InitLocals = true;
			Compile(body);
			inited = true;
		}
Пример #8
0
		public static void Run() {
			// Create a new module. The string passed in is the name of the module,
			// not the file name.
			ModuleDef mod = new ModuleDefUser("MyModule.exe");
			// It's a console application
			mod.Kind = ModuleKind.Console;

			// Add the module to an assembly
			AssemblyDef asm = new AssemblyDefUser("MyAssembly", new Version(1, 2, 3, 4), null, null);
			asm.Modules.Add(mod);

			// Add a .NET resource
			byte[] resourceData = Encoding.UTF8.GetBytes("Hello, world!");
			mod.Resources.Add(new EmbeddedResource("My.Resource", resourceData,
							ManifestResourceAttributes.Private));

			// Add the startup type. It derives from System.Object.
			TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef);
			startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout |
									TypeAttributes.Class | TypeAttributes.AnsiClass;
			// Add the type to the module
			mod.Types.Add(startUpType);

			// Create the entry point method
			MethodDef entryPoint = new MethodDefUser("Main",
				MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String)));
			entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static |
							MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
			entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
			// Name the 1st argument (argument 0 is the return type)
			entryPoint.ParamDefs.Add(new ParamDefUser("args", 1));
			// Add the method to the startup type
			startUpType.Methods.Add(entryPoint);
			// Set module entry point
			mod.EntryPoint = entryPoint;

			// Create a TypeRef to System.Console
			TypeRef consoleRef = new TypeRefUser(mod, "System", "Console", mod.CorLibTypes.AssemblyRef);
			// Create a method ref to 'System.Void System.Console::WriteLine(System.String)'
			MemberRef consoleWrite1 = new MemberRefUser(mod, "WriteLine",
						MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String),
						consoleRef);

			// Add a CIL method body to the entry point method
			CilBody epBody = new CilBody();
			entryPoint.Body = epBody;
			epBody.Instructions.Add(OpCodes.Ldstr.ToInstruction("Hello World!"));
			epBody.Instructions.Add(OpCodes.Call.ToInstruction(consoleWrite1));
			epBody.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction());
			epBody.Instructions.Add(OpCodes.Ret.ToInstruction());

			// Save the assembly to a file on disk
			mod.Write(@"C:\saved-assembly.exe");
		}
Пример #9
0
		// This will open the current assembly, add a new class and method to it,
		// and then save the assembly to disk.
		public static void Run() {
			// Open the current module
			ModuleDefMD mod = ModuleDefMD.Load(typeof(Example2).Module);

			// Create a new public class that derives from System.Object
			TypeDef type1 = new TypeDefUser("My.Namespace", "MyType",
								mod.CorLibTypes.Object.TypeDefOrRef);
			type1.Attributes = TypeAttributes.Public | TypeAttributes.AutoLayout |
								TypeAttributes.Class | TypeAttributes.AnsiClass;
			// Make sure to add it to the module or any other type in the module. This is
			// not a nested type, so add it to mod.Types.
			mod.Types.Add(type1);

			// Create a public static System.Int32 field called MyField
			FieldDef field1 = new FieldDefUser("MyField",
							new FieldSig(mod.CorLibTypes.Int32),
							FieldAttributes.Public | FieldAttributes.Static);
			// Add it to the type we created earlier
			type1.Fields.Add(field1);

			// Add a static method that adds both inputs and the static field
			// and returns the result
			MethodImplAttributes methImplFlags = MethodImplAttributes.IL | MethodImplAttributes.Managed;
			MethodAttributes methFlags = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot;
			MethodDef meth1 = new MethodDefUser("MyMethod",
						MethodSig.CreateStatic(mod.CorLibTypes.Int32, mod.CorLibTypes.Int32, mod.CorLibTypes.Int32),
						methImplFlags, methFlags);
			type1.Methods.Add(meth1);

			// Create the CIL method body
			CilBody body = new CilBody();
			meth1.Body = body;
			// Name the 1st and 2nd args a and b, respectively
			meth1.ParamDefs.Add(new ParamDefUser("a", 1));
			meth1.ParamDefs.Add(new ParamDefUser("b", 2));

			// Create a local. We don't really need it but let's add one anyway
			Local local1 = new Local(mod.CorLibTypes.Int32);
			body.Variables.Add(local1);

			// Add the instructions, and use the useless local
			body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction());
			body.Instructions.Add(OpCodes.Ldarg_1.ToInstruction());
			body.Instructions.Add(OpCodes.Add.ToInstruction());
			body.Instructions.Add(OpCodes.Ldsfld.ToInstruction(field1));
			body.Instructions.Add(OpCodes.Add.ToInstruction());
			body.Instructions.Add(OpCodes.Stloc.ToInstruction(local1));
			body.Instructions.Add(OpCodes.Ldloc.ToInstruction(local1));
			body.Instructions.Add(OpCodes.Ret.ToInstruction());

			// Save the assembly to a file on disk
			mod.Write(@"C:\saved-assembly.dll");
		}
Пример #10
0
		public void Init(CilBody body) {
			if (inited)
				return;

			encoding = ctx.Context.Annotations.Get<x86Encoding>(ctx.Method.DeclaringType, Encoding, null);
			if (encoding == null) {
				encoding = new x86Encoding();
				encoding.Compile(ctx);
				ctx.Context.Annotations.Set(ctx.Method.DeclaringType, Encoding, encoding);
			}

			inited = true;
		}
Пример #11
0
		public CilBodyOptions(CilBody body, RVA rva, FileOffset fileOffset)
		{
			this.KeepOldMaxStack = body.KeepOldMaxStack;
			this.InitLocals = body.InitLocals;
			this.MaxStack = body.MaxStack;
			this.LocalVarSigTok = body.LocalVarSigTok;
			this.RVA = rva;
			this.FileOffset = fileOffset;
			this.Instructions.AddRange(body.Instructions);
			this.ExceptionHandlers.AddRange(body.ExceptionHandlers);
			this.Locals.AddRange(body.Variables);
			this.Scope = body.Scope;
		}
Пример #12
0
        private ControlFlowGraphBuilder(CilBody methodBody)
        {
            this.methodBody = methodBody;
            offsets = methodBody.Instructions.Select(i => i.Offset).ToArray();
            hasIncomingJumps = new bool[methodBody.Instructions.Count];

            entryPoint = new ControlFlowNode(0, 0, ControlFlowNodeType.EntryPoint);
            nodes.Add(entryPoint);
            regularExit = new ControlFlowNode(1, null, ControlFlowNodeType.RegularExit);
            nodes.Add(regularExit);
            exceptionalExit = new ControlFlowNode(2, null, ControlFlowNodeType.ExceptionalExit);
            nodes.Add(exceptionalExit);
            Debug.Assert(nodes.Count == 3);
        }
Пример #13
0
		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>>();
		}
Пример #14
0
		public CilBodyOptions(CilBody body, RVA headerRva, FileOffset headerFileOffset, RVA rva, FileOffset fileOffset) {
			KeepOldMaxStack = body.KeepOldMaxStack;
			InitLocals = body.InitLocals;
			HeaderSize = body.HeaderSize;
			MaxStack = body.MaxStack;
			LocalVarSigTok = body.LocalVarSigTok;
			HeaderRVA = headerRva;
			HeaderFileOffset = headerFileOffset;
			RVA = rva;
			FileOffset = fileOffset;
			Instructions.AddRange(body.Instructions);
			ExceptionHandlers.AddRange(body.ExceptionHandlers);
			Locals.AddRange(body.Variables);
			Scope = body.Scope;
		}
Пример #15
0
		public CilBody CopyTo(CilBody body) {
			body.KeepOldMaxStack = KeepOldMaxStack;
			body.InitLocals = InitLocals;
			body.HeaderSize = HeaderSize;
			body.MaxStack = MaxStack;
			body.LocalVarSigTok = LocalVarSigTok;
			body.Instructions.Clear();
			body.Instructions.AddRange(Instructions);
			body.ExceptionHandlers.Clear();
			body.ExceptionHandlers.AddRange(ExceptionHandlers);
			body.Variables.Clear();
			body.Variables.AddRange(this.Locals);
			body.Scope = this.Scope;
			body.UpdateInstructionOffsets();
			return body;
		}
Пример #16
0
		public ILStructure(CilBody body)
			: this(ILStructureType.Root, 0, body.GetCodeSize())
		{
			// Build the tree of exception structures:
			for (int i = 0; i < body.ExceptionHandlers.Count; i++) {
				ExceptionHandler eh = body.ExceptionHandlers[i];
				if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd))
					AddNestedStructure(new ILStructure(ILStructureType.Try, (int)eh.TryStart.GetOffset(), (int)eh.TryEnd.GetOffset(), eh));
				if (eh.HandlerType == ExceptionHandlerType.Filter)
					AddNestedStructure(new ILStructure(ILStructureType.Filter, (int)eh.FilterStart.GetOffset(), (int)eh.HandlerStart.GetOffset(), eh));
				AddNestedStructure(new ILStructure(ILStructureType.Handler, (int)eh.HandlerStart.GetOffset(), eh.HandlerEnd == null ? body.GetCodeSize() : (int)eh.HandlerEnd.GetOffset(), eh));
			}
			// Very simple loop detection: look for backward branches
			List<KeyValuePair<Instruction, Instruction>> allBranches = FindAllBranches(body);
			// We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;")
			for (int i = allBranches.Count - 1; i >= 0; i--) {
				int loopEnd = allBranches[i].Key.GetEndOffset();
				int loopStart = (int)allBranches[i].Value.Offset;
				if (loopStart < loopEnd) {
					// We found a backward branch. This is a potential loop.
					// Check that is has only one entry point:
					Instruction entryPoint = null;
					
					// entry point is first instruction in loop if prev inst isn't an unconditional branch
					Instruction prev = body.GetPrevious(allBranches[i].Value);
					if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode))
						entryPoint = allBranches[i].Value;
					
					bool multipleEntryPoints = false;
					foreach (var pair in allBranches) {
						if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) {
							if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) {
								// jump from outside the loop into the loop
								if (entryPoint == null)
									entryPoint = pair.Value;
								else if (pair.Value != entryPoint)
									multipleEntryPoints = true;
							}
						}
					}
					if (!multipleEntryPoints) {
						AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint));
					}
				}
			}
			SortChildren();
		}
Пример #17
0
		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;
		}
Пример #18
0
		public override void ToBody(CilBody body) {
			if (Type != BlockType.Normal) {
				if (Type == BlockType.Try) {
					Handler.TryStart = GetFirstInstr();
					Handler.TryEnd = GetLastInstr();
				}
				else if (Type == BlockType.Filter) {
					Handler.FilterStart = GetFirstInstr();
				}
				else {
					Handler.HandlerStart = GetFirstInstr();
					Handler.HandlerEnd = GetLastInstr();
				}
			}

			foreach (BlockBase block in Children)
				block.ToBody(body);
		}
		public static void WriteTo(this Instruction instruction, MethodDef method, CilBody body, ITextOutput writer)
		{
			writer.WriteDefinition(dnlibExtensions.OffsetToString(instruction.Offset), instruction, true);
			writer.Write(": ");
			writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, true);
			if (instruction.Operand != null) {
				writer.Write(' ');
				if (instruction.OpCode == OpCodes.Ldtoken) {
					if (dnlibExtensions.IsMethod(instruction.Operand))
						writer.WriteKeyword("method ");
					else if (dnlibExtensions.IsField(instruction.Operand))
						writer.WriteKeyword("field ");
				}
				WriteOperand(writer, instruction.Operand);
			}
			else if (method != null && body != null) {
				switch (instruction.OpCode.Code) {
					case Code.Ldloc_0:
					case Code.Ldloc_1:
					case Code.Ldloc_2:
					case Code.Ldloc_3:
						writer.WriteComment("  // ");
						var local = instruction.GetLocal(body.Variables);
						if (local != null)
							WriteOperand(writer, local);
						break;

					case Code.Ldarg_0:
					case Code.Ldarg_1:
					case Code.Ldarg_2:
					case Code.Ldarg_3:
						writer.WriteComment("  // ");
						var arg = instruction.GetParameter(method.Parameters);
						if (arg != null)
							WriteOperand(writer, arg);
						break;
				}
			}
		}
Пример #20
0
        private static CilBody ToCil(MethodDef method, Body body, int index)
        {
            CilBody       nm             = new dnlib.DotNet.Emit.CilBody();
            IList <Local> localVariables = method.Body.Variables.Locals;

            foreach (var localVariableInfo in localVariables)
            {
                nm.Variables.Locals.Add(localVariableInfo);
            }
            ConvertToDnBody(nm, body, index);
            foreach (dnlib.DotNet.Emit.Instruction lmao in nm.Instructions)
            {
                if (lmao.GetOperand() is TargetDisplOperand)
                {
                    var t = (TargetDisplOperand)lmao.Operand;
                    if (t.Displacement > 0)
                    {
                        lmao.Operand = nm.Instructions[t.Displacement];
                    }
                }
            }
            return(nm);
        }
Пример #21
0
        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));
            }
        }
Пример #22
0
        private MosaInstruction ResolveInstruction(MethodDef methodDef, CilBody body, int index, GenericArgumentResolver resolver)
        {
            Instruction instruction = body.Instructions[index];
            int? prev = index == 0 ? null : (int?)body.Instructions[index - 1].Offset;
            int? next = index == body.Instructions.Count - 1 ? null : (int?)body.Instructions[index + 1].Offset;

            object operand = instruction.Operand;

            // Special case: newarr instructions need to have their operand changed now so that the type is a SZArray
            if (instruction.OpCode == OpCodes.Newarr)
            {
                var typeSig = resolver.Resolve(((ITypeDefOrRef)instruction.Operand).ToTypeSig());
                var szArraySig = new SZArraySig(typeSig);
                operand = metadata.Loader.GetType(szArraySig);
            }
            else if (instruction.Operand is ITypeDefOrRef)
            {
                operand = ResolveTypeOperand((ITypeDefOrRef)instruction.Operand, resolver);
            }
            else if (instruction.Operand is MemberRef)
            {
                MemberRef memberRef = (MemberRef)instruction.Operand;
                if (memberRef.IsFieldRef)
                    operand = ResolveFieldOperand(memberRef, resolver);
                else
                    operand = ResolveMethodOperand(memberRef, resolver);
            }
            else if (instruction.Operand is IField)
            {
                operand = ResolveFieldOperand((IField)instruction.Operand, resolver);
            }
            else if (instruction.Operand is IMethod)
            {
                operand = ResolveMethodOperand((IMethod)instruction.Operand, resolver);
            }
            else if (instruction.Operand is Local)
            {
                operand = ((Local)instruction.Operand).Index;
            }
            else if (instruction.Operand is Parameter)
            {
                operand = ((Parameter)instruction.Operand).Index;
            }
            else if (instruction.Operand is Instruction)
            {
                operand = (int)((Instruction)instruction.Operand).Offset;
            }
            else if (instruction.Operand is Instruction[])
            {
                Instruction[] targets = (Instruction[])instruction.Operand;
                int[] offsets = new int[targets.Length];
                for (int i = 0; i < offsets.Length; i++)
                    offsets[i] = (int)targets[i].Offset;
                operand = offsets;
            }
            else if (instruction.Operand is string)
            {
                operand = metadata.Cache.GetStringId((string)instruction.Operand);
            }

            ushort code = (ushort)instruction.OpCode.Code;
            if (code > 0xff)    // To match compiler's opcode values
                code = (ushort)(0x100 + (code & 0xff));

            return new MosaInstruction((int)instruction.Offset, code, operand, prev, next);
        }
Пример #23
0
		/// <summary>
		/// Creates a CIL body. Must be called after <see cref="Read()"/>, and can only be
		/// called once.
		/// </summary>
		/// <returns>A new <see cref="CilBody"/> instance</returns>
		public CilBody CreateCilBody() {
			// Set init locals if it's a tiny method or if the init locals bit is set (fat header)
			bool initLocals = flags == 2 || (flags & 0x10) != 0;
			var cilBody = new CilBody(initLocals, instructions, exceptionHandlers, locals);
			cilBody.MaxStack = maxStack;
			cilBody.LocalVarSigTok = localVarSigTok;
			instructions = null;
			exceptionHandlers = null;
			locals = null;
			return cilBody;
		}
Пример #24
0
 private static int ResolveOffset(CilBody body, Instruction instruction)
 {
     if (instruction == null)
     {
         instruction = body.Instructions[body.Instructions.Count - 1];
         return (int)(instruction.Offset + instruction.GetSize());
     }
     else
         return (int)instruction.Offset;
 }
Пример #25
0
 void Add(CilBody cb)
 {
     if (cb == null)
         return;
     Add(cb.Instructions);
     Add(cb.ExceptionHandlers);
     Add(cb.Variables);
 }
Пример #26
0
 /// <summary>
 /// Updates <paramref name="body"/> with the PDB info (if any)
 /// </summary>
 /// <param name="body">Method body</param>
 /// <param name="rid">Method rid</param>
 /// <returns>Returns originak <paramref name="body"/> value</returns>
 CilBody InitializeBodyFromPdb(CilBody body, uint rid)
 {
     if (pdbState != null)
         pdbState.InitializeDontCall(body, rid);
     return body;
 }
Пример #27
0
		/// <summary>
		/// Constructs a successful devirtualize attempt.
		/// </summary>
		/// <param name="vmethod">Virtualized method</param>
		/// <param name="reader">Method body reader</param>
		/// <param name="body">Devirtualized method body</param>
		public DevirtualizeAttempt(MethodStub vmethod, VirtualizedMethodBodyReader reader, CilBody body)
		{
			this.VirtualizedMethod = vmethod;
			this.Reader = reader;
			this.MethodBody = body;
		}
Пример #28
0
            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);
                    }
                }
            }
Пример #29
0
        public override void Mangle(CilBody body, ScopeBlock root, CFContext ctx)
        {
            Trace trace = new Trace(body, ctx.Method.ReturnType.RemoveModifiers().ElementType != ElementType.Void);
            var local = new Local(ctx.Method.Module.CorLibTypes.UInt32);
            body.Variables.Add(local);
            body.InitLocals = true;

            body.MaxStack += 2;
            IPredicate predicate = null;
            if (ctx.Predicate == PredicateType.Normal) {
                predicate = new NormalPredicate(ctx);
            }
            else if (ctx.Predicate == PredicateType.Expression) {
                predicate = new ExpressionPredicate(ctx);
            }
            else if (ctx.Predicate == PredicateType.x86) {
                predicate = new x86Predicate(ctx);
            }

            foreach (InstrBlock block in GetAllBlocks(root)) {
                LinkedList<Instruction[]> statements = SpiltStatements(block, trace, ctx);

                // Make sure .ctor is executed before switch
                if (ctx.Method.IsInstanceConstructor) {
                    var newStatement = new List<Instruction>();
                    while (statements.First != null) {
                        newStatement.AddRange(statements.First.Value);
                        Instruction lastInstr = statements.First.Value.Last();
                        statements.RemoveFirst();
                        if (lastInstr.OpCode == OpCodes.Call && ((IMethod)lastInstr.Operand).Name == ".ctor")
                            break;
                    }
                    statements.AddFirst(newStatement.ToArray());
                }

                if (statements.Count < 3) continue;

                int i;

                var keyId = Enumerable.Range(0, statements.Count).ToArray();
                ctx.Random.Shuffle(keyId);
                var key = new int[keyId.Length];
                for (i = 0; i < key.Length; i++) {
                    var q = ctx.Random.NextInt32() & 0x7fffffff;
                    key[i] = q - q % statements.Count + keyId[i];
                }

                var statementKeys = new Dictionary<Instruction, int>();
                LinkedListNode<Instruction[]> current = statements.First;
                i = 0;
                while (current != null) {
                    if (i != 0)
                        statementKeys[current.Value[0]] = key[i];
                    i++;
                    current = current.Next;
                }

                var statementLast = new HashSet<Instruction>(statements.Select(st => st.Last()));

                Func<IList<Instruction>, bool> hasUnknownSource;
                hasUnknownSource = instrs => instrs.Any(instr => {
                    if (trace.HasMultipleSources(instr.Offset))
                        return true;
                    List<Instruction> srcs;
                    if (trace.BrRefs.TryGetValue(instr.Offset, out srcs)) {
                        // Target of switch => assume unknown
                        if (srcs.Any(src => src.Operand is Instruction[]))
                            return true;

                        // Not within current instruction block / targeted in first statement
                        if (srcs.Any(src => src.Offset <= statements.First.Value.Last().Offset ||
                                            src.Offset >= block.Instructions.Last().Offset))
                            return true;

                        // Not targeted by the last of statements
                        if (srcs.Any(src => statementLast.Contains(src)))
                            return true;
                    }
                    return false;
                });

                var switchInstr = new Instruction(OpCodes.Switch);
                var switchHdr = new List<Instruction>();

                if (predicate != null) {
                    predicate.Init(body);
                    switchHdr.Add(Instruction.CreateLdcI4(predicate.GetSwitchKey(key[1])));
                    predicate.EmitSwitchLoad(switchHdr);
                }
                else {
                    switchHdr.Add(Instruction.CreateLdcI4(key[1]));
                }

                switchHdr.Add(Instruction.Create(OpCodes.Dup));
                switchHdr.Add(Instruction.Create(OpCodes.Stloc, local));
                switchHdr.Add(Instruction.Create(OpCodes.Ldc_I4, statements.Count));
                switchHdr.Add(Instruction.Create(OpCodes.Rem_Un));
                switchHdr.Add(switchInstr);

                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);
            }
        }
Пример #30
0
		/// <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:
						var target = inst.Operand as Instruction;
						if (target != null)
							result.Add(new KeyValuePair<Instruction, Instruction>(inst, target));
						break;
					case OperandType.InlineSwitch:
						var list = inst.Operand as IList<Instruction>;
						if (list != null) {
							foreach (Instruction target2 in list) {
								if (target2 != null)
									result.Add(new KeyValuePair<Instruction, Instruction>(inst, target2));
							}
						}
						break;
				}
			}
			return result;
		}
Пример #31
0
		public DevirtualizeResults Devirtualize(DevirtualizeOptions options, Action<DevirtualizeAttempt> attemptCallback)
		{
			var methods = this.Parent.FindMethodStubs();

			if (methods.Length == 0)
				return new DevirtualizeResults();

			var attempts = new List<DevirtualizeAttempt>();

			foreach (var method in methods)
			{
				var reader = new VirtualizedMethodBodyReader(method, this.Logger, this.Parent.Version);
				Exception exception = null, fixerException = null;

				try
				{
					reader.Read(); // Read method
				}
				catch (Exception e)
				{
					exception = e;
				}

				DevirtualizeAttempt attempt;

				if (exception == null)
				{
					var body = new CilBody(
						true,
						reader.Instructions,
						reader.ExceptionHandlers,
						reader.Locals
					);

					method.Method.FreeMethodBody();
					method.Method.Body = body;

					// Perform fixes
					try
					{
						PerformFixes(method.Method);
					}
					catch (Exception e)
					{
						fixerException = e;
					}

					if (fixerException == null)
					{
						// Inject DevirtualizedAttribute if specified
						if (options.HasFlag(DevirtualizeOptions.InjectAttributes))
							this.Injector.InjectDevirtualized(method.Method);

						attempt = new DevirtualizeAttempt(method, reader, body);
					}
					else
						attempt = new DevirtualizeAttempt(method, reader, fixerException);
				}
				else
					attempt = new DevirtualizeAttempt(method, reader, exception);

				// Add attempt to list and fire callback
				attempts.Add(attempt);
				if (attemptCallback != null)
					attemptCallback(attempt);
			}

			return new DevirtualizeResults(attempts);
		}