【转】托管函数的挂钩(完美版)

原文:http://blog.csdn.net/cstod/article/details/6262506

CLR Injection: Runtime Method Replacer

http://www.codeproject.com/Articles/37549/CLR-Injection-Runtime-Method-Replacer

CLR Injection: Modify IL Code during Run-time

http://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time

我之前发过一篇叫“托管函数的挂钩”的文章,实现了对MarshalByRefObject继承树下的实例函数的挂钩。 

最近,在CodeProject上看到一个关于托管函数挂钩的文章,发现作者的方法很好用,但是正好不能用于MarshalByRefObject继承树下的实例函数(作者本人并没有发现这个问题),于是两种方法正好互补。

你也许要用,我为什么要强调MarshalByRefObject继承树呢?这是因为非常多的类都存在于该类的继承树下,比如很多人习惯把代码写在自己的窗体类中,而Form就在MarshalByRefObject树下,从我的实际经验来看,它比非MarshalByRefObject继承树的范围更广。 

我对两种代码进行了封装,使用时只需调用ManagedReplacer.Replace方法即可。 

说明:托管函数在第一次被调用时会被JIT成本地代码,之后会复用被JIT的本地代码,所以一定要在函数被JIT之前进行挂钩,否则将无效。

参考:http://www.sysnet.pe.kr/2/0/942

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using RuntimeHelpers = System.Runtime.CompilerServices.RuntimeHelpers;
using System.Runtime.InteropServices;
using System.Reflection.Emit;

namespace System
{
    public static class MethodUtil
    {
        /// <summary>
        /// 将源方法替换为新方法
        /// </summary> 
        public static void Replace(this MethodBase source, MethodBase dest)
        {
            ReplaceMethod(source, dest, false);
        }

        public static void ReplaceMethod(MethodBase source, MethodBase dest, bool isDynamicSource)
        {
            if (!MethodSignaturesEqual(source, dest))
            {
                throw new ArgumentException("The method signatures are not the same.", "source");
            }
            ReplaceMethod(GetMethodAddress(source), dest, isDynamicSource);
        }

        public static void ReplaceMethod(IntPtr srcAdr, MethodBase dest, bool isDynamicSource)
        {
            IntPtr destAdr = GetMethodAddress(dest);
            unsafe
            {
                if (IntPtr.Size == 8)
                {
                    ulong* d = (ulong*)destAdr.ToPointer();

                    if (isDynamicSource == true)
                    {
                        *d = (ulong)srcAdr.ToInt64();
                    }
                    else
                    {
                        *d = *((ulong*)srcAdr.ToPointer());
                    }
                }
                else
                {
                    uint* d = (uint*)destAdr.ToPointer();

                    if (isDynamicSource == true)
                    {
                        *d = (uint)srcAdr.ToInt32();
                    }
                    else
                    {
                        *d = *((uint*)srcAdr.ToPointer());
                    }
                }
            }
        }

        public static IntPtr GetMethodAddress(MethodBase method)
        {
            if ((method is DynamicMethod))
            {
                return GetDynamicMethodAddress(method);
            }

            // Prepare the method so it gets jited
            RuntimeHelpers.PrepareMethod(method.MethodHandle);

            // If 3.5 sp1 or greater than we have a different layout in memory.
            if (IsNet20Sp2OrGreater())
            {
                return GetMethodAddress20SP2(method);
            }


            unsafe
            {
                // Skip these
                const int skip = 10;

                // Read the method index.
                UInt64* location = (UInt64*)(method.MethodHandle.Value.ToPointer());
                int index = (int)(((*location) >> 32) & 0xFF);

                if (IntPtr.Size == 8)
                {
                    // Get the method table
                    ulong* classStart = (ulong*)method.DeclaringType.TypeHandle.Value.ToPointer();
                    ulong* address = classStart + index + skip;
                    return new IntPtr(address);
                }
                else
                {
                    // Get the method table
                    uint* classStart = (uint*)method.DeclaringType.TypeHandle.Value.ToPointer();
                    uint* address = classStart + index + skip;
                    return new IntPtr(address);
                }
            }
        }

