/// <summary>
        /// Adds method body interception to the target method.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method     = IL.GetMethod();
            TypeReference    returnType = method.ReturnType.ReturnType;

            Instruction endLabel = IL.Create(OpCodes.Nop);
            Instruction executeOriginalInstructions = IL.Create(OpCodes.Nop);

            // Execute the method body replacement if and only if
            // interception is enabled
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, executeOriginalInstructions);

            Instruction invokeReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _methodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Ldloc, _classMethodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Br, executeOriginalInstructions);
            IL.Append(invokeReplacement);

            // This is equivalent to the following code:
            // var replacement = provider.GetMethodReplacement(info);
            var invokeMethodReplacement = new InvokeMethodReplacement(executeOriginalInstructions,
                                                                      _methodReplacementProvider,
                                                                      _classMethodReplacementProvider, _invocationInfo);

            invokeMethodReplacement.Emit(IL);

            IL.Emit(OpCodes.Br, endLabel);

            #region The original instruction block

            IL.Append(executeOriginalInstructions);
            var addOriginalInstructions = new AddOriginalInstructions(_oldInstructions, endLabel);
            addOriginalInstructions.Emit(IL);

            #endregion

            // Mark the end of the method body
            IL.Append(endLabel);

            var saveReturnValue = new SaveReturnValue(returnType, _returnValue);
            saveReturnValue.Emit(IL);
        }
示例#2
0
        /// <summary>
        /// Saves the return value from a given method call.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            ModuleDefinition module   = IL.GetModule();
            TypeReference    voidType = module.ImportType(typeof(void));
            bool             returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType;

            if (_returnType is GenericParameter || returnTypeIsValueType)
            {
                IL.Create(OpCodes.Box, _returnType);
            }

            if (_returnType != voidType)
            {
                IL.Create(OpCodes.Stloc, _returnValue);
            }
        }
示例#3
0
        private void changeMethod(MethodDefinition method)
        {
            ModuleDefinition module       = method.DeclaringType.Module;
            MethodInfo       writeline    = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
            MethodReference  writeLineRef = module.Import(writeline);

            CilWorker   cil = method.Body.CilWorker;
            Instruction op1 = cil.Create(OpCodes.Ldstr, "Say hello was called!");
            Instruction op2 = cil.Create(OpCodes.Call, writeLineRef);

            cil.InsertBefore(method.Body.Instructions[0], op1);
            cil.InsertAfter(op1, op2);

            module.Import(method.DeclaringType);
            AssemblyFactory.SaveAssembly(module.Assembly, @"c:\temp\cilTemp\tempasm.dll");
        }
示例#4
0
        public void Emit(CilWorker IL)
        {
            var module         = IL.GetModule();
            var modifiableType = module.ImportType <IModifiableType>();
            var getInterceptionDisabledMethod = module.ImportMethod <IModifiableType>("get_IsInterceptionDisabled");

            if (!_hostMethod.HasThis)
            {
                IL.Emit(OpCodes.Ldc_I4_0);
                IL.Emit(OpCodes.Stloc, _interceptionDisabled);
                return;
            }

            var skipLabel = IL.Create(OpCodes.Nop);

            // var interceptionDisabled = this.IsInterceptionDisabled;
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, modifiableType);
            IL.Emit(OpCodes.Brfalse, skipLabel);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, modifiableType);
            IL.Emit(OpCodes.Callvirt, getInterceptionDisabledMethod);
            IL.Emit(OpCodes.Stloc, _interceptionDisabled);

            IL.Append(skipLabel);
        }
示例#5
0
        /// <summary>
        /// Saves the return value from a given method call.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            var module   = IL.GetModule();
            var voidType = module.ImportType(typeof(void));
            var returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType;

            if (_returnType is GenericParameter || returnTypeIsValueType)
            {
                IL.Create(OpCodes.Box, _returnType);
            }

            if (_returnType != voidType)
            {
                IL.Create(OpCodes.Stloc, _returnValue);
            }
        }
示例#6
0
        public Instruction CreateConditionalBranch()
        {
            Instruction branch      = CilWorker.Create(OpCodes.Nop);
            Instruction instruction = CilWorker.Create(OpCodes.Brtrue, branch);

            instruction.Next = CilWorker.Create(OpCodes.Nop);
            return(instruction);
        }
示例#7
0
        private static void InsertCustomCodeCall(
            MethodDefinition method,
            MethodReference generatedTypeCtorRef,
            MethodReference generatedMethodRef,
            CilWorker cilWorker,
            Instruction instructionToInsertBefore,
            bool replaceMethod
            )
        {
            bool hasReturnValue = (method.ReturnType.ReturnType.FullName != typeof(void).FullName);

            Instruction nop = cilWorker.Create(OpCodes.Nop);

            cilWorker.InsertBefore(instructionToInsertBefore, nop);

            // call ctor
            Instruction newGeneratedType = cilWorker.Create(OpCodes.Newobj, generatedTypeCtorRef);

            cilWorker.InsertBefore(instructionToInsertBefore, newGeneratedType);

            // load arguments on stack if any
            for (int i = 0; i < method.Parameters.Count; i++)
            {
                Instruction loadArg = cilWorker.Create(OpCodes.Ldarga_S, method.Parameters[i]);
                cilWorker.InsertBefore(instructionToInsertBefore, loadArg);
            }

            // call replacing method
            Instruction callGeneratedMethod = cilWorker.Create(OpCodes.Call, generatedMethodRef);

            cilWorker.InsertBefore(instructionToInsertBefore, callGeneratedMethod);

            if (hasReturnValue)
            {
                if (replaceMethod)
                {
                    // add variable to list
                    var generatedValueVar = new VariableDefinition(method.ReturnType.ReturnType);
                    method.Body.Variables.Add(generatedValueVar);
                    // assign to variable
                    Instruction assignNewGeneratedValue = cilWorker.Create(OpCodes.Stloc, generatedValueVar);
                    cilWorker.InsertBefore(instructionToInsertBefore, assignNewGeneratedValue);
                    Instruction ldLoc = cilWorker.Create(OpCodes.Ldloc_0);
                    Instruction brs   = cilWorker.Create(OpCodes.Br_S, ldLoc);
                    cilWorker.InsertBefore(instructionToInsertBefore, brs);
                    cilWorker.InsertBefore(instructionToInsertBefore, ldLoc);
                }
                else
                {
                    // remove value from stack
                    Instruction pop = cilWorker.Create(OpCodes.Pop);
                    cilWorker.InsertBefore(instructionToInsertBefore, pop);
                }
            }
        }
示例#8
0
        /// <summary>
        /// Emits a Console.WriteLine call to using the current CilWorker that will only be called if the contents
        /// of the target variable are null at runtime.
        /// </summary>
        /// <param name="IL">The target CilWorker.</param>
        /// <param name="text">The text that will be written to the console.</param>
        /// <param name="targetVariable">The target variable that will be checked for null at runtime.</param>
        public static void EmitWriteLineIfNull(this CilWorker IL, string text, VariableDefinition targetVariable)
        {
            var skipWrite = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, targetVariable);
            IL.Emit(OpCodes.Brtrue, skipWrite);
            IL.EmitWriteLine(text);
            IL.Append(skipWrite);
        }
        private void EmitCanReplace(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider)
        {
            var skipGetProvider = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, provider);
            IL.Emit(OpCodes.Brfalse, skipGetProvider);

            IL.Emit(OpCodes.Ldloc, provider);

            // Push the host instance
            var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, _canReplace);

            IL.Emit(OpCodes.Stloc, _canReplaceFlag);
            IL.Append(skipGetProvider);
        }
示例#10
0
        public Instruction CreateSwitchBranch()
        {
            Instruction branch1     = CilWorker.Create(OpCodes.Nop);
            Instruction branch2     = CilWorker.Create(OpCodes.Nop);
            Instruction branch3     = CilWorker.Create(OpCodes.Nop);
            Instruction instruction = CilWorker.Create(OpCodes.Switch, new Instruction[] { branch1, branch2, branch3 });

            instruction.Next = CilWorker.Create(OpCodes.Nop);
            return(instruction);
        }
示例#11
0
        public void codeBlock_CallToMethod(MethodDefinition targetMethod, MethodInfo methodToCall)
        {
            CilWorker cliWorker      = targetMethod.Body.CilWorker;
            var       lsInstructions = new List <Instruction>
            {
                cliWorker.Create(OpCodes.Call, getMethodReference(methodToCall))
            };

            CecilOpCodeUtils.addInstructionsToMethod_InsertAtEnd(targetMethod, lsInstructions);
        }
示例#12
0
 private static bool hookStaticVoidMethodAtBegin_Int(MethodDefinition hookedMethod, MethodDefinition callMeth)
 {
     try {
         CilWorker initProc = hookedMethod.Body.CilWorker;
         initProc.InsertBefore(hookedMethod.Body.Instructions[0], initProc.Create(OpCodes.Call,
                                                                                  baseAssembly.MainModule.Import(callMeth.Resolve())));
         return(true);
     } catch {
         return(false);
     }
 }
示例#13
0
        public void Rewrite(MethodDefinition method, CilWorker IL,
                            IEnumerable <Instruction> oldInstructions)
        {
            var targetMethod = _parameters.TargetMethod;
            var worker       = targetMethod.GetILGenerator();
            var module       = worker.GetModule();

            _getInterceptionDisabled.Emit(worker);

            // Construct the InvocationInfo instance
            var skipInvocationInfo = worker.Create(OpCodes.Nop);

            worker.Emit(OpCodes.Ldloc, _parameters.InterceptionDisabled);
            worker.Emit(OpCodes.Brtrue, skipInvocationInfo);


            var interceptedMethod = targetMethod;

            _emitter.Emit(targetMethod, interceptedMethod, _parameters.InvocationInfo);


            var skipGetReplacementProvider = IL.Create(OpCodes.Nop);

            // var provider = this.MethodReplacementProvider;
            //IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            //IL.Emit(OpCodes.Brtrue, skipGetReplacementProvider);
            _getInstanceMethodReplacementProvider.Emit(IL);
            _surroundMethodBody.AddProlog(worker);
            IL.Append(skipGetReplacementProvider);

            worker.Append(skipInvocationInfo);

            _getClassMethodReplacementProvider.Emit(worker);



            var returnType = targetMethod.ReturnType.ReturnType;

            _addMethodReplacement.Emit(worker);

            // Save the return value
            TypeReference voidType = module.Import(typeof(void));

            _surroundMethodBody.AddEpilog(worker);

            if (returnType != voidType)
            {
                worker.Emit(OpCodes.Ldloc, _parameters.ReturnValue);
            }

            worker.Emit(OpCodes.Ret);
        }
示例#14
0
        private void EmitGetMethodReplacement(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider)
        {
            // var replacement = MethodReplacementProvider.GetReplacement(info);
            IL.Emit(OpCodes.Ldloc, provider);

            // Push the host instance
            Instruction pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, _getReplacement);
            IL.Emit(OpCodes.Stloc, _replacement);
        }
示例#15
0
        protected override void Replace(Instruction oldInstruction, MethodDefinition hostMethod,
                                        CilWorker IL)
        {
            var targetMethod = (MethodReference)oldInstruction.Operand;

            var callOriginalMethod = IL.Create(OpCodes.Nop);
            var returnType         = targetMethod.ReturnType.ReturnType;
            var endLabel           = IL.Create(OpCodes.Nop);
            var module             = hostMethod.DeclaringType.Module;

            // Create the stack that will hold the method arguments
            IL.Emit(OpCodes.Newobj, _stackCtor);
            IL.Emit(OpCodes.Stloc, _currentArguments);

            // Make sure that the argument stack doesn't show up in
            // any of the other interception routines
            IgnoreLocal(IL, _currentArguments, module);

            SaveInvocationInfo(IL, targetMethod, module, returnType);

            var getInterceptionDisabled = new GetInterceptionDisabled(hostMethod, _interceptionDisabled);

            getInterceptionDisabled.Emit(IL);

            var surroundMethodBody = new SurroundMethodBody(_methodReplacementProvider, _aroundInvokeProvider,
                                                            _invocationInfo, _interceptionDisabled, _returnValue,
                                                            typeof(AroundInvokeMethodCallRegistry),
                                                            "AroundMethodCallProvider");

            surroundMethodBody.AddProlog(IL);
            // Use the MethodReplacementProvider attached to the
            // current host instance
            Replace(IL, oldInstruction, targetMethod, hostMethod, endLabel, callOriginalMethod);

            IL.Append(endLabel);

            surroundMethodBody.AddEpilog(IL);
        }
示例#16
0
        private void EmitCreateMethodActivationContext(MethodDefinition method, CilWorker IL, TypeReference concreteType)
        {
            // TODO: Add static method support
            var pushThis = method.IsStatic ? IL.Create(OpCodes.Ldnull) : IL.Create(OpCodes.Ldarg_0);

            // Push the 'this' pointer onto the stack
            IL.Append(pushThis);

            var module = method.DeclaringType.Module;

            // Push the current method onto the stack
            IL.PushMethod(method, module);

            // Push the concrete type onto the stack
            IL.Emit(OpCodes.Ldtoken, concreteType);
            IL.Emit(OpCodes.Call, _getTypeFromHandle);

            IL.Emit(OpCodes.Ldloc, _constructorArguments);
            IL.Emit(OpCodes.Callvirt, _toArrayMethod);
            IL.Emit(OpCodes.Newobj, _methodActivationContextCtor);

            // var context = new MethodActivationContext(this, currentMethod, concreteType, args);
            IL.Emit(OpCodes.Stloc, _methodContext);
        }
示例#17
0
        override protected void ProcessMethod(MethodDefinition method)
        {
            if (!method.HasBody)
            {
                return;
            }

            MethodBody  body             = method.Body;
            Instruction firstInstruction = body.Instructions[0];
            CilWorker   worker           = body.CilWorker;

            // ldstr "TRACE: " + method
            worker.InsertBefore(firstInstruction,
                                worker.Create(OpCodes.Ldstr, "TRACE: " + method));

            // call Console.WriteLine(string)
            MethodReference Console_WriteLine =
                Import(typeof(Console).GetMethod(
                           "WriteLine", new Type[] { typeof(string) })
                       );

            worker.InsertBefore(firstInstruction,
                                worker.Create(OpCodes.Call, Console_WriteLine));
        }
示例#18
0
        public void AddEpilog(CilWorker IL)
        {
            var skipEpilog = IL.Create(OpCodes.Nop);

            // if (!IsInterceptionDisabled && surroundingImplementation != null) {
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipEpilog);

            // surroundingImplementation.AfterInvoke(invocationInfo, returnValue);
            var emitAfterInvoke = new EmitAfterInvoke(_surroundingImplementation, _surroundingClassImplementation, _invocationInfo, _returnValue);

            emitAfterInvoke.Emit(IL);

            // }
            IL.Append(skipEpilog);
        }
