【问题标题】:C# Mono.Cecil injected IL Code does not get executedC# Mono.Cecil 注入的 IL 代码未执行
【发布时间】:2020-08-31 20:41:25
【问题描述】:

我想用 Mono.Cecil 做一个小示例代码 目标是操纵 IL。 方法 X 确实在控制台上打印了一些东西。为了测试对 IL 代码的操作,我从方法中删除了所有指令。但是当我运行 External2.dll 时,仍然会打印控制台输出(但是从 External2.dll 中删除了执行控制台输出的说明)。我该如何解决这个问题?

var module = ModuleDefinition.ReadModule("External.dll");
var types = module.Types;
foreach (var type in types) {
    foreach (var method in type.Methods) {
        if (method.Name == "X") {
            Console.WriteLine(method.Body.Instructions.Count);
            method.Body.Instructions.Clear();
            Console.WriteLine(method.Body.Instructions.Count);
        }
    }
}
module.Write("External2.dll");

【问题讨论】:

    标签: c# .net mono cil mono.cecil


    【解决方案1】:

    我认为您需要使用AssemblyDefinition 而不是ModuleDefinition

    此外,您不能简单地从方法主体中删除所有指令。您需要至少有一个ret。例如下面的代码确实有效:

    using System;
    using System.Linq;
    using Mono.Cecil;
    using System.IO;
    
    namespace cecil
    {
        class Program
        {
            static void Main(string[] args)
            {
                X();
    
                var assembly = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
                var method = assembly.MainModule.Types.SelectMany(t => t.Methods).SingleOrDefault(m => m.Name == "X");
    
                if (method == null)
                {
                    System.Console.WriteLine("Method X not found.");
                }
                else
                {
                    Console.WriteLine(method.Body.Instructions.Count);
                    method.Body.Instructions.Clear();
                    var ilProcessor = method.Body.GetILProcessor();
                    ilProcessor.Append(ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Ret));
    
                    Console.WriteLine(method.Body.Instructions.Count);
    
                    var newAssemblyFileName= "External2.dll";
                    assembly.Write(newAssemblyFileName);
                    System.Console.WriteLine($"Assembly saved to {Path.GetFullPath(newAssemblyFileName)}");
                }
            }
    
            private static void X()
            {
                System.Console.WriteLine("From X");
            }
        }
    }
    

    顺便说一句,您可以随时使用https://cecilifier.me 来帮助您。

    【讨论】:

    • 是的,ret 必须还在。我怎么能监督这个:)
    • 再次感谢您的帮助。但我仍然有同样的问题。 IL 代码会被您的代码操纵。但是由于某种原因,当我运行 External2.dll 时,我仍然会得到“来自 X”的控制台输出,就像会有一些缓存机制一样。你知道这怎么可能吗?我用 dotnet \External2.dll 运行它
    • 当我将 External2.dll(以及所有引用)复制到另一个文件夹时它可以工作:) 所以必须有一个文件我必须删除
    • 我需要有关您如何构建/运行的更多详细信息以提供更多帮助。例如,我已经用 dotnet core 对此进行了测试,并且为了能够运行“External2.dll”,我需要将它复制到原来的上面。
    猜你喜欢
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多