Inject C++ in application (Unity IL2CPP)
Sometimes we want to add or edit some code in an application. If the app is built by Mono, there is no problem to achieve this goal. However, in case the developers used IL2CPP, the task is much more complicated. In such situations, we can edit binaries or inject code. Here I’d like to show how easy it is to inject any code you’d possibly like in a Unity application on Windows. Here is a simple text showing app which was build using IL2CPP.
We will need:
- IL2CPP Inspector
- Visual Studio
- Cheat Engine
Now let’s start with IL2CPP Inspector:
First we need to choose the file:
[App Folder]\[App Name]_Data\il2cpp_data\Metadata\global-metadata.dat
And then this file:
[App Folder]\GameAssembly.dll
Now, the app will show us its options and basic info. It’s needed to remember the Architecture of our target app, because we will need this later. For this exemplary “victim”, the architecture is x86.
Generating C# prototypes from binaries or DLLs also helps a lot if you want to look on classes via dnSpy. I have chosen C# prototypes sliced by assemblies.
In the destination folder, after transformation, you can see the .cs files:
It’s time to create a solution via our coding, which we will inject to the app. IL2CPP Inspector has an option to make it automatically. So we choose C++ scaffolding / DLL injection project option and export.
IL2CPP will generate a solution file. We can open the project via Visual Studio:
First, after opening the file, choose right architecture that IL2CPP shows and Release the option.
As you can see it’s basic dynamic-link DLL project, with a pregenerated thread that is staring while DLL is attached.
In file main.cpp we can write our code which will be injected into the app.
IL2CPP Inspector can also create headers files that contain most of Unity and game logic functions and adds also own methods to help its coding in this environment. Now, we need somehow to hook up to the object instance in Unity. By looking at previously generated prototypes, you can probably find a way to achieve this. For example, in original code we have static field what constants instance of the Text component.
While it is static field, we can have direct access to the value. The code to change text on screen looks like this:
“text” in component Text is a property with getter and setter. So in this case we use the Text_set_text method and not applying values directly to prevent not updating visualization of the text:
Having the right code, we can build DLL which we will inject.
As you can see, compilation ended without any error. DLL files. We can find it in:
[Project Path]/Release/IL2CppDLL.dll
To inject DLL, we use Cheat Engine.
Choose process of victim application via clicking on the screen icon in right top corner.
Open Memory View:
Choose in Tools tab option “Inject DLL”
Choose DLL that we created.
After accepting, you will see the info box that DLL was injected successfully.
Finally, in the victim app, the text will change, so our goal is accomplished.