Archive

Archive for June, 2020

IL2CPP Reverse Engineering Part 1: Hello World and the IL2CPP Toolchain

June 24, 2020 12 comments

[You can use Il2CppInspector to help automate the techniques outlined in this series]

[Updated 27th November 2020: the command-line build instructions were updated to be compatible with Il2CppInspector 2020.2.1]

In this article, you will learn:

  • what IL2CPP is and why it exists
  • what the generated C++ source code and binary disassembly of a simple function looks like compared to native C#, IL and C++ code
  • how to setup your environment to generate C++ source code and IL2CPP binaries from your own C# code so that you can examine and compare them with your original code
  • how to use IL2CPP at the command-line on arbitrary code without Unity

Introduction to IL2CPP

IL2CPP is an alternative application deployment model introduced into Unity in 2015 which is designed to bring significant performance improvements to Unity games. It’s a beautiful mess, and today we’re going to start picking it apart.

A standard Unity game is distributed as a series of .NET assemblies which are executed by the managed runtime (CLR) on the target platform of choice as per the norm for any .NET application. The premise of IL2CPP is to take these assemblies, parse the IL, generate C++ equivalent source code from it, then compile this C++ into machine code for faster, unmanaged execution. This is described quite well on this page of the Unity manual with this diagram:

A diagram of the automatic steps taken when building a project using IL2CPP

There are several excellent guides about how IL2CPP generates code such as Unity’s own IL2CPP Internals blog series and Jackson Dunstan’s exquisitely detailed musings, so I’m not going to repeat that work here. Instead, I want to focus on the opposite perspective: how do we reverse engineer compiled IL2CPP binaries?

Unity games have traditionally been exceptionally easy to reverse engineer, generally requiring nothing more than a copy of ILSpy (or my preferred tool Telerik JustDecompile) and a dream. IL2CPP changes all that: we go from neat assemblies – often with all of the function and variable names intact – to straight up machine code that we have to wade through in a disassembler. Suddenly, even finding the areas of interest becomes magnitudes tougher. How can we make this task easier?

To answer that question, we’re going to need to develop a deep understanding of how IL2CPP manages types and data under the hood, and that’s what this series is all about. Buckle up!

Read more…
Advertisement
Categories: IL2CPP Tags:
%d bloggers like this: