Пример #1
0
        public bool PatchMethod2(MethodDefinition method, Injection injection)
        {
            bool success = true;

            if (method.IsConstructor ||
                method.IsAbstract ||
                method.IsSetter ||
                (method.IsSpecialName && !method.IsGetter) || // to allow getter methods
                method.IsGenericInstance ||
                method.IsManaged == false ||
                method.Body == null)
            {
                SendMessage("Ignored method: " + method.Name, MessageType.Warning);
                return(true);
            }

            try
            {
                var constructor = injection.Constructor;
                constructor.Resolve();

                bool isInjected = method.Body.Variables.Count(x => x.VariableType.Scope == injection.TypeReference.Scope &&
                                                              x.VariableType.FullName == injection.TypeReference.FullName &&
                                                              x.VariableType.Namespace == injection.TypeReference.Namespace) > 0;


                MethodInjector editor = new MethodInjector(method);

                VariableDefinition vInject      = editor.AddVariable(injection.TypeReference);
                VariableDefinition vInjection   = editor.AddVariable(_cinjection);
                VariableDefinition vObjectArray = editor.AddVariable(Assembly.ImportType <object[]>());

                Instruction firstExistingInstruction = method.Body.Instructions[0];

                // create constructor of Injector
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, constructor));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInject));

                #region OnInvoke without Param
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke));
                #endregion


                method.Resolve();

                SendMessage("Injected method " + method, MessageType.Output);
            }
            catch (Exception ex)
            {
                SendMessage(ex.Message, MessageType.Error);
                return(false);
            }

            return(true);
        }
Пример #2
0
        public bool PatchMethod(MethodDefinition method, Injection injection)
        {
            bool success = true;

            if (method.IsConstructor ||
                method.IsAbstract ||
                method.IsSetter ||
                (method.IsSpecialName && !method.IsGetter) || // to allow getter methods
                method.IsGenericInstance ||
                method.IsManaged == false ||
                method.Body == null)
            {
                SendMessage("Ignored method: " + method.Name, MessageType.Warning);
                return(true);
            }

            try
            {
                var constructor = injection.Constructor;
                constructor.Resolve();

                bool isInjected = method.Body.Variables.Count(x => x.VariableType.Scope == injection.TypeReference.Scope &&
                                                              x.VariableType.FullName == injection.TypeReference.FullName &&
                                                              x.VariableType.Namespace == injection.TypeReference.Namespace) > 0;

                if (isInjected) // already injected
                {
                    SendMessage("Already injected method " + method.Name + " with " + injection.TypeReference.Name, MessageType.Warning);
                    return(true);
                }

                MethodInjector editor = new MethodInjector(method);

                VariableDefinition vInject      = editor.AddVariable(injection.TypeReference);
                VariableDefinition vInjection   = editor.AddVariable(_cinjection);
                VariableDefinition vObjectArray = editor.AddVariable(Assembly.ImportType <object[]>());

                Instruction firstExistingInstruction = method.Body.Instructions[0];

                // create constructor of Injector
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, constructor));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInject));

                #region OnInvoke without Param
                //editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject));
                //editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke));
                #endregion

                #region OnInvoke with Param
                // create constructor of CInjection
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, _cinjectionCtor));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInjection));

                // create parameter of GetCurrentMethod
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Call, _methodGetCurrentMethod));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetMethod));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop));

                // create parameter of GetExecutingAssembly
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Call, _methodGetExecutingAssembly));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetExecutingAssembly));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop));

                if (method.Parameters.Count > 0)
                {
                    // create array of object (arguments)
                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection));
                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, method.Parameters.Count));
                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newarr, Assembly.ImportType <object>()));
                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vObjectArray));

                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        bool processAsNormal = true;

                        if (method.Parameters[i].ParameterType.IsByReference)
                        {
                            /* Sample Instruction set:
                             * L_002a: ldloc.2
                             * L_002b: ldc.i4.0
                             * L_002c: ldarg.1
                             * L_002d: ldind.ref
                             * L_002e: stelem.ref
                             * */

                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, i));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldarg, method.Parameters[i]));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldind_Ref));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stelem_Ref));

                            processAsNormal = false;
                        }
                        //else if (method.Parameters[i].ParameterType.IsArray)
                        //{

                        //}
                        //else if (method.Parameters[i].ParameterType.IsDefinition) // delegate needs no seperate handling
                        //{

                        //}
                        else if (method.Parameters[i].ParameterType.IsFunctionPointer)
                        {
                        }
                        //else if (method.Parameters[i].ParameterType.IsOptionalModifier)
                        //{

                        //}
                        else if (method.Parameters[i].ParameterType.IsPointer)
                        {
                        }
                        else
                        {
                            processAsNormal = true;
                        }

                        if (processAsNormal)
                        {
                            /* Sample Instruction set: for simple PARAMETER
                             * L_0036: ldloc.s objArray
                             * L_0038: ldc.i4 0
                             * L_003d: ldarg array
                             * L_0041: box Int32    <-------------- anything can be here
                             * L_0046: stelem.ref
                             * */

                            /* Sample Instruction set: for ARRAY
                             * L_0036: ldloc.s objArray
                             * L_0038: ldc.i4 0
                             * L_003d: ldarg array
                             * L_0041: box string[]
                             * L_0046: stelem.ref
                             * */

                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, i));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldarg, method.Parameters[i]));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Box, method.Parameters[i].ParameterType));
                            editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stelem_Ref));
                        }
                    }

                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray));
                    editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetArguments));
                }

                // call OnInvoke with appropriate parameters
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke));
                editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop));

                #endregion

                #region OnComplete
                Instruction[] exitInstructions = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToArray();

                for (int i = 0; i < exitInstructions.Length; i++)
                {
                    var previous = exitInstructions[i].Previous; // most likely previous statement will be NOP, LDLOC.0 (pop, or load from stack)
                    editor.InsertBefore(previous, editor.Create(OpCodes.Ldloc_S, vInject));
                    editor.InsertBefore(previous, editor.Create(OpCodes.Callvirt, injection.OnComplete));

                    Debug.WriteLine(method.Name + " " + method.ReturnType.Name + " " + previous.OpCode);
                }
                #endregion

                method.Resolve();

                SendMessage("Injected method " + method, MessageType.Output);
            }
            catch (Exception ex)
            {
                SendMessage(ex.Message, MessageType.Error);
                return(false);
            }

            return(true);
        }