将代码动态附加到方法 .Net-Core
Dynamically Append Code to a method .Net-Core
我对在 .Net-Core 中动态附加代码很感兴趣。 注意:这仅用于教育目的。
目前我有一个 class 交换方法:
public static void Inject<TTarget, TInject>(string targetFuncName, string injectFuncName)
{
MethodInfo methodToReplace = typeof(TTarget).GetMethod(targetFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
MethodInfo methodToInject = typeof(TInject).GetMethod(injectFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
Console.WriteLine("\nVersion x86 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
Console.WriteLine("\nVersion x86 Release\n");
*tar = *inj;
#endif
}
else
{
long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
Console.WriteLine("\nVersion x64 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
Console.WriteLine("\nVersion x64 Release\n");
*tar = *inj;
#endif
}
}
}
此代码可以很好地交换方法,但是,如果您正在调试,则似乎永远不会命中原始代码。相反,我想交换方法字节中的 return 语句,并将其替换为跳转到另一个具有相同参数的函数的语句。
但是,.Net Core 当前不支持 MethodRental.SwapMethodBody
如何动态地将代码附加到函数的末尾?
我想出了一个作弊方法。我还没有写出所有的代码,但我会用伪代码来解释
假设我们有一个方法:
public class ValuesController: ControllerBase
{
[HttpGet("Seven")]
public int Seven(string id)
{
return 7;
}
}
我们想换一种方法
public int Eight(int retValue)
{
return retValue + 1;
}
我们可以在动态程序集中生成一个Func。看起来像这样:
public int Dummy(string id)
{}
public int DummyFuncContainer(string id)
{
var result = Dummy(id);
return Eight(result);
}
那么你需要做的就是。
用我们想要的函数 Seven()
交换 Dummy()
方法,然后我们用 DummyFuncContainer()
交换 Seven()
(现在指向 Dummy()
) .
我对在 .Net-Core 中动态附加代码很感兴趣。 注意:这仅用于教育目的。
目前我有一个 class 交换方法:
public static void Inject<TTarget, TInject>(string targetFuncName, string injectFuncName)
{
MethodInfo methodToReplace = typeof(TTarget).GetMethod(targetFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
MethodInfo methodToInject = typeof(TInject).GetMethod(injectFuncName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
unsafe
{
if (IntPtr.Size == 4)
{
int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2;
int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2;
#if DEBUG
Console.WriteLine("\nVersion x86 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
Console.WriteLine("\nVersion x86 Release\n");
*tar = *inj;
#endif
}
else
{
long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer() + 1;
long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer() + 1;
#if DEBUG
Console.WriteLine("\nVersion x64 Debug\n");
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
#else
Console.WriteLine("\nVersion x64 Release\n");
*tar = *inj;
#endif
}
}
}
此代码可以很好地交换方法,但是,如果您正在调试,则似乎永远不会命中原始代码。相反,我想交换方法字节中的 return 语句,并将其替换为跳转到另一个具有相同参数的函数的语句。
但是,.Net Core 当前不支持 MethodRental.SwapMethodBody
如何动态地将代码附加到函数的末尾?
我想出了一个作弊方法。我还没有写出所有的代码,但我会用伪代码来解释
假设我们有一个方法:
public class ValuesController: ControllerBase
{
[HttpGet("Seven")]
public int Seven(string id)
{
return 7;
}
}
我们想换一种方法
public int Eight(int retValue)
{
return retValue + 1;
}
我们可以在动态程序集中生成一个Func。看起来像这样:
public int Dummy(string id)
{}
public int DummyFuncContainer(string id)
{
var result = Dummy(id);
return Eight(result);
}
那么你需要做的就是。
用我们想要的函数 Seven()
交换 Dummy()
方法,然后我们用 DummyFuncContainer()
交换 Seven()
(现在指向 Dummy()
) .