示例#19
0
        private void GetInstanceProvider(CilWorker IL)
        {
            var skipInstanceProvider = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, _hostInterfaceType);
            IL.Emit(OpCodes.Brfalse, skipInstanceProvider);
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, _hostInterfaceType);
            IL.Emit(OpCodes.Callvirt, _getProvider);
            IL.Emit(OpCodes.Stloc, _instanceProvider);

            IL.Emit(OpCodes.Ldloc, _instanceProvider);
            IL.Emit(OpCodes.Brtrue, skipInstanceProvider);

            IL.Append(skipInstanceProvider);
        }
        public void WeaveConstructorCalls(IEnumerable <ConstructorCallWeave> weaves, FactoryMap factories)
        {
            MethodInfo getFactoryMethod = typeof(Factories).GetMethod("Create");

            foreach (ConstructorCallWeave weave in weaves)
            {
                Factory factory = factories.GetForObjectType(weave.Constructor.DeclaringType);
                _log.Log("Weaving {0} in {1}", factory.ObjectType, weave.ParentMethod);

                MethodReference       getObjectMethodReference = weave.ParentAssembly.Import(getFactoryMethod);
                GenericInstanceMethod methodCall = new GenericInstanceMethod(getObjectMethodReference);
                methodCall.GenericArguments.Add(factory.ObjectType);

                CilWorker   worker         = weave.ParentMethod.Body.CilWorker;
                Instruction callGetFactory = worker.Create(OpCodes.Call, methodCall);
                worker.Replace(weave.NewInstruction, callGetFactory);
            }
        }
        public void Emit(CilWorker IL)
        {
            var module            = IL.GetModule();
            var method            = IL.GetMethod();
            var returnType        = method.ReturnType.ReturnType;
            var methodReplacement = MethodDefinitionExtensions.AddLocal(method, typeof(IInterceptor));

            GetMethodReplacementInstance(method, IL, methodReplacement, _methodReplacementProvider, _invocationInfo);

            var skipGetClassMethodReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, methodReplacement);
            IL.Emit(OpCodes.Brtrue, skipGetClassMethodReplacement);

            GetMethodReplacementInstance(method, IL, methodReplacement, _classMethodReplacementProvider, _invocationInfo);

            IL.Append(skipGetClassMethodReplacement);
            IL.Emit(OpCodes.Ldloc, methodReplacement);
            IL.Emit(OpCodes.Brfalse, _executeOriginalInstructions);

            // var returnValue = replacement.Intercept(info);
            InvokeInterceptor(module, IL, methodReplacement, returnType, _invocationInfo);
        }
示例#22
0
 private static bool hookStaticVoidMethodAtEnd_Int(MethodDefinition hookedMethod, MethodDefinition callMeth)
 {
     try {
         HashSet <Instruction> retInstructions = new HashSet <Instruction>();
         foreach (Instruction instr in hookedMethod.Body.Instructions)
         {
             if (instr.OpCode == OpCodes.Ret)
             {
                 retInstructions.Add(instr);
             }
         }
         CilWorker initProc  = hookedMethod.Body.CilWorker;
         bool      overriden = false;
         foreach (Instruction ret in retInstructions)
         {
             initProc.InsertBefore(ret, initProc.Create(OpCodes.Call,
                                                        baseAssembly.MainModule.Import(callMeth.Resolve())));
             overriden = true;
         }
         return(overriden);
     } catch {
         return(false);
     }
 }
        /// <summary>
        /// Rewrites the instructions in the target method body to support dynamic exception handling.
        /// </summary>
        /// <param name="targetMethod">The target method.</param>
        /// <param name="IL">The <see cref="CilWorker"/> instance that represents the method body.</param>
        /// <param name="oldInstructions">The IL instructions of the original method body.</param>
        protected override void RewriteMethodBody(MethodDefinition targetMethod, CilWorker IL,
                                                  IEnumerable <Instruction> oldInstructions)
        {
            var endOfOriginalInstructionBlock = IL.Create(OpCodes.Nop);
            var addOriginalInstructions       = new AddOriginalInstructions(oldInstructions, endOfOriginalInstructionBlock);


            var endLabel   = IL.Create(OpCodes.Nop);
            var tryStart   = IL.Emit(OpCodes.Nop);
            var tryEnd     = IL.Emit(OpCodes.Nop);
            var catchStart = IL.Emit(OpCodes.Nop);
            var catchEnd   = IL.Emit(OpCodes.Nop);

            var module  = IL.GetModule();
            var handler = new ExceptionHandler(ExceptionHandlerType.Catch);
            var body    = targetMethod.Body;

            body.ExceptionHandlers.Add(handler);

            handler.CatchType = module.ImportType <Exception>();

            handler.TryStart = tryStart;
            handler.TryEnd   = tryEnd;

            handler.HandlerStart = catchStart;
            handler.HandlerEnd   = catchEnd;

            var emitter = new InvocationInfoEmitter(true);

            var returnType = targetMethod.ReturnType.ReturnType;

            // try {
            IL.Append(tryStart);
            addOriginalInstructions.Emit(IL);

            IL.Append(endOfOriginalInstructionBlock);
            if (returnType != _voidType && _returnValue != null)
            {
                IL.Emit(OpCodes.Stloc, _returnValue);
            }

            IL.Emit(OpCodes.Leave, endLabel);

            // }
            IL.Append(tryEnd);
            // catch (Exception ex) {
            IL.Append(catchStart);
            IL.Emit(OpCodes.Stloc, _exception);

            SaveExceptionInfo(targetMethod, emitter);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);

            var getHandlerMethodInfo = typeof(ExceptionHandlerRegistry).GetMethod("GetHandler");
            var getHandlerMethod     = module.Import(getHandlerMethodInfo);

            IL.Emit(OpCodes.Call, getHandlerMethod);
            IL.Emit(OpCodes.Stloc, _exceptionHandler);

            // if (exceptionHandler == null)
            //      throw;
            var doRethrow = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Brfalse, doRethrow);


            // if (handler.CanCatch(exceptionInfo)) {
            var leaveBlock = IL.Create(OpCodes.Nop);
            var canCatch   = module.ImportMethod <IExceptionHandler>("CanCatch");

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, canCatch);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            var catchMethod = module.ImportMethod <IExceptionHandler>("Catch");

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, catchMethod);
            // }


            var getShouldSkipRethrow = module.ImportMethod <IExceptionHandlerInfo>("get_ShouldSkipRethrow");

            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, getShouldSkipRethrow);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            IL.Emit(OpCodes.Br, leaveBlock);

            IL.Append(doRethrow);
            IL.Emit(OpCodes.Rethrow);

            IL.Append(leaveBlock);

            IL.Emit(OpCodes.Leave, endLabel);
            IL.Append(catchEnd);
            // }
            IL.Append(endLabel);

            if (returnType != _voidType && _returnValue != null)
            {
                var returnOriginalValue = IL.Create(OpCodes.Nop);
                var getReturnValue      = module.ImportMethod <IExceptionHandlerInfo>("get_ReturnValue");

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Brfalse, returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Callvirt, getReturnValue);
                IL.Emit(OpCodes.Stloc, _returnValue);
                IL.Append(returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _returnValue);
            }

            IL.Emit(OpCodes.Ret);
        }
