Unity Hacking via Python


What is cheating?
Apr 15, 2017
After creating several scripts for Cheat Engine for Unity games in the past I decided I'd like to pursue a different approach as it was nearly impossible to maintain them when the game changed and finally got something working that I like well enough to share. Since its not Cheat Engine, I'm posting generic details here in the General Gamehacking thread.

If you do not already know how to program then if you do not already have a game specific set of scripts then this might be advanced material.

In any case, I really wanted something scriptable and something that can inspect anything in the game and change it. Ultimately I figured out how to compile IronPython for Mono that Unity uses and compiled something that loads into general Unity games and apps I've tried so far. I use a thirdparty plugin called IPA from Eusth (More details can be found here https://github.com/Eusth/IPA) to instrument the game and load plugins it was created for one game but works for any Unity game I've ever tried.

Runs on Windows x86 and x64 architectures. Only on standalone unity installs so no silverlight or web clients. And currently I have different builds for Unity 4 and 5 as that is what I have encountered most.

To install:
Download and unpack the console zip file from github file into the game folder. The plugin requires IPA to be installed so I've created additional downloads that include a recent version but you can download separately from here.

Drag the game exe over ipa.exe to instrument it. Note that this changes the dlls in the Managed folder. This enables the console assemblies to be loaded by the game (and any other plugins you might have). There are other ways to do this that might be simpler and less invasive but this is really simple once you used it once or twice. It makes a backup of the changed dlls so you can revert the changes if you dont like it.

To use:
Press the Ctrl+` (backquote) keys at the same time. For international users you can change the console startup options from the Plugins\Console\Console.ini file if you dont have easy access to the backtick or prefer a different key. There is also an option to open on start or to start hidden and run a startup script which is useful if there is a GUI cheat window script for the game.

You can close the console using ^Z (Control-Z) + Enter or run quit(). I will note that once the console is closed after opening I cannot restart the console and have it work properly so that is disabled. Games will close if you close the console using the X button.

From here you can manipulate anything in the game if you know how to find it. Most games usually have some class that is the root of everything that you can use to get access to more interesting stuff though not always easily. You can use Reflector, dotPeek or dnSpy to search through the game assemblies to find useful stuff. For Unity, most of the good stuff is in Assembly-CSharp.dll.

I should note that manipulating Unity objects directly from the Console can crash the game so I've introduced a library called coroutine to help run python functions properly in unity. If you put too much in a function then unity block and you never see anything so its best to only use the unity wrapper for short operations. You can look at the test.py library in the download for details.

Also you cannot create MonoBehaviour derived classes directly in Python so I had to create wrapper classes that call back to python classes.

You can use the behaviors to take things to the next level and custom user interfaces in Unity which will run arbitrary python code. This is finally where the real payoff is as you can bind keys or buttons to scripts that do useful work. I'll post some specific game examples elsewhere to show this.

You can see an example of using the Unity gui for Cosmic Star Heroine here.

>>> import UnityEngine
>>> print UnityEngine.Application.unityVersion
Create centered window that has a couple of buttons for testing
def test():
    import unity_util
    import UnityEngine
    from UnityEngine import GUI, GUILayout, Screen, Rect, Input, KeyCode
    import System
    # delete all of the old stuff
    class DemoMessage():
        def __init__(self):
            self.color = UnityEngine.Color.white
            self.counter = 1
            self.options = System.Array.CreateInstance(UnityEngine.GUILayoutOption, 0)
            self.show_buttons = False
            self.gameObject = None # will be assigned if exists as member
            self.component = None # will be assigned if exists as member
            self.visible = True
            #print "Called when object is created"
        def Update(self):
            # Update is called less so better place to check keystate than OnGUI
            if Input.GetKeyDown(KeyCode.F8):
                # unity sucks for checking meta keys
                ctrl, alt, shift = unity_util.metakey_state()
                if ctrl and not alt and not shift:
                    self.visible = not self.visible
        def OnGUI(self):
            if self.visible:
                self.counter = self.counter + 1
                origColor = GUI.color
                    GUI.BeginGroup(Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 400, 400))
                    GUI.color = self.color
                    with GUILayout.VerticalScope("Group", GUI.skin.window):
                        self.show_buttons = GUILayout.Toggle(self.show_buttons, "Buttons")
                        if self.show_buttons:
                            if GUILayout.Button("Click me"):
                                print "clicked"
                            if GUILayout.Button("Close"):
                                if self.gameObject: 
                    GUI.color = origColor
        def __del__(self):
            #print "Called when object is garbage collected"
    return unity_util.create_gui_behavior(DemoMessage)


What is cheating?
Apr 17, 2017
As someone who almost exclusively hacks unity games now-a-days, this is awesome. Thank you so much!

Can't wait to dive in with it.