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