示例#24
0
        private void InjectCustomCode(MethodDefinition method, MethodHook methodHook)
        {
            // generate assembly with custom code
            m_codeGenerator.GenerateAssembly(methodHook, Path.GetDirectoryName(m_assemblyPath));

            // load generated assembly
            string             assemblyName      = methodHook.GetSafeName();
            AssemblyDefinition generatedAssembly = LoadGeneratedAssembly(assemblyName);

            // get method reference with custom code
            string generatedClassName  = String.Format("{0}_{1}", assemblyName, "Class");
            var    generatedType       = generatedAssembly.MainModule.Types.Cast <TypeDefinition>().First(t => t.Name == generatedClassName);
            string generatedMethodName = String.Format("{0}_{1}", assemblyName, "Hook");
            // TODO: take parameter types into account, to resolve methods with the same names
            var             generatedMethod   = generatedType.Methods.Cast <MethodDefinition>().First(m => m.Name == generatedMethodName);
            MethodReference generatedTypeCtor = null;

            for (int i = 0; i <= generatedType.Constructors.Count; i++)
            {
                if (!generatedType.Constructors[i].HasParameters)
                {
                    generatedTypeCtor = generatedType.Constructors[i];
                    break;
                }
            }
            if (generatedTypeCtor == null)
            {
                throw new InvalidOperationException("Default constructor was not found in generated assembly");
            }

            // inject call
            MethodReference generatedTypeCtorRef = m_assemblyDefinition.MainModule.Import(generatedTypeCtor);
            MethodReference generatedMethodRef   = m_assemblyDefinition.MainModule.Import(generatedMethod);

            method.Body.InitLocals = true;

            CilWorker cilWorker = method.Body.CilWorker;

            if (methodHook.HookType == HookType.ReplaceMethod)
            {
                method.Body.Instructions.Clear();
                method.Body.Variables.Clear();
                // return value
                Instruction returnInstruction = cilWorker.Create(OpCodes.Ret);
                cilWorker.Append(returnInstruction);
                InsertCustomCodeCall(method, generatedTypeCtorRef, generatedMethodRef, cilWorker, returnInstruction, true);
            }
            else if ((methodHook.HookType & HookType.OnMethodEnter) == HookType.OnMethodEnter)
            {
                Instruction firstInstruction = method.Body.Instructions[0];
                InsertCustomCodeCall(method, generatedTypeCtorRef, generatedMethodRef, cilWorker, firstInstruction, false);
            }
            else if ((methodHook.HookType & HookType.OnMethodExit) == HookType.OnMethodExit)
            {
                Instruction returnInstruction = method.Body.Instructions[method.Body.Instructions.Count - 1];
                if (returnInstruction.OpCode != OpCodes.Ret)
                {
                    throw new InvalidOperationException(String.Format("Method '{0}' has no valid ret instruction", method.Name));
                }
                InsertCustomCodeCall(method, generatedTypeCtorRef, generatedMethodRef, cilWorker, returnInstruction, false);
            }
        }
示例#25
0
        /// <summary>
        /// Emits the IL to save information about
        /// the method currently being executed.
        /// </summary>
        /// <seealso cref="IInvocationInfo"/>
        /// <param name="targetMethod">The target method currently being executed.</param>
        /// <param name="interceptedMethod">The method that will be passed to the <paramref name="invocationInfo"/> as the currently executing method.</param>
        /// <param name="invocationInfo">The local variable that will store the resulting <see cref="IInvocationInfo"/> instance.</param>
        public void Emit(MethodDefinition targetMethod, MethodReference interceptedMethod,
                         VariableDefinition invocationInfo)
        {
            ModuleDefinition   module         = targetMethod.DeclaringType.Module;
            VariableDefinition currentMethod  = MethodDefinitionExtensions.AddLocal(targetMethod, typeof(MethodBase));
            VariableDefinition parameterTypes = MethodDefinitionExtensions.AddLocal(targetMethod, typeof(Type[]));
            VariableDefinition arguments      = MethodDefinitionExtensions.AddLocal(targetMethod, typeof(object[]));
            VariableDefinition typeArguments  = MethodDefinitionExtensions.AddLocal(targetMethod, typeof(Type[]));
            TypeReference      systemType     = ModuleDefinitionExtensions.ImportType(module, typeof(Type));

            CilWorker IL = MethodDefinitionExtensions.GetILGenerator(targetMethod);

            #region Initialize the InvocationInfo constructor arguments

            // Type[] typeArguments = new Type[genericTypeCount];
            int genericParameterCount = targetMethod.GenericParameters.Count;
            IL.Emit(OpCodes.Ldc_I4, genericParameterCount);
            IL.Emit(OpCodes.Newarr, systemType);
            IL.Emit(OpCodes.Stloc, typeArguments);

            // object[] arguments = new object[argumentCount];
            IL.PushArguments(targetMethod, module, arguments);

            // object target = this;
            if (targetMethod.HasThis)
            {
                IL.Emit(OpCodes.Ldarg_0);
            }
            else
            {
                IL.Emit(OpCodes.Ldnull);
            }

            IL.PushMethod(interceptedMethod, module);

            IL.Emit(OpCodes.Stloc, currentMethod);

            // MethodBase targetMethod = currentMethod as MethodBase;
            IL.Emit(OpCodes.Ldloc, currentMethod);

            // Push the generic type arguments onto the stack
            if (genericParameterCount > 0)
            {
                IL.PushGenericArguments(targetMethod, module, typeArguments);
            }

            // Make sure that the generic methodinfo is instantiated with the
            // proper type arguments
            if (targetMethod.GenericParameters.Count > 0)
            {
                TypeReference methodInfoType = module.Import(typeof(MethodInfo));
                IL.Emit(OpCodes.Isinst, methodInfoType);

                MethodReference getIsGenericMethodDef = module.ImportMethod <MethodInfo>("get_IsGenericMethodDefinition");
                IL.Emit(OpCodes.Dup);
                IL.Emit(OpCodes.Callvirt, getIsGenericMethodDef);

                // Determine if the current method is a generic method
                // definition
                Instruction skipMakeGenericMethod = IL.Create(OpCodes.Nop);
                IL.Emit(OpCodes.Brfalse, skipMakeGenericMethod);

                // Instantiate the specific generic method instance
                MethodReference makeGenericMethod = module.ImportMethod <MethodInfo>("MakeGenericMethod", typeof(Type[]));
                IL.Emit(OpCodes.Ldloc, typeArguments);
                IL.Emit(OpCodes.Callvirt, makeGenericMethod);
                IL.Append(skipMakeGenericMethod);
            }

            if (_pushStackTrace)
            {
                IL.PushStackTrace(module);
            }
            else
            {
                IL.Emit(OpCodes.Ldnull);
            }

            // Save the parameter types
            IL.Emit(OpCodes.Ldc_I4, targetMethod.Parameters.Count);
            IL.Emit(OpCodes.Newarr, systemType);
            IL.Emit(OpCodes.Stloc, parameterTypes);

            IL.SaveParameterTypes(targetMethod, module, parameterTypes);
            IL.Emit(OpCodes.Ldloc, parameterTypes);

            // Push the type arguments back onto the stack
            IL.Emit(OpCodes.Ldloc, typeArguments);

            // Save the return type
            MethodReference getTypeFromHandle = module.Import(_getTypeFromHandle);

            TypeReference returnType = targetMethod.ReturnType.ReturnType;
            IL.Emit(OpCodes.Ldtoken, returnType);
            IL.Emit(OpCodes.Call, getTypeFromHandle);

            // Push the arguments back onto the stack
            IL.Emit(OpCodes.Ldloc, arguments);

            #endregion

            // InvocationInfo info = new InvocationInfo(...);
            MethodReference infoConstructor = module.Import(_invocationInfoConstructor);
            IL.Emit(OpCodes.Newobj, infoConstructor);
            IL.Emit(OpCodes.Stloc, invocationInfo);
            IL.Emit(OpCodes.Ldloc, invocationInfo);

            MethodReference addInstance = module.Import(typeof(IgnoredInstancesRegistry).GetMethod("AddInstance"));
            IL.Emit(OpCodes.Call, addInstance);
        }
        public void StoreFactoryMap(IAssembly assembly, FactoryMap factoryMap)
        {
            MethodInfo      getTypeFromHandleReflect = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
            MethodReference getTypeFromHandle        = assembly.Import(getTypeFromHandleReflect);
            TypeReference   systemType          = assembly.Import(typeof(Type));
            TypeReference   arrayOfTypes        = assembly.Import(typeof(Type[]));
            TypeReference   arrayOfArrayOfTypes = assembly.Import(typeof(Type[][]));

            // Now we create the actual type and stuff...
            TypeDefinition   mapType            = GetFactoryMapType(assembly);
            MethodDefinition getFactoriesMethod = new MethodDefinition(FactoryMapMethodName, MethodAttributes.Public, arrayOfArrayOfTypes);

            getFactoriesMethod.IsVirtual = true;
            mapType.Methods.Add(getFactoriesMethod);

            getFactoriesMethod.Body.Variables.Add(new VariableDefinition("map", 0, getFactoriesMethod, arrayOfArrayOfTypes));
            getFactoriesMethod.Body.Variables.Add(new VariableDefinition("row", 1, getFactoriesMethod, arrayOfTypes));
            getFactoriesMethod.Body.InitLocals = true;

            CilWorker      worker    = getFactoriesMethod.Body.CilWorker;
            List <Factory> factories = new List <Factory>(factoryMap.Factories);

            worker.Append(worker.Create(OpCodes.Nop));
            worker.Append(worker.Create(OpCodes.Ldc_I4, factories.Count));
            worker.Append(worker.Create(OpCodes.Newarr, arrayOfTypes));
            worker.Append(worker.Create(OpCodes.Stloc_0));
            worker.Append(worker.Create(OpCodes.Ldloc_0));

            int index = 0;

            foreach (Factory factory in factories)
            {
                worker.Append(worker.Create(OpCodes.Ldc_I4, index));

                worker.Append(worker.Create(OpCodes.Ldc_I4, 2));
                worker.Append(worker.Create(OpCodes.Newarr, systemType));
                worker.Append(worker.Create(OpCodes.Stloc_1));

                worker.Append(worker.Create(OpCodes.Ldloc_1));
                worker.Append(worker.Create(OpCodes.Ldc_I4_0));
                worker.Append(worker.Create(OpCodes.Ldtoken, factory.ObjectType));
                worker.Append(worker.Create(OpCodes.Call, getTypeFromHandle));
                worker.Append(worker.Create(OpCodes.Stelem_Ref));

                worker.Append(worker.Create(OpCodes.Ldloc_1));
                worker.Append(worker.Create(OpCodes.Ldc_I4_1));
                worker.Append(worker.Create(OpCodes.Ldtoken, factory.FactoryType));
                worker.Append(worker.Create(OpCodes.Call, getTypeFromHandle));
                worker.Append(worker.Create(OpCodes.Stelem_Ref));

                worker.Append(worker.Create(OpCodes.Ldloc_1));
                worker.Append(worker.Create(OpCodes.Stelem_Ref));
                index++;
                worker.Append(worker.Create(OpCodes.Ldloc_0));
            }

            worker.Append(worker.Create(OpCodes.Ret));
            assembly.Inject(mapType);
        }
