Defeating Unity Game with DnSpy, basic reversing engineering

By Jesus Dominguez aka n0tM4l4f4m4 @chucho_domz

Reto de la categoría de 'reverse engineering' del  X-MAS CTF 2019

Challenge

X-MAS: Lapland Mission
I have been trying to win at this game for a while now, but whatever I do there's always a robot that shoots me dead :(
Can you help me win please? (Game) 

File recognition

Una vez descargado el archivo vemos que es un .exe, procederemos a ejecutarlo en una maquina virtual y veremos de que va.


Al ejecutar el archivo vemos que nos dice made with unity, por lo que confirmamos que es un juego hecho en unity. (Fig1)
Fig1

Al entrar al juego nos dan unas instrucciones del modo de juego y unas recomendaciones. (Fig2) 

Fig2

Vemos que la parte de recomendaciones hay 2 cosas por notar, la primera es que hay unos robots que apenas te vean te mataran y la segunda es que para conseguir la flag hay que matarlos a todos.

Vamos a jugar a ver que pasa.

Como vemos empezamos en una cabaña y al apenas salir nos disparan los robots.(Fig3, Fig4)

Fig3
Fig4

Se intento ver si se podían ver por las paredes como pasa en algunos juegos, para intentar ver el mapa completo y tampoco se obtuvo resultado. (Fig5)

Fig5
Unity es un motor de video juegos multiplataforma que mayormente utiliza el lenguaje del alto nivel C# para su programación, aunque también soporta de forma nativa  UnityScript y Boo, siendo estos dos últimos menos populares que el primero.

Hay que recordar que tanto unity como .NET, usan algo llamado AOTcompilación anticipada, los cuales generan a partir de un lenguaje de alto nivel un lenguaje intermedio (CIL en caso de .NET), para posteriormente generan el código ensamblador.

Teniendo en cuenta lo anterior usaremos una herramienta que ya nos ha salvado cuando hemos hecho reversing a .NET, esta es dnSpy, que como la documentación dice sirve para debuggear y editar ensamblados de Unity y .NET, una herramienta similar es ILSpy.

Ahora bien, el compilado que unity genera lo tenemos en la carpeta \X-MAS_Data\Managed y es el archivo Assembly-CSharp.dll, que es donde unity compilo toda la programación en C#.

Al abrir la DLL vemos todos las clases que el juego tiene programadas, así que vamos a empezar a explorar para ver la forma de ganar. (Fig6)

Fig6
Explorando un rato las clases vemos que la clase GamerManager, tiene un método llamado CheckBots, el cual revisa que los bots estén activos, en caso de que todos los Robots del juego lo estén, muestra la pantalla de ganador con el método winscreen.SetActive(), por lo cual ganaríamos el juego. (Fig7)

Fig7
Vamos a analizar el método para ver donde es llamado este.

Vemos que es llamado en el método KilledRobot, de la clase PlayerControl. (Fig8)

Fig8
Con esto confirmamos que tenemos que matarlos a todos para ganar.

La siguiente clase que nos llama la atención es la de Bot, donde tenemos varios métodos, uno es el método Shoot, que es usado para dispararnos. (Fig9)

Fig9
Vemos que dentro de la misma clase en el método Update, es llamado mediante el método IsInvoke.
En la documentación de unity vemos que, el método Update es heredado de MonoBehavoir, y este se invocado en cada frame del vídeo juego.

Llegamos a la conclusión que en este método se usa para dispararnos, en concreto en las siguientes condiciones. (Fig10)

Fig10
El seesPlayer se inicializa en FALSE, así que el robot nos disparara en cuanto nos vea. En la siguiente condición se IsInvoking retorna FALSE por lo que entra a la condición llamando a la función Shoot con 0.1(Fig9).
Quitaremos los operadores NOT de las condiciones para que aunque se muestre la animación donde nos disparan, seamos inmunes al no invocarse el método Shoot (Fig9) y podamos ganar. (Fig11)

Fig11
Con esto hecho recompilamos la DLL y sustituimos la original.

Abrimos el juego y probamos. Y si todo correcto a pesar de que la animación se muestra la función Shoot no es invocada por lo tanto no entra el método Die de la clase Player (Fig9) y no morimos. (Fig12)

Fig12
Funciono, la animación se muestra pero no morimos.
Acabaremos con los robots para ganar el juego.
Eliminamos al ultimo.(Fig13)

Fig13
Ganamos y obtenemos la flag! (Fig14)

Fig14

Flag

X-MAS{G3T_GOOD_G3T_LM4O_BOX}




Go Mayas!



Comentarios