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


    原文: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

  • 相关阅读:
    加油 ^_^
    ES6 小记
    Angular2 初学小记
    Round 4
    react中iconfont字体图标不显示问题
    react 实现组件嵌套以及子组件与父组件之间的通信
    wamp&花生壳 在本地搭建自己的网站
    深入浅出CSS(二):关于雪碧图、background-position与steps函数的三角恋情
    深入浅出CSS(一):line-height与vertical-align的性质
    十进制字符编号
  • 原文地址:https://www.cnblogs.com/zhahost/p/3660139.html
Copyright © 2020-2023  润新知