Home > Net >  How are variables stored in memory in Unity and can a public method with return type be intercepted
How are variables stored in memory in Unity and can a public method with return type be intercepted

Time:11-29

The purpose of this question is to get a better understanding of how my Unity scripts could be potentially hacked, especially at runtime. I was reading this article: https://www.gamedeveloper.com/programming/game-development-protect-your-game-from-getting-hacked and would like to know where to find resources on potentially of "memory injection" hacking as per the article.

The second part of my question has to do with the risks involved in variables being intercepted at runtime. For instance passing a plain text password to a method and getting a return value like so:

    public class CryptoTest : MonoBehaviour
    {
        private readonly CryptoService cryptoService = new CryptoService();
    
        private void Start()
        {
            string plainPassword = "This is a potential password";
            string encryptedPassword = cryptoService.EncryptedString(plainPassword);
            string decryptedPassword = cryptoService.DecryptedString(encryptedPassword);
    
            Debug.Log("Encrypted Password: "   encryptedPassword);
            Debug.Log("Decrypted Password: "   decryptedPassword);
        }
    } 

This is the class that is responsible for encrypting/decrypting:

public class CryptoService
{
    public string EncryptedString(string targetString)
    {
        string containerName = Application.productName   Application.version;

        CspParameters cspParams = new CspParameters { KeyContainerName = containerName };
        RSACryptoServiceProvider cryptoService = new RSACryptoServiceProvider(cspParams);

        byte[] tempBytes = cryptoService.Encrypt(Encoding.UTF8.GetBytes(targetString), true);
        string encryptedString = Convert.ToBase64String(tempBytes);

        return encryptedString;
    }

    public string DecryptedString(string targetString)
    {
        string containerName = Application.productName   Application.version;

        CspParameters cspParams = new CspParameters { KeyContainerName = containerName };
        RSACryptoServiceProvider cryptoService = new RSACryptoServiceProvider(cspParams);

        string decryptedString = Encoding.UTF8.GetString(cryptoService.Decrypt(Convert.FromBase64String(targetString), true));

        return decryptedString;
    }
}

I suppose a big factor has to do with how I use those input/output values, however, the accessor will always be private within the class apart from the CryptoService Class. Can anyone see the potential for that implementation to be hacked/intercepted?

Any information is much appreciated and any links to resources that I might be overlooking! Thanks :)

CodePudding user response:

Please note - that when the logic is on the client, there is no solution that works 100% - it's always theoretically possible to bypass any protection you will place on the client.

Here's my simple approach of combating this that I use all the time, plus you get to mess with players who you catch cheating if you want to.

Basically create an ObfuscatedValue class, which looks something like this (semi pseudo code):

public class MemoryObfuscatedInt
{
    private int _secret;
    private int _obfuscatedValue;

    // This value will always have the real, visual number - only here to catch potential cheaters
    private int _honeyPotValue;

    public MemoryObfuscatedInt()
    {
        _secret = Random.Range(100, 1000);
    }

    public MemoryObfuscatedInt(int secret)
    {
        _secret = secret;
    }

    public bool DidPlayerCheat()
    {
        return _honeyPotValue != Value;
    }

    public int Value
    {
        get
        {
            return _obfuscatedValue / _secret;
        }

        set
        {
            _obfuscatedValue = value * _secret;
            _honeyPotValue = value;

        }
    }

    public static implicit operator int(MemoryObfuscatedInt i) => i.Value;
    public static explicit operator MemoryObfuscatedInt(int toObfuscate) => new MemoryObfuscatedInt { Value = toObfuscate };
}

So if someone uses something like CheatEngine to modify variables, they will look for the _honeyPot value and change them, later you can manually call DidPlayerCheat() and see that the honeypot value has been changed, which basically means the player cheated.

In no way is this approach near anything perfect, but it's good enough to protect from 99.99% of the script kiddies that will try to "hack" your game.

You could of course also encrypt or use any form of obfuscation you wish, I used simple multiplication as an example.

  • Related