Results 1 to 2 of 2
  1. #1
    Drenferalis's Avatar
    Join Date
    May 2012
    Gender
    male
    Posts
    1
    Reputation
    31
    Thanks
    6

    Post Making a Unity 3D Game Internal Hack C#/C++

    Disclaimer: I am by no means "experienced" in any of this. I don't know how to steal handles, I can't bypass anti-cheats, I hardly know any ASM, and I'm a really shitty programmer. Some of the code needed to make this work belongs to Ghostery @ UC, and they credit Nomster and iZed (figured I should give credit).

    Invoker


    Getting Started:
    The first part of this entire thing is downloading mono, you'll need the mono library and includes. You can find them on the mono-project website. I moved my mono install to C:\Mono\ for ease of use, if you skip this step you will need to modify future steps. There are other ways to do this, but this is the way that I have found is most reliable and adaptive while still being easy. This tutorial will use Visual Studio 2017 for the compiling of the dll invoker. The invoker is needed to execute your C# hack inside of the Unity Game assembly. The invoker is using C++ primarily for its dllmain entrypoint.

    1. First create a new Empty C++ project.
    2. Right click the Project in the Solution Viewer and click Properties.
    3. Click Configuration Properties -> C/C++ -> General in the left window. (If you don't see it make sure you right clicked the Project and not the Solution and that it is a C++ project)
    4. Under "Additional Include Directories" add your Mono include path. Mine was "C:\Mono\include\mono-2.0"
    5. Click Configuration Properties -> Linker -> General in the left window.
    6. Under "Additional Library Directories" add your mono library path. Mine was "C:\Mono\lib"
    7. Click Configuration Properties -> Linker -> Input in the left window.
    8. Under "Additional Dependencies" add your mono library. Mine was "mono-2.0-sgen.lib"
    9. Click Configuration Properties -> General in the left window.
    10. Change "Configuration Type" to "Dynamic Library (.dll)"



    After that is done you have set up the required references for the mono invoker.

    Create a new cpp file

    Here is the code that Ghostery gave (with some additions for helpful debugging.):
    Code:
    #include <windows.h>
    #include <process.h>
    #include <mono\jit\jit.h>
     
    //Credit to Ghostery@UC 2016
     
    HMODULE hMono = GetModuleHandleA("mono.dll");
     
     
    //Simple function for returning mono functions. Change DWORD64 to DWORD for 32 bit
    DWORD64 GetMonoFunction(char* funcname){
     
    	return (DWORD64)GetProcAddress(hMono, funcname);
    }
     
     
    void RunMonoInject()
    {	
    	//Attach
    	typedef MonoThread* (__cdecl* mono_thread_attach_t)(MonoDomain* mDomain);
    	mono_thread_attach_t mono_thread_attach = (mono_thread_attach_t)GetMonoFunction("mono_thread_attach");
    	
    	
    	//Class
    	typedef MonoClass* (__cdecl* mono_class_from_name_t)(MonoImage* image, const char* name_space, const char* name);
    	typedef MonoMethod* (__cdecl* mono_class_get_method_from_name_t)(MonoClass* mclass, const char* name, int param_count);
    	mono_class_from_name_t mono_class_from_name = (mono_class_from_name_t)GetMonoFunction("mono_class_from_name");
    	mono_class_get_method_from_name_t mono_class_get_method_from_name = (mono_class_get_method_from_name_t)GetMonoFunction("mono_class_get_method_from_name");
     
    	
    	//Code execution
    	typedef MonoObject* (__cdecl* mono_runtime_invoke_t)(MonoMethod* method, void* obj, void** params, MonoObject** exc);
    	mono_runtime_invoke_t mono_runtime_invoke = (mono_runtime_invoke_t)GetMonoFunction("mono_runtime_invoke");
    
    	
    	//Assembly
    	typedef MonoAssembly* (__cdecl* mono_assembly_open_t)(MonoDomain* mDomain, const char* filepath);
    	typedef MonoImage* (__cdecl* mono_assembly_get_image_t)(MonoAssembly *assembly);
    	mono_assembly_open_t mono_assembly_open_ = (mono_assembly_open_t)GetMonoFunction("mono_domain_assembly_open");
    	mono_assembly_get_image_t mono_assembly_get_image_ = (mono_assembly_get_image_t)GetMonoFunction("mono_assembly_get_image");
     
    	
    	//Domain
    	typedef MonoDomain* (__cdecl* mono_root_domain_get_t)();
    	typedef MonoDomain* (__cdecl* mono_domain_get_t)();
    	mono_root_domain_get_t mono_root_domain_get = (mono_root_domain_get_t)GetMonoFunction("mono_get_root_domain");
    	mono_domain_get_t mono_domain_getnormal = (mono_domain_get_t)GetMonoFunction("mono_domain_get");
    		
    	//No clue what happens here, but is required in order for the domain to be ready at time for code-execution.
    	mono_thread_attach(mono_root_domain_get());
    	//Now that we're attached we get the domain we are in.
    	MonoDomain* domain = mono_domain_getnormal();
    	if(!domain)
    		MessageBox(0, "Failed to obtain Mono Domain...", "MessageBox caption", MB_OK);
    
    	//Opening a custom assembly in the domain.
    	MonoAssembly* domainassembly = mono_assembly_open_(domain, "Ex: C:\\MyDll.dll"); //Replace with your DLL.
    	if (!domainassembly)
    		MessageBox(0, "Failed to open DLL.", "Error!", MB_OK);
    
    	//Getting the assemblys Image(Binary image, essentially a file-module).	 
    	MonoImage *Image = mono_assembly_get_image_(domainassembly);
    	if(!Image)
    		MessageBox(0, "Failed to open Image.", "Error!", MB_OK);
    
    	//Declaring the class inside the custom assembly we're going to use. (Image, NameSpace, ClassName)
    	MonoClass* pClass = mono_class_from_name(Image, "NameSpace", "ClassName");
    
    	//Declaring the method, that attaches our assembly to the game. (Class, MethodName, Parameters)
    	MonoMethod* MonoClassMethod = mono_class_get_method_from_name(pClass, "MethodName", 0);
    		
    	//Invoking said method.
    	mono_runtime_invoke(MonoClassMethod, NULL, NULL, NULL);
    
    	MessageBox(0, "Finished Mono Inject", "MessageBox caption", MB_OK);
    
    
    }
     
    UINT __stdcall dwMain2(void*){
    	
    	RunMonoInject();
    	
    	return 0;
    }
     
    //Entry point.
    extern "C" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
    	if (ul_reason_for_call == DLL_PROCESS_ATTACH){
    		_beginthreadex(0, 0, dwMain2, 0, 0, 0);
    	}
    
    	return true;
     
    }
    Disclaimer: NOT MY CODE. See disclaimer at top of post. (Googling "mono_runtime_invoke" will give you the full documentation from mono.)

    Now to explain a bit about the code and what it does:

    Upon initialization it obtains a handle to mono with a system function. This handle is later used to get pointer information from inside the process's mono dll.
    When the entrypoint detects successful injection it will create a new thread that runs the MonoInject function.
    Next the script uses typedef to define new types and functions with the pointer information from a system function using the handle.
    Once all of the definitions are finished the script can start to use them.

    First the script attaches the current thread into the root domain of the mono instance.
    Next it obtains a reference to the domain we are in.
    Next it uses assembly_open which loads our managed Hack DLL into the domains memory.
    Next it gets the reference to the code part of our assembly with mono_assembly_get_image. Basically loading the code format.
    Now the script will begin to look in your DLL for the namespace and class specified in mono_class_from_name.
    Once it has a reference to the class it will obtain a reference to the method that we want Invoked with mono_class_get_method_from_name, which would usually be your Unity GameObject loader.
    Once it has this reference we can finally invoke it (unless the method is non-static, in which case we would need to init the object in the current domain before invoking with a reference to the new object).

    Note: It should be fairly obvious, but in case you didn't notice, you need to change the source to reflect your DLL.

    GameObject / MonoBehavior


    Now that we have our invoker (which effectively gives us an entry point in C# in the correct domain and thread) we can start making hacks in C# by abusing UnityEngine's GameObject and the MonoBehaviour Interface.

    For this next section the steps will vary greatly depending on the game and type of hack you are trying to make, but a great first start is always looking at the available code, to do this I normally use ILSpy and load up the games Managed/Assembly-CSharp.dll Here I can see all the public objects I can access and manipulate.

    This is the typical Load method for a C# Unity hack:
    Code:
    using UnityEngine;
    
    namespace UnityHack
    {
        public class HackLoad
        {
            public static GameObject load_object;
    
            public static void Load()
            {
    
                    load_object = new GameObject();
                    load_object.AddComponent<Cheat>();
                    UnityEngine.Object.DontDestroyOnLoad(load_object); // Allows object to persist through loading scenes.
                    
    
            }
        }
    }
    Credit: Not mine, and its hard to trace who exactly came up with this method.

    Important: Note that the Load method is "static".

    Now you can make a new class that inherits MonoBehaviour and use it as the component you would like to add to our object.

    Note: In order to use the public objects from Assembly-CSharp.dll you must include it as a reference in your C# project.

    Here's an example of a hack I made for a game called Welcome to the Game 2.0:

    Code:
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using UnityEngine;
    
    namespace UnityHack
    {
        class Cheat : MonoBehaviour
        {
            private bool first = true;
            public void Update()
            {
                if (first && GameManager.BehaviourManager.NotesBehaviour.enabled)
                {
                    GameManager.BehaviourManager.NotesBehaviour.AddNote("Welcome to My Hacks! Listing all wifi data:");
                    List<WifiNetworkDefinition> Wifis = GameManager.ManagerSlinger.WifiManager.GetAllWifiNetworks();
                    foreach (WifiNetworkDefinition x in Wifis)
                    {
                        GameManager.BehaviourManager.NotesBehaviour.AddNote(
    
                            "*** Name: " + x.networkName + 
                            " Password: " + x.networkPassword + 
                            " Heat: " + x.networkTrackProbability * 100f + "% chance of attack every "+ x.networkTrackRate + " Seconds." +
                            " Loading Delay: " + x.networkPower + " ***"
                            );
                    }
                    first = false;
                }
    
    
                if (EnemyManager.State != ENEMY_STATE.IDLE)
                {
                    LookUp.DesktopUI.MOTION_SENSOR_MENU_ICON_ACTIVE.alpha = 1f;
                    LookUp.DesktopUI.MOTION_SENSOR_MENU_ICON_IDLE.alpha = 0f;
                }
                else
                {
                    LookUp.DesktopUI.MOTION_SENSOR_MENU_ICON_ACTIVE.alpha = 0f;
                    LookUp.DesktopUI.MOTION_SENSOR_MENU_ICON_IDLE.alpha = 1f;
                }
    
    
            }
            
        }
    }
    As you can see this is literally just programming a new behavior for the game as if you were programming for a unity game, so all Unity documentation that excludes the editor also applies.

    Now to load your hacks use any regular injector to inject your invoking DLL, which will load your C# assembly DLL.

    If you want your hacks to do something specific and you can't figure out how: look up how to do it in Unity. There are tons of community forums helping Unity developers.

    And here's an example of how to get a moving targets aim position with bullet drop:
    Code:
    public Vector3 GetTargetPosition(Vector3 origin, Vector3 target, Vector3 targetVelocity)
            {
                Vector3 lookPos = target - origin;
                float scale = lookPos.magnitude / Player.activeWeapon.projectileSpeed;
                
                Vector3 normalized = lookPos.normalized;
                Vector3 aimVector = Vector3.zero;
                Vector3 tmp = Vector3.zero;
    
                Vector3 b = Player.activeWeapon.projectileGravity * Mathf.Pow(scale, 2f) / 2f;
                tmp = lookPos - b;
                scale = scale / Vector3.Dot(tmp.normalized, normalized);
                aimVector = targetVelocity * scale - Player.activeWeapon.projectileGravity * Mathf.Pow(scale, 2f) / 2f;
    
                return aimVector;
            }
    Final Notes: Yep, I am a terrible programmer. This method of hacking is super detectable, check for anti-cheats when digging around, if you find one and use this method, expect a ban. The reason I posted this, even though most of the code itself that makes this work isn't mine is because thanks to this code I finally understood how invoking code in domains worked, and I believe that grouping all this information together in a sensical manner could be largely beneficial to the community. Please let me know of any corrections I should make.
    Last edited by Drenferalis; 04-19-2018 at 05:27 PM.

  2. The Following 6 Users Say Thank You to Drenferalis For This Useful Post:

    059 (01-02-2019),HacxXcoder_Death (04-19-2018),jpitt1 (09-22-2018),malloc84 (11-22-2019),MarcelElaie (05-25-2019),yobson (06-09-2018)

  3. #2
    MarcelElaie's Avatar
    Join Date
    Aug 2018
    Gender
    male
    Posts
    2
    Reputation
    10
    Thanks
    0
    awesome tutorial bro , don't understand why nobody comment though...

Similar Threads

  1. [Help] Making Game Trainers/Hacks on MAC
    By a stick in forum C++/C Programming
    Replies: 1
    Last Post: 01-01-2017, 06:16 PM
  2. Replies: 7
    Last Post: 08-21-2012, 07:09 AM
  3. You can make one online strategy game hack, please
    By bu-do in forum Hack Requests
    Replies: 1
    Last Post: 08-21-2012, 06:15 AM
  4. In-Game kicking hack for Warrock
    By Zededarian in forum Game Hacking Tutorials
    Replies: 1
    Last Post: 05-19-2012, 10:40 PM
  5. Helbreath International Hack/GM Hack tut
    By xxaznrjaexx in forum Hack Requests
    Replies: 1
    Last Post: 01-27-2006, 02:42 AM