示例#27
0
        public static bool Run(string dllFile, string projectFile)
        {
            if (!File.Exists(projectFile))
            {
                WriteLineStatus("Project file not found.");
                return(false);
            }
            if (!File.Exists(dllFile))
            {
                WriteLineStatus("Compiled DLL not found.");
                return(false);
            }
            try
            {
                List <Function> functions = GetFunctionsWithAttribute(projectFile, "ApiExtension");


                AssemblyDefinition assembly =
                    AssemblyFactory.GetAssembly(
                        dllFile);

                assembly.MainModule.LoadSymbols();

                StringBuilder sb = new StringBuilder();

                // Gets all types which are declared in the Main Module of the assembly
                foreach (TypeDefinition type in assembly.MainModule.Types)
                {
                    // Writes the full name of a type
                    sb.AppendLine(type.FullName);

                    // Gets all methods of the current type
                    foreach (MethodDefinition method in type.Methods)
                    {
                        if (method.CustomAttributes.Count > 0)
                        {
                            string attributeName = method.CustomAttributes[0].Constructor.DeclaringType.Name;

                            if (attributeName == "ApiExtensionAttribute")
                            {
                                bool matchingFunctionFound = false;

                                List <Function> possibleMathes = new List <Function>();

                                // Find the matching function in the source-code functions
                                foreach (Function function in functions)
                                {
                                    if (function.Name != method.Name)
                                    {
                                        continue;
                                    }
                                    bool   isMatch    = false;
                                    string signature1 = function.FullyQualifiedDisplayNameWithBCLTypes.Replace(".Fields.Constructors.Properties.Functions.Inner Classes", "").Replace(".Fields.Constructors.Properties.Functions", "").Replace(".Fields.Constructors.Functions", "").Replace(".Constructors.Functions", "").Replace(".Functions", "").Replace(" ", "").ToLower();
                                    string signature2 = GetFullyQualifiedDisplayName(type, method).ToLower();

                                    if (function.Name == method.Name)
                                    {
                                        //string gg = "";
                                    }
                                    isMatch = signature1 == signature2;

                                    if (isMatch)
                                    {
                                        possibleMathes.Add(function);
                                    }
                                    else
                                    {
                                        // It might still be a match, but parameter types might be qualified differently
                                        //if (function.FullyQualifiedName.IndexOf(type.FullName.Replace("/", ".Fields.Constructors.Properties.Functions.Inner Classes.")) == 0 && method.Name == function.Name && method.Parameters.Count == function.Parameters.Count)
                                        string name1 = function.FullyQualifiedName.Replace(".Fields.Constructors.Properties.Functions.Inner Classes", "").Replace(".Fields.Constructors.Properties.Functions", "").Replace(".Fields.Constructors.Functions", "").Replace(".Constructors.Functions", "").Replace(".Functions", "");
                                        string name2 = string.Format("{0}.{1}", type.FullName, method.Name).Replace("/", ".");

                                        if (name1 == name2 && method.Parameters.Count == function.Parameters.Count)
                                        {
                                            bool parametersMatch = true;

                                            for (int paramCounter = 0; paramCounter < method.Parameters.Count; paramCounter++)
                                            {
                                                if (method.Parameters[paramCounter].Name != function.Parameters[paramCounter].Name)
                                                {
                                                    parametersMatch = false;
                                                    break;
                                                }
                                            }
                                            if (parametersMatch)
                                            {
                                                if (!method.IsPublic)
                                                {
                                                    WriteLineStatus(string.Format("Function is not public: {0}.{1}", type.FullName, method.Name));
                                                    return(false);
                                                }
                                                possibleMathes.Add(function);
                                            }
                                        }
                                    }
                                }
                                if (possibleMathes.Count == 0)
                                {
                                    WriteLineStatus(string.Format("Function not found in source-code: {0}.{1}", type.FullName, method.Name));
                                    return(false);
                                }
                                else if (possibleMathes.Count == 1)
                                {
                                    // No need to perform any further checks
                                    matchingFunctionFound = true;
                                    StringBuilder xmlComments = new StringBuilder(100);

                                    foreach (string xmlComment in possibleMathes[0].XmlComments)
                                    {
                                        xmlComments.AppendLine(xmlComment);
                                    }
                                    string functionBody = Slyce.Common.Utility.StandardizeLineBreaks(possibleMathes[0].BodyText,
                                                                                                     Slyce.Common.Utility.LineBreaks.Unix).
                                                          Replace("\n", "");
                                    functionBody = CleanFunctionBodyEnds(functionBody);

                                    if (method.CustomAttributes[0].ConstructorParameters.Count == 0)
                                    {
                                        method.CustomAttributes.RemoveAt(0);
                                        CustomAttribute ca = new CustomAttribute(assembly.MainModule.Import(
                                                                                     typeof(ArchAngel.Interfaces.Attributes.ApiExtensionAttribute).
                                                                                     GetConstructor(
                                                                                         new Type[] { typeof(string), typeof(string) })));

                                        ca.ConstructorParameters.Clear();
                                        ca.ConstructorParameters.Add(xmlComments.ToString());
                                        ca.ConstructorParameters.Add(functionBody);

                                        method.CustomAttributes.Add(ca);
                                    }
                                    else if (method.CustomAttributes[0].ConstructorParameters.Count == 2)
                                    {
                                        method.CustomAttributes[0].ConstructorParameters[0] = xmlComments.ToString();
                                        method.CustomAttributes[0].ConstructorParameters[1] = functionBody;
                                    }
                                    else
                                    {
                                        WriteLineStatus("FAILED - ApiExtensionAttribute has unexpected number of arguments: " + method.Name);
                                        return(false);
                                    }
                                    WriteLineStatus("Processed: " + method.Name);
                                }
                                else
                                {
                                    bool parametersMatch = true;
                                    matchingFunctionFound = false;

                                    foreach (Function function in possibleMathes)
                                    {
                                        for (int paramCounter = 0; paramCounter < method.Parameters.Count; paramCounter++)
                                        {
                                            if (method.Parameters[paramCounter].ParameterType.Name != function.Parameters[paramCounter].DataType)
                                            {
                                                parametersMatch = false;
                                                break;
                                            }
                                        }
                                        if (parametersMatch)
                                        {
                                            matchingFunctionFound = true;
                                            method.CustomAttributes[0].ConstructorParameters[0] = function.Comments.PreceedingComments;
                                            method.CustomAttributes[0].ConstructorParameters[1] =
                                                CleanFunctionBodyEnds(Slyce.Common.Utility.StandardizeLineBreaks(function.BodyText, Slyce.Common.Utility.LineBreaks.Unix).Replace(
                                                                          "\n", ""));
                                            break;
                                        }
                                    }
                                    if (!matchingFunctionFound)
                                    {
                                        WriteLineStatus("Many possible matching functions found in source-code: " + method.Name);
                                        return(false);
                                    }
                                }
                                //}

                                if (method.Body == null)
                                {
                                    continue;
                                }
                                // Gets the CilWorker of the method for working with CIL instructions
                                CilWorker      worker          = method.Body.CilWorker;
                                FieldReference projectInstance = assembly.MainModule.Import(typeof(SharedData).GetField("CurrentProject"));
                                //MethodReference projectInstance =
                                //    assembly.MainModule.Import(typeof(SharedData).GetMethod("get_CurrentProject"));
                                MethodReference callApiExtFunctionMethodRef =
                                    assembly.MainModule.Import(typeof(IWorkbenchProject).GetMethod("CallApiExtensionFunction"));

                                // Create local variables
                                VariableDefinition archAngelApiExtResult = new VariableDefinition(assembly.MainModule.Import(typeof(object)));
                                VariableDefinition parameters1           = new VariableDefinition(assembly.MainModule.Import(typeof(object[])));
                                VariableDefinition parameters2           = new VariableDefinition(assembly.MainModule.Import(typeof(object[])));

                                int localVarIndexOffset = method.Body.Variables.Count;
                                method.Body.Variables.Add(archAngelApiExtResult);
                                method.Body.Variables.Add(parameters1);
                                method.Body.Variables.Add(parameters2);

                                // Get the first instruction of the current method
                                Instruction firstInstruction = method.Body.Instructions[0];
                                // Arguments in a non-static method are one-based, because arg[0] is 'this'.
                                int argIndexOffset = method.IsStatic ? 0 : 1;

                                #region Initialize all "out" arguments to null
                                for (int argIndex = 0; argIndex < method.Parameters.Count; argIndex++)
                                {
                                    ParameterDefinition arg = method.Parameters[argIndex];
                                    int realArgIndex        = argIndex + argIndexOffset;

                                    if (arg.IsOut)
                                    {
                                        // Load the argument
                                        switch (realArgIndex)
                                        {
                                        case 0:
                                            method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_0));
                                            break;

                                        case 1:
                                            method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_1));
                                            break;

                                        case 2:
                                            method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_2));
                                            break;

                                        case 3:
                                            method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_3));
                                            break;

                                        default:
                                            method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_S, arg));
                                            break;
                                        }
                                        // Set it to null
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldnull));
                                        // Store the ref object
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stind_Ref));
                                    }
                                }
                                #endregion

                                #region Initialize object array

                                #region Size array to number of arguments
                                switch (method.Parameters.Count)
                                {
                                case 0:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_0));
                                    break;

                                case 1:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_1));
                                    break;

                                case 2:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_2));
                                    break;

                                case 3:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_3));
                                    break;

                                case 4:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_4));
                                    break;

                                case 5:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_5));
                                    break;

                                case 6:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_6));
                                    break;

                                case 7:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_7));
                                    break;

                                case 8:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_8));
                                    break;

                                default:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_S, (sbyte)method.Parameters.Count));
                                    //method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_S, method.Parameters[method.Parameters.Count - 1]));
                                    break;
                                }
                                #endregion

                                // Create a new array of objects, load the object array
                                method.Body.CilWorker.InsertBefore(firstInstruction,
                                                                   worker.Create(OpCodes.Newarr, assembly.MainModule.Import(typeof(object))));

                                // Create new object[] - must be declared as a local variable
                                // parameters2 is the third variable we added
                                switch (localVarIndexOffset + 2)
                                {
                                case 0:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_0));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_0));
                                    break;

                                case 1:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_1));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_1));
                                    break;

                                case 2:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_2));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_2));
                                    break;

                                case 3:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_3));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_3));
                                    break;

                                default:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_S, parameters2));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_S, parameters2));
                                    break;
                                }
                                #endregion

                                // Load all method arguments into the object array
                                for (int argIndex = 0; argIndex < method.Parameters.Count; argIndex++)
                                {
                                    int realArgIndex        = argIndex + argIndexOffset;
                                    ParameterDefinition arg = method.Parameters[argIndex];

                                    // Specify the array insertion index.
                                    switch (argIndex)
                                    {
                                    case 0:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_0));
                                        break;

                                    case 1:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_1));
                                        break;

                                    case 2:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_2));
                                        break;

                                    case 3:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_3));
                                        break;

                                    case 4:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_4));
                                        break;

                                    case 5:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_5));
                                        break;

                                    case 6:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_6));
                                        break;

                                    case 7:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_7));
                                        break;

                                    case 8:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_8));
                                        break;

                                    default:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldc_I4_S, (sbyte)argIndex));
                                        break;
                                    }
                                    // Load the argument
                                    switch (realArgIndex)
                                    {
                                    case 0:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_0));
                                        break;

                                    case 1:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_1));
                                        break;

                                    case 2:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_2));
                                        break;

                                    case 3:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_3));
                                        break;

                                    default:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldarg_S, arg));
                                        break;
                                    }
                                    if (arg.ParameterType.IsValueType)
                                    {
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Box, arg.ParameterType));
                                    }
                                    // If the parameter is out or ref
                                    if (arg.IsOut)
                                    {
                                        // Load as indirect reference
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldind_Ref));
                                    }
                                    // Replace the current array object with the new object
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stelem_Ref));

                                    // Assign the new object
                                    // parameters2 is the third variable we added
                                    switch (localVarIndexOffset + 2)
                                    {
                                    case 0:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_0));
                                        break;

                                    case 1:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_1));
                                        break;

                                    case 2:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_2));
                                        break;

                                    case 3:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_3));
                                        break;

                                    default:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_S, parameters2));
                                        break;
                                    }
                                }
                                // POP (parameters variable) OFF STACK AND STORE IN LOCAL VARIABLE AT INDEX 1 (object[] parameters)
                                // parameters1 is the third variable we added
                                switch (localVarIndexOffset + 1)
                                {
                                case 0:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_0));
                                    break;

                                case 1:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_1));
                                    break;

                                case 2:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_2));
                                    break;

                                case 3:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_3));
                                    break;

                                default:
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Stloc_S, parameters1));
                                    break;
                                }
                                // Call the ApiExtension function
                                //// NEW
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldsfld, projectInstance));
                                // END NEW
                                //method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Call, projectInstance));
                                method.Body.CilWorker.InsertBefore(firstInstruction,
                                                                   worker.Create(OpCodes.Ldstr, method.DeclaringType.FullName + "." + method.Name));
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloca_S, archAngelApiExtResult));
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloca_S, parameters1));
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Callvirt, callApiExtFunctionMethodRef));
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Brfalse_S, firstInstruction));

                                if (method.ReturnType.ReturnType.FullName != "System.Void")
                                {
                                    switch (localVarIndexOffset)
                                    {
                                    case 0:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_0));
                                        break;

                                    case 1:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_1));
                                        break;

                                    case 2:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_2));
                                        break;

                                    case 3:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_3));
                                        break;

                                    default:
                                        method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ldloc_S, archAngelApiExtResult));
                                        break;
                                    }
                                    //method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Castclass, method.ReturnType.ReturnType));
                                    method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Unbox_Any, method.ReturnType.ReturnType));
                                }
                                method.Body.CilWorker.InsertBefore(firstInstruction, worker.Create(OpCodes.Ret));
                                method.Body.InitLocals = true;
                            }
                            //}// Added
                        }
                        //Import the modifying type into the AssemblyDefinition of //"MyLibrary"
                        assembly.MainModule.Import(type);
                    }
                }
                //Save the modified "MyLibrary" assembly
                string newFilename = GetNewFilename(dllFile);
                AssemblyFactory.SaveAssembly(assembly, newFilename);

                // Copy the existing pdb sideways
                string sourceDirectory   = Path.GetDirectoryName(dllFile);
                string targetDirectory   = Path.GetDirectoryName(newFilename);
                string sourcePdbFilePath = Path.Combine(sourceDirectory, Path.GetFileNameWithoutExtension(dllFile) + ".pdb");
                string tempPdbFilePath   = Path.Combine(sourceDirectory, Path.GetFileNameWithoutExtension(dllFile) + "_temp.pdb");
                string targetPdbFilePath = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(dllFile) + "_EXT.pdb");
                File.Copy(sourcePdbFilePath, tempPdbFilePath);

                assembly.MainModule.SaveSymbols();
                if (File.Exists(targetPdbFilePath))
                {
                    File.Delete(targetPdbFilePath);
                }
                File.Move(sourcePdbFilePath, targetPdbFilePath);
                File.Move(tempPdbFilePath, sourcePdbFilePath);

                WriteLineStatus("Finished");
                return(true);
            }
            catch (Exception ex)
            {
                WriteLineStatus("Error: " + ex.Message);
                return(false);
            }
        }
