DLL Injection Part 4 — Injecting managed DLL

This is the fourth part of the DLL Injection series. For your convenience you can find other parts in the table of contents in Part 1 – Registry

Las time we saw how to inject DLL into target process using remote threads. However, throughout this whole series we were injecting only native DLL, e.g., libraries compiled to native code. Today we will inject managed library.

Test program

We will use the following program to demonstrate the library injection:

We throw exception every two seconds and immediately handle it with catch clause. We will use this program to demonstrate the DLL injection. We will inject a library which will handle first chance exception and print to console so we will indeed see that our code is executing in the same application domain as the code above. This is only a sample program and in general we do not require our target process to be .NET application, we will use this only for demonstration purposes.

Executing .NET code

First, we need to obtain a handle for .NET framework loaded into the process. You can load .NET into any native application using CLRCreateInstance function. You can have only one .NET framework loaded into the process. We will use this function to obtain a handle for already loaded framework (since our test application is written in C#). Once it’s loaded we can execute any managed code using ExecuteInDefaultAppDomain method.

The plan looks easy at first sight. We simply inject native DLL, next in DLLMain we get a handle for .NET framework, and finally we execute a piece of code. It looks good, however, we need to very careful when executing code in DLLMain method because of loader lock. Loading any library in this method results in a deadlock. And we probably need to load libraries in order to load .NET framework.

However, we can use very similar approach. Basically, we will create two remote threads: first one will load our native dll, the second one will load .NET and execute managed code. Let’s see some code.

Native DLL

We start with the native library. First, the code for loading .NET runtime:

We will inject this library and execute the ImplantDotNetAssembly method. You can use the code from previous part to inject the library. Now we need to get the address of ImplantDotNetAssembly method in the target address space. See the code below:

We load native library into our process and calculate the offset of the function. We assume that the offset will be the same in the target process. Now we need to get the handle for library in the target process:

Finally, we add offset to the module base address and use it as a function address for remote thread. We create remote thread as usually.

Injected managed code

All we need to do is write a managed library which will handle first chance exception. We can use the following code:

As we can see, our function accepts one string argument and returns int so it can be executed. We simply call this function from our native library and we should see that the lambda is called every time an exception is thrown.

Summary

As we can see, we are able to inject both native and managed libraries into other processes. We are also able to choose application domain for our injected code thanks to API for loading .NET into a process. In fact, you can configure many more options when loading framework: you can implement custom memory manager or override routines for creating .NET threads. However, today we only inject managed code.