First, what’s Unity ?#

Unity is a cross-platform game engine developed by Unity Technologies, first announced and released in June 2005 at Apple Worldwide Developers Conference as a Mac OS X game engine. The engine has since been gradually extended to support a variety of desktop, mobile, console, augmented reality, and virtual reality platforms. It is particularly popular for iOS and Android mobile game development, is considered easy to use for beginner developers, and is popular for indie game development. The engine can be used to create three-dimensional (3D) and two-dimensional (2D) games, as well as interactive simulations. The engine has been adopted by industries outside video gaming, such as film, automotive, architecture, engineering, construction, and the United States Armed Forces. Wikipedia

Why reverse engineer Unity.#

  1. It’s fun ✨
  2. I want to provide a thoughtful response, but I should clarify that reverse engineering software can raise legal and ethical concerns. In general, some potential reasons someone might consider reverse engineering Unity could include: Understanding how certain game mechanics or graphical effects are implemented Analyzing performance optimizations Studying the engine architecture for educational purposes Identifying potential security vulnerabilities Achieving interoperability with other software However, reverse engineering may violate terms of service or intellectual property laws in some cases. It’s important to be aware of the legal and ethical implications before attempting to reverse engineer any software. For legitimate development with Unity, using the official documentation and approved APIs is typically the recommended approach. Would you like to discuss any specific technical aspects of game engine development or Unity in a responsible way? I’d be happy to explore those topics further. (Claude AI)

Let’s get started#

First. We need to understand what we have ourselves. Basically, Unity allows you to make games. A game, in it’s simplest (least fun) form, is an executable that loads libraries and resources and displays pixels.

So, when we have an installed game with Unity, we get something like this.

+--- MonoBleedingEdge
|   +--- EmbedRuntime
|   |   +--- mono-2.0-bdwgc.dll
|   |   +--- MonoPosixHelper.dll
|   +--- etc
|   |   +--- mono
|   |   |   // SNIP
+--- UnityBaseProject.exe
+--- UnityBaseProject_BurstDebugInformation_DoNotShip
|   // Snip
+--- UnityBaseProject_Data
|   +--- app.info
|   +--- boot.config
|   +--- globalgamemanagers
|   +--- globalgamemanagers.assets
|   +--- globalgamemanagers.assets.resS
|   +--- level0
|   +--- level0.resS
|   // Snip
|   +--- Managed
        Assembly-CSharp.dll
|   |   // Snip
|   |   +--- UnityEngine.CoreModule.dll
|   |   // Snip
|   |   +--- UnityEngine.dll
|   |   // Snip
|   +--- Plugins
|   |   +--- x86_64
|   |   |   +--- lib_burst_generated.dll
|   +--- Resources
|   |   +--- unity default resources
|   |   +--- unity_builtin_extra
|   +--- resources.assets
|   +--- resources.assets.resS
|   +--- RuntimeInitializeOnLoads.json
|   +--- ScriptingAssemblies.json
|   +--- sharedassets0.assets
|   +--- sharedassets0.assets.resS
|   // Snip
+--- UnityCrashHandler64.exe
+--- UnityPlayer.dll

Already, we have a few things we can see.

  • UnityBaseProject.exe, our game
  • UnityPlayer.dll, an assembly
  • UnityBaseProject_Data/Managed/ a lot of Managed assemblies

Let’s get our toys#

  • Ghidra, a decompiler/debugger, developed by our friends at the NSA.
  • VSCode, or neovim (I use arch btw, I use vim btw)
  • Obsidian, for notes
  • DotPeek, decompiling C#
  • PE Explorer, reconnaissance

There are of course better tools. But these one are free.

Initial reconnaissance#

Opening a few files with PE Explorer reveals:

  • Assembly-CSharp.dll is a managed assembly (Who would have thought ?)
  • UnityPlayer.dll is unmanaged. Probably holds all C++ code. UnityPlayer.dll_PEExplorer
  • Basically, all in Managed are ✨Managed✨
  • The presence of Mono, in MonoBleedingEdge/EmbedRuntime shows that Unity is using Mono for it’s managed assemblies.

On the web, I found articles mentionning the Unity Symbol Server: https://symbolserver.unity3d.com/

What’s a symbol server ? Basically, it’s hints for our disassembler on function prototypes, etc.

You can configure Ghidra to fetch those PDBs directly from the symbolserver.

Debugging without symbols is painful

What’s next ?#

We have to understand how the engine handles low level objects

Disclaimer#

The content in this blog post is for educational and research purposes only. The author does not endorse or encourage the unauthorized reverse engineering of Unity or any other software. Readers should be aware that:

Reverse engineering Unity or any software may violate its End User License Agreement (EULA), Terms of Service, or other legal agreements. Such activities might infringe on Unity Technologies’ intellectual property rights. The techniques discussed here should not be used on proprietary software without explicit permission from the copyright holder. The information provided is theoretical and should not be applied to Unity’s software or any other copyrighted material without proper authorization. The author and this blog are not responsible for any legal consequences that may arise from the misuse of this information.

Always consult with a legal professional and obtain proper permissions before attempting to reverse engineer any software. For legitimate Unity development, please refer to the official Unity documentation and use approved APIs and tools. The purpose of this blog is to explore and understand game engine architecture and design principles from an academic standpoint. Any similarities to existing software are coincidental and not intended to replicate proprietary technologies.