示例#28
0
        /// <summary>
        /// Replaces the <paramref name="oldInstruction"/> with a set of new instructions.
        /// </summary>
        /// <param name="oldInstruction">The instruction currently being evaluated.</param>
        /// <param name="hostMethod">The method that contains the target instruction.</param>
        /// <param name="IL">The CilWorker that will be used to emit the method body instructions.</param>
        protected override void Replace(Instruction oldInstruction, MethodDefinition hostMethod, CilWorker IL)
        {
            var           targetField = (FieldReference)oldInstruction.Operand;
            TypeReference fieldType   = targetField.FieldType;
            bool          isSetter    = oldInstruction.OpCode == OpCodes.Stsfld || oldInstruction.OpCode == OpCodes.Stfld;

            if (isSetter)
            {
                hostMethod.Body.InitLocals = true;
                // Save the setter argument and box it if necessary
                if (fieldType.IsValueType || fieldType is GenericParameter)
                {
                    IL.Emit(OpCodes.Box, fieldType);
                }

                IL.Emit(OpCodes.Stloc, _currentArgument);
            }

            // There's no need to push the current object instance
            // since the this pointer is pushed prior to the field call
            if (hostMethod.IsStatic)
            {
                IL.Emit((OpCodes.Ldnull));
            }

            // Push the current method
            ModuleDefinition module = hostMethod.DeclaringType.Module;

            // Push the current method onto the stack
            IL.PushMethod(hostMethod, module);

            // Push the current field onto the stack
            IL.PushField(targetField, module);

            // Push the host type onto the stack
            IL.PushType(hostMethod.DeclaringType, module);

            // Create the IFieldInterceptionContext instance
            IL.Emit(OpCodes.Newobj, _fieldContextCtor);
            IL.Emit(OpCodes.Stloc, _fieldContext);

            Instruction skipInterception = IL.Create(OpCodes.Nop);

            // Obtain an interceptor instance
            if (hostMethod.IsStatic)
            {
                IL.Emit(OpCodes.Ldloc, _fieldContext);
                IL.Emit(OpCodes.Call, _getInterceptor);
            }
            else
            {
                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, _fieldInterceptionHostType);
                IL.Emit(OpCodes.Brfalse, skipInterception);

                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, _fieldInterceptionHostType);
                IL.Emit(OpCodes.Callvirt, _getInstanceInterceptor);
            }

            // The field interceptor cannot be null
            IL.Emit(OpCodes.Stloc, _fieldInterceptor);
            IL.Emit(OpCodes.Ldloc, _fieldInterceptor);
            IL.Emit(OpCodes.Brfalse, skipInterception);

            // if (FieldInterceptor.CanIntercept(context) {
            IL.Emit(OpCodes.Ldloc, _fieldInterceptor);
            IL.Emit(OpCodes.Ldloc, _fieldContext);
            IL.Emit(OpCodes.Callvirt, _canIntercept);
            IL.Emit(OpCodes.Brfalse, skipInterception);

            bool isGetter = oldInstruction.OpCode == OpCodes.Ldsfld || oldInstruction.OpCode == OpCodes.Ldfld;

            Instruction endLabel = IL.Create(OpCodes.Nop);

            //Call the interceptor instead of the getter or setter
            if (isGetter)
            {
                IL.Emit(OpCodes.Ldloc, _fieldInterceptor);
                IL.Emit(OpCodes.Ldloc, _fieldContext);
                IL.Emit(OpCodes.Callvirt, _getValue);
                IL.Emit(OpCodes.Unbox_Any, fieldType);
            }

            if (isSetter)
            {
                // Push the 'this' pointer for instance field setters
                if (!hostMethod.IsStatic)
                {
                    IL.Emit(OpCodes.Ldarg_0);
                }

                IL.Emit(OpCodes.Ldloc, _fieldInterceptor);
                IL.Emit(OpCodes.Ldloc, _fieldContext);
                IL.Emit(OpCodes.Ldloc, _currentArgument);

                // Unbox the setter value
                IL.Emit(OpCodes.Unbox_Any, fieldType);

                IL.Emit(OpCodes.Callvirt, _setValue);

                // Set the actual field value
                IL.Emit(OpCodes.Unbox_Any, fieldType);
                IL.Emit(oldInstruction.OpCode, targetField);
            }

            IL.Emit(OpCodes.Br, endLabel);

            // }
            IL.Append(skipInterception);

            // else {

            // Load the original field
            if (!hostMethod.IsStatic)
            {
                IL.Emit(OpCodes.Ldarg_0);
            }


            if (isSetter)
            {
                IL.Emit(OpCodes.Ldloc, _currentArgument);

                // Unbox the setter value
                IL.Emit(OpCodes.Unbox_Any, fieldType);
            }

            IL.Emit(oldInstruction.OpCode, targetField);

            // }

            IL.Append(endLabel);
        }
