C# 在运行时更改方法体

逆向工程 拆卸 部件 C#
2021-06-23 08:23:30

我正在尝试更改第三方库中的一个部件,它有一个错误,但是,没有修复程序并且源代码也不可用。

一开始,我试图通过反汇编直接修改IL Opcodes,但它有某种保护,所以重新编译它后,即使我从中删除了它也无法使用Strong Name verification它。

我试图IL instructions在运行时改变,但是

        InjectionHelper.Initialize();
        InjectionHelper.WaitForIntializationCompletion();
        Type type = obj.GetType();
        var methods = type.GetMethods();
       // MethodInfo targetMethod = type.GetMethod("MethodName",  BindingFlags.NonPublic | BindingFlags.Instance);

        var methodInfo = type
            .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Single(
                m =>
                    m.ReturnType == typeof(string) &&
                    m.GetParameters().Length == 1);

        RuntimeHelpers.PrepareMethod(methodInfo.MethodHandle);
        byte[] ilOpCodes = methodInfo.GetMethodBody()?.GetILAsByteArray();
        for (int i = 0; i < ilOpCodes.Length; i++)
        {
            if (ilOpCodes[i] == OpCodes.Ldc_I4_1.Value)
            {
                ilOpCodes[i] = (byte) OpCodes.Ldc_I4_0.Value;
                break;
            }
        }
        InjectionHelper.UpdateILCodes(methodInfo,ilOpCodes);

但不幸的是有一个例外。

Unhandled Exception: System.Exception: UpdateILCodes() failed, please check the initialization is failed or uncompleted.

我犯了什么错误吗?我使用这篇文章作为参考https://www.codeproject.com/Articles/463508/NET-CLR-Injection-Modify-IL-Code-during-Run-time 那么让它可用的最佳方法是什么?

1个回答

过去我在运行时编辑 IL 代码时遇到问题,特别是如果该方法已经由 JIT 编译器编译,我发现的最完整的证明方法是在运行时修补它是编辑 x86/由 JIT 编译器生成的 x86_64(或您正在运行的任何架构),它位于由

MethodInfo.MethodHandle.GetFunctionPointer()

但是您需要通过调用或使用来确保目标函数已经编译

RuntimeHelpers.PrepareMethod(MethodHandle)

从那里你可以使用不安全的代码块或 Marshal 来复制你自己的 x86 字节码(例如跳转到你想要替换的函数)

但是,我确实建议您使用,或者至少看一看Harmony,它是一个被多个游戏用来支持 mod 的库。

至于在删除强名称后无法使用该库的原因,可能是因为使用该库的应用程序是由强名称“链接”的,如果没有它,加载会失败。