.NET Inside Out Part 3 — How to override sealed function in C#

This is the third part of the .NET Inside Out series. For your convenience you can find other parts in the table of contents in Part 1 – Virtual and non-virtual calls in C#

A word of warning! Things presented here depend on the implementation details and require an extensive knowledge about the internals. There are multiple things in place which may change the outcome — multi-tiered compilation, optimizations, JIT vs AoT compilation, and others. I wrote an article covering some aspects but YMMV.

Warning — clickbait title!
We are not going to override sealed function, however, we are going to substitute one method with another using some machine code. Let’s go.

Introduction

Sometimes we would like to stub a function in order to use different one in tests. There are dozens of mocking libraries in C# which easily can do that, however, they usually require the method to be virtual. There are also libraries like Fakes able to modify event sealed types. We are going to do something similar.

Every method is a piece of machine code. If we simply modify this code to jump somewhere else, it will do that. If we jump to some other method with matching signature, we can easily “override sealed function”. Enough of theory, let’s see the code.

Implementation

This method takes two method descriptors: source method to override and target method to use as a jump target. We first prepare the methods (so they are compiled to machine code), next we extract their addresses and calculate the jump. Finally, we generate simple machine code which does the jump. First byte (0xE9) is an opcode of jump instruction, next four bytes represent relative destination address. Finally, we copy the code in place.

We can use the following test program:

The code was tested on x86 and x64 Windows 10 with .NET 4.5.