示例#29
0
        private void Replace(CilWorker IL, Instruction oldInstruction, MethodReference targetMethod, MethodDefinition hostMethod, Instruction endLabel, Instruction callOriginalMethod)
        {
            var returnType = targetMethod.ReturnType.ReturnType;
            var module     = hostMethod.DeclaringType.Module;

            if (!hostMethod.IsStatic)
            {
                GetInstanceProvider(IL);
            }


            var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            // If all else fails, use the static method replacement provider
            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, _getStaticProvider);
            IL.Emit(OpCodes.Stloc, _staticProvider);

            var restoreArgumentStack = IL.Create(OpCodes.Nop);

            var callReplacement   = IL.Create(OpCodes.Nop);
            var useStaticProvider = IL.Create(OpCodes.Nop);


            #region Use the instance method replacement provider

            IL.Emit(OpCodes.Ldloc, _instanceProvider);
            IL.Emit(OpCodes.Brfalse, useStaticProvider);


            EmitCanReplace(IL, hostMethod, _instanceProvider);
            IL.Emit(OpCodes.Ldloc, _canReplaceFlag);
            IL.Emit(OpCodes.Brfalse, useStaticProvider);

            EmitGetMethodReplacement(IL, hostMethod, _instanceProvider);


            IL.Emit(OpCodes.Ldloc, _replacement);
            IL.Emit(OpCodes.Brtrue, callReplacement);

            #endregion

            IL.Append(useStaticProvider);
            // if (!MethodReplacementProvider.CanReplace(info))
            //      CallOriginalMethod();
            EmitCanReplace(IL, hostMethod, _staticProvider);

            IL.Emit(OpCodes.Ldloc, _canReplaceFlag);
            IL.Emit(OpCodes.Brfalse, restoreArgumentStack);

            EmitGetMethodReplacement(IL, hostMethod, _staticProvider);

            IL.Append(callReplacement);

            // if (replacement == null)
            //      CallOriginalMethod();
            IL.Emit(OpCodes.Ldloc, _replacement);
            IL.Emit(OpCodes.Brfalse, restoreArgumentStack);

            EmitInterceptorCall(IL);

            IL.PackageReturnValue(module, returnType);

            IL.Emit(OpCodes.Br, endLabel);

            IL.Append(restoreArgumentStack);

            // Reconstruct the method arguments if the interceptor
            // cannot be found

            // Push the target instance
            ReconstructMethodArguments(IL, targetMethod);

            // Mark the CallOriginalMethod instruction label
            IL.Append(callOriginalMethod);

            // Call the original method
            IL.Append(oldInstruction);
        }
