码迷,mamicode.com
首页 > Windows程序 > 详细

C# 运行时替换方法(需要unsafe编译)

时间:2017-08-11 14:45:52      阅读:1731      评论:0      收藏:0      [点我收藏+]

标签:console   debug   help   pre   ...   amp   adk   sharp   type   

第一种方法的基本原理是将函数指针替换成想要的方法(https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method);还有一种方式是用 methodInfo.GetMethodBody().GetILAsByteArray() 获得IL字节码,然后(利用C++?)编写注入代码对其字节码重新写入(https://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time)。

这两种方法都需要先调用 RuntimeHelpers.PrepareMethod (https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.preparemethod(v=vs.110).aspx)来准备方法。

第一种方法实现简便,下面是演示代码:

  1 /* https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method
  2    For .NET 4 and above
  3 
  4 "C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe" /unsafe+ /out:replacemethod.exe replacemethod.cs && start "replacemethod.exe" replacemethod.exe
  5 Foo1 is called.
  6 Foo2 is called.
  7 Foo2 returns.
  8 Foo3 is called. I‘m foo3‘s argument.
  9 Foo4 is called.
 10 --------------------
 11 Version x64 Relaese
 12 Version x64 Relaese
 13 Version x64 Relaese
 14 Version x64 Relaese
 15 --------------------
 16 Bar1 is called.
 17 Bar2 is called.
 18 Bar2 returns.
 19 Bar3 is called. I‘m foo3‘s argument.
 20 Bar4 is called.
 21 
 22 Press any key to EXIT...
 23 */
 24 
 25 using System;
 26 using System.Reflection;
 27 using System.Runtime.CompilerServices;
 28 
 29 class Program {
 30     public static void Main(params string[] args){
 31         var sp = new string(-, 20);
 32 
 33         Target targetInstance = new Target();
 34 
 35         targetInstance.Test();
 36         Console.WriteLine(sp);
 37 
 38         Injection.Install(1);
 39         Injection.Install(2);
 40         Injection.Install(3);
 41         Injection.Install(4);
 42         
 43         Console.WriteLine(sp);
 44         targetInstance.Test();
 45 
 46         Console.Write("\nPress any key to EXIT...");
 47         Console.ReadKey(true);
 48     }
 49 }
 50 
 51 
 52 public class Injection {
 53     public static void Install(int funcNum) {
 54         MethodInfo methodToReplace = typeof(Target).GetMethod("Foo"+funcNum, BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public);
 55         MethodInfo methodToInject = typeof(Injection).GetMethod("Bar"+funcNum, BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public);
 56         RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
 57         RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
 58 
 59         unsafe {
 60             if (IntPtr.Size == 4) 
 61             {
 62                 int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
 63                 int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
 64 #if DEBUG
 65                 Console.WriteLine("Version x86 Debug");
 66                 byte* injInst = (byte*)*inj;
 67                 byte* tarInst = (byte*)*tar;
 68                 int* injSrc = (int*)(injInst + 1);
 69                 int* tarSrc = (int*)(tarInst + 1);
 70                 *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
 71 #else
 72                 Console.WriteLine("Version x86 Relaese");
 73                 *tar = *inj;
 74 #endif
 75             }
 76             else 
 77             {
 78                 long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
 79                 long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
 80 #if DEBUG
 81                 Console.WriteLine("Version x64 Debug");
 82                 byte* injInst = (byte*)*inj;
 83                 byte* tarInst = (byte*)*tar;
 84                 int* injSrc = (int*)(injInst + 1);
 85                 int* tarSrc = (int*)(tarInst + 1);
 86                 *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
 87 #else
 88                 Console.WriteLine("Version x64 Relaese");
 89                 *tar = *inj;
 90 #endif
 91             }
 92         }
 93     }
 94 
 95     private void Bar1() {
 96         Console.WriteLine("Bar1 is called.");
 97     }
 98     private string Bar2() {
 99         Console.WriteLine("Bar2 is called.");
100         return "Bar2 returns.";
101     }
102     private void Bar3(string arg) {
103         Console.WriteLine("Bar3 is called. " + arg);
104     }
105     private void Bar4() {
106         Console.WriteLine("Bar4 is called.");
107     }
108 }
109 
110 
111 public class Target {
112     public void Test() {
113         Foo1();
114         Console.WriteLine(Foo2());
115         Foo3("I‘m foo3‘s argument.");
116         Foo4();
117     }
118 
119     private void Foo1() {
120         Console.WriteLine("Foo1 is called.");
121     }
122     public string Foo2() {
123         Console.WriteLine("Foo2 is called.");
124         return "Foo2 returns.";
125     }
126     private void Foo3(string arg) {
127         Console.WriteLine("Foo3 is called. "+arg);
128     }
129     private void Foo4() {
130         Console.WriteLine("Foo4 is called.");
131     }
132 }

 

第二种方法请查阅连接

C# 运行时替换方法(需要unsafe编译)

标签:console   debug   help   pre   ...   amp   adk   sharp   type   

原文地址:http://www.cnblogs.com/Bob-wei/p/7345574.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!