It's time go deeper, peeps. We'll start diving into the more involved/technical game hacking strategies moving forward. Today, i'm focusing on games built with Unity in specific. For the unenlightened, Unity is a cross-platform game engine that is used to create a lot of games. Kerbal Space Program, Cuphead, Doom, and Escape from Tarkov are just a few of the big names created with this engine. With so many big name games we now have a nice target to where we can create a certain attack flow based on what we want to from the game. Let's tear the face off this engine and start ripping it apart.

Tools we'll need to take with us:

DnSpy for - decompiling some code

Unity Asset Bundle Extractor - for extracting and replacing assets

Unity Asset Studio - for looking at and extracting assets

Harmony - for patching games

Cheat Engine - for live function calls

For an overview, most games are written in C#. C# is the main language Unity supports and there is another javascript-like language it supports, but we don't need to mess with that right now. Being as C# is heavily used in an object oriented context, you're going to want to have some experience with concepts like inheritance, overriding, overwriting, and datatypes. The Unity engine calls on game objects which refer to assets stored in asset files for each compiled level or in shared asset files. Assets are any item a dev wants to use in their game. This can include meshes, textures, animations, audio, scenes, etc. A lot of devs also store their code in DLLs (dynamically linked libraries). Great, so here we have two resources we can farm in this case. We can get access to these assets by extracting them and we can access the source code. For those who don't know, assets are either given out for free (low quality), purchased (higher quality), or made in-house. This means that if we can extract them properly, we can take assets and use them in our own game development. I wouldn't recommend selling these or publishing games with them because you're probably going to catch a 'suit against you. But hey, some people like to live wild. I don't judge, yo. For this article, i'll be using a personal favorite game of mine as a test subject, Risk of Rain 2. This game is a rogue-like wave fighting game with a unique artistic style. Great game, highly recommend for hundreds of hours of game time. Let's jump in.

In order to access our assets, we gotta find the source folder of our game. Since this is a Steam game, we can find it in Steam>Steamapps>common>Risk of Rain 2. For a first look, I prefer to use Asset Studio because it can provide a preview to meshes before you extract them. It's better than the guess and check method of extracting assets. From the file path previously mentioned you're going to want to enter the directory Risk of Rain 2_Data. This a pretty standard as most Unity games store their assets in a base directory then store supporting DLLs and other resources in the subsequent directories that we'll get to later.  

So we've got some assets, but what we do with it? We have a few options. As said earlier, we can steal it or sell it OOORRR we can make a mod. That's right you can make any edits to this model in Blender and use the import raw data in Unity Studio bundle asset extractor as shown below.

Home brew = Best brew

I'm not downloading Blender and modifying the mesh because that's just not my cup of tea. However, if you wanna make a mesh of a goose and run around bonking aliens messing with the honk, go right ahead. We can do the same with textures, audio files, and any asset you can find with your extractors. Just a reminder, this isn't as easy in other games like Resident Evil where you have to step through the memory and find the address character models are loaded into. This is Unity which doesn't require a ton of skills to create a game. Since we can customize the look, let's customize the experience.

Using DnSpy, we can decompile variables and functions for our target game. The directory that contains the target DLL is one directory further in called "Managed." The target file is Assembly-CSharp.dll.  

Before you start making crazy edits and being a mad lad, create a copy of this file in case you need to restart. It's very easy to crash your game off of a single changed value. Once we have a back up, we can start exploring. This method is not only good for hacking the game, but also data mining for information about future patches and updates.

Unreleased Character HAN-D

So one good thing about this game being in early access, we know there is unreleased content in the game. In the top image we can see that the devs left both functions and meshes related to an unreleased character named HAN-D in their code/assets. Theoretically, I could go ahead and add this character to the selection to play it in-game, but that would also require me to go in to the code and add all of it's assets into all the proper locations that refer to any character game objects related to HAN-D. This could take a while and I don't really want to spoil the character for myself since I do actually enjoy new content for this game. SPOILER: this character is a short-ranged, heavy-damage melee character. Moving forward, let's actually mess with some in-game functionality.

Changing Small Values

After sifting through the dev's half-decent code, I found the function that calculates how much money to take away from the player's character money stack. If we break it down, it starts by making an instance of the cost type and getting the player's money amount. Then, the this.paycost method sets the respective values of each field for both the item bought as well as the player's money stack. I went ahead and changed the value for the cost, so let's see how it affects the in-game player's money value.

Check it, free items!

If you watch the top left corner you can see the player has an initial stack of $68 then purchases a chest for $25, which should subtract from that value and give me $43 left over. However, as you can see, there was no effect on the player's money value. Nice! Harmony can be used to apply a patch in this situation as well, but i'm not going to go into it. Here is a link that does explain how to use harmony though: https://gist.github.com/pardeike/c02e29f9e030e6a016422ca8a89eefc9

Last step, let's take a look at Cheat Engines live mono injections. Go ahead and start your game, then start CE and hook the game. On the toolbar at the top there should be a tab named "Mono." This will inject a DLL automatically for the Mono Data Collector the game uses already and set up a pipe to communicate with (as per CE docs). What does this do you ask? Well, we've essentially attached a debugger where we can run functions at a high level or we can step through the ASM at a low level. This gives us access to change address values as we hit each individual command called. If you don't understand how this transition, I suggest you do a bit of research on how compilers and assemblers work to execute programs. Once the mono dissector is open, find a function you'd like to tackle.

In the image above, I have found a function that handles the timer on a player's run. We can see that if the stop watch is paused, it'll return the offset from the fixed time pointer. In the game, there is a level where you enter a "world between worlds" and time stops, which is probably why they created this function.

Found the time!

After running the mono dissector, I located the same function from before and used the "jit" command to take a look at the ASM. Immediately it is evident that the je instruction is most likely indicative of the if statement checking if the stop watch is paused. The test instruction does a bitwise and and sets the sign flag to 1 which is then checked with the next je. Since je is checking if 0 = 1, it jumps to the  end of the function and returns.

Negative time is good time

Above is the result of changing the first je instruction to a nop and returning the function. Great! In-game time has been frozen and the difficulty scaling has stopped as it is based on how long you've been in a match. Since this is done in assembly real-time, there isn't any need to attach a debugger. With CE, we can also create a LUA script to automate this, then distribute it to anyone who wants it.

In the end, if your Unity game is using mono instead of IL2CPP, your game is open to being ripped off (if you care). I could see not caring if you just used assets from the Unity store, but if you're creating all of your assets at home, you're doing yourself a disservice. For those who don't know, IL2CPP ensures Unity converts IL code from scripts and assemblies to C++. This will allow for other types of attacks, sure, but your assets will be harder to pull than with Mono. These methods still aren't super in-depth and could 100% be done by people who don't have much of any experience in programming or modding. Nonetheless, jump in, fam, go break some games.