C # Intercept / modify / redirect method

Say I have a private, “instance”, non-static bool method in a third-party dll. This whole method returns a value. Nothing more. How can I intercept calls to this method, change its OpCodes IL / method body, or redirect it to an additional, overridden, or derived method.

I do not want to decompile a third-party dll, manually change the source and recompile it. I would also prefer not to save the assembly to disk, as this also involves using a “recompiled” assembly instead of the original.

Basically I want to be able to use the original dll - no replacements or file changes. I just want to do what I said above.

Is there any way to do this? If so, can you develop or publish links / tutorials, etc.

In addition, I know about virtual, overriding, and new modifiers, but I remember that I: do not have the source of the mentioned third-party DLL, cannot access the source, I do not want to decompile something like dotPeek and recompile.

Thanks!

Edit: I forgot to mention the rest of the infrastructure: MainProgram loads ThirdPartyDLL. MainProgram also downloads MyPluginDLL. I am trying to change a method in ThirdPartyDLL from MyPluginDLL, so that when MainProgram calls the specified method, it will call the changed method. I want to be able to do this WITHOUT saving the new assembly and restarting MainProgram with the new assembly. Essentially, I want to do this either at startup or at launch of MainProgram.

+4
1

, , Mono Cecil. , . .

class Program
{
    static void Main(string[] args)
    {
        Assembly assembly;
        using (MemoryStream assemblyStream = new MemoryStream(File.ReadAllBytes("TargetDLL.dll")))
        {
            // 1. Get the reference to third-party method.
            AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(assemblyStream);
            TypeDefinition targetDLLType = assemblyDef.Modules[0].GetType("TargetDLL.Foo");
            MethodDefinition barMethod = targetDLLType.Methods[0];

            // 2. Let see what Foo.Bar returns...
            assembly = Assembly.Load(assemblyStream.ToArray());
            Console.WriteLine(CallMethod<int>(assembly.GetType("TargetDLL.Foo"), "Bar"));

            // 3. Boot up the IL processor.
            var processor = barMethod.Body.GetILProcessor();

            // 4 View the unmodified IL.
            Console.WriteLine("Original code");
            PrintIL(processor);

            // 5. Modify the code.
            // 5.a Clear the method of all IL.
            processor.Body.Instructions.Clear();

            // 5.b Inject our custom return value.
            processor.Emit(OpCodes.Ldc_I4, 1337);
            processor.Emit(OpCodes.Ret);

            // 6. And how does it look now?
            Console.WriteLine();
            Console.WriteLine("New code");
            PrintIL(processor);

            // 7. Save it.
            assemblyDef.Write(assemblyStream);
            assembly = Assembly.Load(assemblyStream.ToArray());

            // 8. Result value.
            Console.WriteLine(CallMethod<int>(assembly.GetType("TargetDLL.Foo"), "Bar"));
        }

        Console.WriteLine("END");
        Console.ReadKey(true);
    }

    static void PrintIL(ILProcessor processor)
    {
        foreach (var instruction in processor.Body.Instructions)
        {
            Console.WriteLine(instruction);
        }
    }

    static T CallMethod<T>(Type type, string method)
    {
        return (T)type.InvokeMember("Bar", BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public, null, null,
            null);
    }
}

DLL TargetDLL.dll . :

namespace TargetDLL
{
    public static class Foo
    {
        public static int Bar()
        {
            return 0;
        }
    }
}

Edit

, Mono.Cecil. 9.5.0 GitHub. ZIP .

+4

All Articles