示例#30
0
        public void ObfuscateFlow(TypeDefinition type, MethodDefinition method)
        {
            if (method.IsConstructor)
            {
                return;
            }

            if (method.IsRuntime)
            {
                return;
            }

            if (method.IsRuntimeSpecialName)
            {
                return;
            }

            if (method.IsSpecialName)
            {
                return;
            }

            if (method.IsVirtual)
            {
                return;
            }

            if (method.IsAbstract)
            {
                return;
            }

            if (method.Overrides.Count > 0)
            {
                return;
            }

            if (method.Name.StartsWith("<"))
            {
                return;
            }

            if (method.Body == null)
            {
                return;
            }

            if (method.Name.Contains("Dispose"))
            {
                return;
            }

            if (method.Name.Contains("ctor"))
            {
                return;
            }

            int count = method.Body.Instructions.Count - 1;

            if (count <= 1)
            {
                return;
            }

            CilWorker worker = method.Body.CilWorker;

            //Instruction insertSentencess = worker.Create(OpCodes.Testy);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[0], insertSentencess);

            //Instruction insertSentencesss = worker.Create(OpCodes.Br_S, method.Body.Instructions[2]);
            //method.Body.CilWorker.InsertBefore(method.Body.Instructions[1], insertSentencesss);
            //Instruction redirect22 = worker.Create(OpCodes.Ret);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[method.Body.Instructions.Count - 1], redirect22);
            List <Instruction> collection = new List <Instruction>();

            //string collection2 = String.Empty;

            foreach (Instruction i in method.Body.Instructions)
            {
                collection.Add(i);
            }

            foreach (Instruction i in collection)
            {
                method.Body.Instructions.Remove(i);
            }

            method.Body.CilWorker.Append(collection[0]);
            for (int i = 1; i < collection.Count - 1; i++)
            {
                int position = r.Next(0, method.Body.Instructions.Count - 1);
                method.Body.CilWorker.InsertAfter(method.Body.Instructions[position], collection[i]);
            }

            int         lastpos  = 0;
            Instruction redirect = worker.Create(OpCodes.Br_S, method.Body.Instructions[method.Body.Instructions.IndexOf(collection[0]) + 1]);

            method.Body.CilWorker.InsertBefore(method.Body.Instructions[0], redirect);
            lastpos = method.Body.Instructions.IndexOf(collection[0]);

            for (int i = 1; i < collection.Count - 1; i++)
            {
                //try
                //{
                int track = 0;
                if (lastpos < method.Body.Instructions.IndexOf(collection[i]))
                {
                    track += 1;
                }
                //Instruction blank = worker.Create(OpCodes.Nop);
                //method.Body.CilWorker.InsertBefore(method.Body.Instructions[lastpos + 1], blank);
                Instruction redirect2 = worker.Create(OpCodes.Br_S, method.Body.Instructions[method.Body.Instructions.IndexOf(collection[i]) + track]);
                //method.Body.CilWorker.Remove(method.Body.Instructions[lastpos + 1]);
                method.Body.CilWorker.InsertBefore(method.Body.Instructions[lastpos + 1], redirect2);
                lastpos = method.Body.Instructions.IndexOf(collection[i]);
                //}
                //catch
                //{
                //    MessageBox.Show("Error");
                //}
            }
            //Instruction redirect2 = worker.Create(OpCodes.Br_S, method.Body.Instructions[method.Body.Instructions.IndexOf(i)]);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[lastpos], redirect2);
            //Instruction in1 = worker.Create(OpCodes.Br_S, method.Body.Instructions[2]);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in1);

            //Instruction in2 = worker.Create(OpCodes.Ldstr, "ajsndjkasndjknaskjdn");
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in2);

            //Instruction in3 = worker.Create(OpCodes.Br_S, method.Body.Instructions[3]);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in3);

            //Instruction in4 = worker.Create(OpCodes.Ldstr, "ajsndjkasndjknaskjdn");
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in4);

            //Instruction in5 = worker.Create(OpCodes.Br_S, method.Body.Instructions[3]);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in5);

            //Instruction in6 = worker.Create(OpCodes.Ldstr, "ajsndjkasndjknaskjdn");
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in6);

            //Instruction in7 = worker.Create(OpCodes.Br_S, method.Body.Instructions[5]);
            //method.Body.CilWorker.InsertAfter(method.Body.Instructions[1], in7);
        }