예제 #1
0
        /// <summary>
        /// Hook a field by injecting a static "setter" method.
        /// If target field is a static field, your setter should accept a value that is originally used to write the field.
        /// If target field is not a static field, your setter should accept a object having the field followed by a value.
        /// Your setter method should not have any return value.
        /// </summary>
        /// <param name="target field"></param>
        /// <param name="hook method">your "setter"</param>
        /// <param name="resolver">This is used to find every IL instruction that writes the field.</param>
        /// <param name="hookName"></param>
        static public void HookFieldWrite(FieldDefinition target, MethodDefinition hookMethod, ReferenceResolver resolver = null, string hookName = null)
        {
            if (hookName == null)
            {
                hookName = target.Name + "__hookwrite__" + hookMethod.Name;
            }

            if (resolver == null)
            {
                resolver = new ReferenceResolver();
                resolver.ScanAssembly(target.DeclaringType.Module.Assembly);
            }

            var injectedMethod = InjectMethod(target.DeclaringType, hookMethod, hookName);

            var references = resolver.FindAllReferences(target);

            foreach (var reference in references)
            {
                if (reference.instruction.OpCode == OpCodes.Stfld || reference.instruction.OpCode == OpCodes.Stsfld)
                {
                    reference.instruction.OpCode  = OpCodes.Call;
                    reference.instruction.Operand = injectedMethod;
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Replace target method with your hook method.
        /// To call the original method, just call hook method from the hook method.
        /// </summary>
        /// <param name="target method"></param>
        /// <param name="hook method"></param>
        /// <param name="resolver">This is used to find all instructions that call the target method.</param>
        /// <param name="hook prefix">This will be used as the prefix of the original target method.</param>
        static public void HookMethod(MethodDefinition targetMethod, MethodDefinition hookMethod, ReferenceResolver resolver = null, string hookPrefix = "__hooked__")
        {
            if (resolver == null)
            {
                resolver = new ReferenceResolver();
                resolver.ScanAssembly(targetMethod.DeclaringType.Module.Assembly);
            }

            var injectedMethod = InjectMethod(targetMethod.DeclaringType, hookMethod);

            injectedMethod.Attributes = targetMethod.Attributes;
            if (!targetMethod.IsStatic && hookMethod.IsStatic)
            {
                // first argument is keyword "this"
                injectedMethod.HasThis = true;
                injectedMethod.Parameters.RemoveAt(0); // should not appear here
            }
            // rename original method
            injectedMethod.Name = targetMethod.Name;
            targetMethod.Name   = hookPrefix + targetMethod.Name;
            // replace the original method with the new one
            resolver.ReplaceAllReferences(targetMethod, injectedMethod);
            // process self-calls
            for (int i = 0; i < injectedMethod.Body.Instructions.Count; ++i)
            {
                var ins = injectedMethod.Body.Instructions[i];
                if (ins.OpCode == OpCodes.Call || ins.OpCode == OpCodes.Callvirt)
                {
                    if ((ins.Operand as MethodReference).FullName == hookMethod.FullName)
                    {
                        ins.Operand = targetMethod;
                    }
                }
            }
        }