        private static IntPtr GetDynamicMethodAddress(MethodBase method)
        {
            unsafe
            {
                RuntimeMethodHandle handle = GetDynamicMethodRuntimeHandle(method);
                byte* ptr = (byte*)handle.Value.ToPointer();

                if (IsNet20Sp2OrGreater())
                {
                    RuntimeHelpers.PrepareMethod(handle);
                    return handle.GetFunctionPointer();

                    //if (IntPtr.Size == 8)
                    //{
                    //    ulong* address = (ulong*)ptr;
                    //    address = (ulong*)*(address + 5);
                    //    return new IntPtr(address + 12);
                    //}
                    //else
                    //{
                    //    uint* address = (uint*)ptr;
                    //    address = (uint*)*(address + 5);
                    //    return new IntPtr(address + 12);
                    //}

                }
                else
                {


                    if (IntPtr.Size == 8)
                    {
                        ulong* address = (ulong*)ptr;
                        address += 6;
                        return new IntPtr(address);
                    }
                    else
                    {
                        uint* address = (uint*)ptr;
                        address += 6;
                        return new IntPtr(address);
                    }
                }

            }
        }

        private static RuntimeMethodHandle GetDynamicMethodRuntimeHandle(MethodBase method)
        {
            RuntimeMethodHandle handle;

            if (Environment.Version.Major == 4)
            {
                MethodInfo getMethodDescriptorInfo = typeof(DynamicMethod).GetMethod("GetMethodDescriptor",
                        BindingFlags.NonPublic | BindingFlags.Instance);
                handle = (RuntimeMethodHandle)getMethodDescriptorInfo.Invoke(method, null);
            }
            else
            {
                FieldInfo fieldInfo = typeof(DynamicMethod).GetField("m_method", BindingFlags.NonPublic | BindingFlags.Instance);
                handle = ((RuntimeMethodHandle)fieldInfo.GetValue(method));
            }

            return handle;
        }

        private static IntPtr GetMethodAddress20SP2(MethodBase method)
        {
            unsafe
            {
                return new IntPtr(((int*)method.MethodHandle.Value.ToPointer() + 2));
            }
        }
        private static bool MethodSignaturesEqual(MethodBase x, MethodBase y)
        {
            if (x.CallingConvention != y.CallingConvention)
            {
                return false;
            }
            Type returnX = GetMethodReturnType(x), returnY = GetMethodReturnType(y);
            if (returnX != returnY)
            {
                return false;
            }
            ParameterInfo[] xParams = x.GetParameters(), yParams = y.GetParameters();
            if (xParams.Length != yParams.Length)
            {
                return false;
            }
            for (int i = 0; i < xParams.Length; i++)
            {
                if (xParams[i].ParameterType != yParams[i].ParameterType)
                {
                    return false;
                }
            }
            return true;
        }
        private static Type GetMethodReturnType(MethodBase method)
        {
            MethodInfo methodInfo = method as MethodInfo;
            if (methodInfo == null)
            {
                // Constructor info.
                throw new ArgumentException("Unsupported MethodBase : " + method.GetType().Name, "method");
            }
            return methodInfo.ReturnType;
        }
        private static bool IsNet20Sp2OrGreater()
        {
            if (Environment.Version.Major == 4)
            {
                return true;
            }

            return Environment.Version.Major == NetFxVersions.Net20SP2.Major &&
                Environment.Version.MinorRevision >= NetFxVersions.Net20SP2.MinorRevision;
        }

        #region NetFxVersions
        public static class NetFxVersions
        {
            public static readonly Version Net35 = new Version(3, 5, 21022, 8);
            public static readonly Version Net35SP1 = new Version(3, 5, 30729, 1);
            public static readonly Version Net30 = new Version(3, 0, 4506, 30);
            public static readonly Version Net30SP1 = new Version(3, 0, 4506, 648);
            public static readonly Version Net30SP2 = new Version(3, 0, 4506, 2152);
            public static readonly Version Net20 = new Version(2, 0, 50727, 42);
            public static readonly Version Net20SP1 = new Version(2, 0, 50727, 1433);
            public static readonly Version Net20SP2 = new Version(2, 0, 50727, 3053);
        }
        #endregion
    }
}

  

devexpress patch for vs2015 packge : devexpress.vspackage.vs2015.zip

IntelliJ IDEA 14 sn

(1)key:IDEA

value:61156-YRN2M-5MNCN-NZ8D2-7B4EW-U12L4 

(2)key:huangwei

value:97493-G3A41-0SO24-W57LI-Y2UGI-JGTU2 

(3)key:hkl520

value:34423-VZYXD-FQXZ7-O6I7U-J3ZK8-R7V62 

(4)key:Intelligent

value:40957-EG6O9-2915L-CF1RP-57IQJ-Y6VZ3 

(5)key:tommy

value:49164-YPNVL-OXUZL-XIWM4-Z9OHC-LF053 

(6)key:whuanghk

value:98220-IN97R-TV1ID-2JAPO-OXZEO-LAM70 

(7)key:itey

value:91758-T1CLA-C64F3-T7X5R-A7YDO-CRSN1

原文地址:https://www.cnblogs.com/zhahost/p/3660139.html