MjeOsX
MjeOsX

Reputation: 405

C# Mono.Cecil injected IL Code does not get executed

I want to make a little sample code with Mono.Cecil The goal is to manipulate the IL. The method X does print something on the console. To test the manipulation of the IL code i remove all instructions from the method. But when I run External2.dll the Console Output is still printed (but the instructions to do the Console output are removed from the External2.dll). How can I fix this problem?

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");

Upvotes: 1

Views: 824

Answers (1)

Vagaus
Vagaus

Reputation: 4215

I think you need to use AssemblyDefinition instead of ModuleDefinition

Also, you cannot simply remove all instructions from your method body. You need to have at least one ret. For instance the code below does work:

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");
        }
    }
}

btw, you can always use https://cecilifier.me to help you out.

Upvotes: 2

Related Questions