第一种方法的基本原理是将函数指针替换成想要的方法(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 }
第二种方法请查阅连接。
标签:console debug help pre ... amp adk sharp type
原文地址:http://www.cnblogs.com/Bob-wei/p/7345574.html
本文介绍了一种在C#中动态替换方法实现的技术,通过函数指针替换或修改IL字节码实现。提供了示例代码,展示了如何使用RuntimeHelpers.PrepareMethod准备方法,并通过unsafe代码块实现方法替换。
&spm=1001.2101.3001.5002&articleId=102455400&d=1&t=3&u=5ad118b3b95c4c07ac54cec41934b516)
7128

被折叠的 条评论
为什么被折叠?



