Metodi di offuscamento di Unity e protezione anti-hack

Hai finalmente rilasciato il gioco su cui hai lavorato così duramente e forse hai anche aggiunto una classifica per aggiungere sfida al gioco. Ma i giorni passano e noti che alcuni giocatori spuntano in cima alla classifica con punteggi irrealisticamente alti. Il tuo primo pensiero è ovviamente che stiano facendo hacking, ma come fanno?

La risposta è che molto probabilmente stanno utilizzando un programma per iniettare i propri valori nella memoria, e il più popolare di questi programmi è Cheat Engine. Ora, nei giochi per giocatore singolo, l'hacking non ha molta importanza, ma diventa un problema quando si tratta di un gioco multigiocatore in cui sono coinvolti gli altri giocatori.

In questo post mostrerò come rendere il tuo gioco più sicuro contro tali attacchi, il che a sua volta migliorerà l'esperienza per i giocatori non hacker.

NOTA: questo articolo tratta solo brevemente gli attacchi più comuni e la protezione di base contro di essi. Se hai bisogno di una soluzione più pronta all'uso, non esitare a controllare questo pacchetto Asset Store.

Quando si tratta di hacking con Cheat Engine ci sono 2 attacchi più comuni: Speed ​​Hacking e Value Scanning.

Hack di velocità

Essendo il più semplice da eseguire (richiede solo 2 clic), lo Speed ​​Hack è solitamente la prima scelta per gli utenti inesperti.

L'hacking della velocità funziona accelerando la velocità di aggiornamento del gioco, rendendo tutto più veloce, dando così agli hacker un vantaggio rispetto ai giocatori che giocano a velocità normale.

Fortunatamente, esiste un modo per rilevare questo hack in Unity. Controlla lo script qui sotto:

NOTA: ad oggi questo metodo non funziona più, quindi rilevare gli speed hack è diventato molto più difficile nei giochi per giocatore singolo. I giochi multiplayer, tuttavia, sono ancora in grado di farlo facendo affidamento sui controlli lato server per rilevare eventuali discrepanze nel tempo giocatore-server e intraprendere l'azione appropriata (calciare/bannare il giocatore, ecc.).

SC_SpeedhackDetector.cs

using UnityEngine;
using System;

public class SC_SpeedhackDetector : MonoBehaviour
{
    //Speed hack protection
    public int timeDiff = 0; 
    int previousTime = 0;
    int realTime = 0;
    float gameTime = 0;
    bool detected = false;

    // Use this for initialization
    void Start()
    {
        previousTime = DateTime.Now.Second;
        gameTime = 1;
    }

    // Update is called once per frame 
    void FixedUpdate()
    {
        if (previousTime != DateTime.Now.Second)
        {
            realTime++;
            previousTime = DateTime.Now.Second;

            timeDiff = (int)gameTime - realTime;
            if (timeDiff > 7)
            {
                if (!detected)
                {
                    detected = true;
                    SpeedhackDetected();
                }
            }
            else
            {
                detected = false;
            }
        }
        gameTime += Time.deltaTime;
    }

    void SpeedhackDetected()
    {
        //Speedhack was detected, do something here (kick player from the game etc.)
        print("Speedhack detected.");
    }
}

Lo script sopra confronta il tempo di gioco con il tempo di sistema del computer. Normalmente entrambi gli orari vengono aggiornati alla stessa velocità (presupponendo che Time.timeScale sia impostato su 1), ma quando SpeedHack è attivato, accelera la frequenza di aggiornamento del gioco, rendendo l'ingresso -Il tempo di gioco si accumula più velocemente.

Quando la differenza tra i due tempi diventa troppo grande (in questo caso 7 secondi, ma puoi scegliere qualsiasi valore, assicurati solo che non sia troppo piccolo per evitare falsi positivi) lo script chiama il metodo SpeedhackDetected() che segnala la presenza di SpeedHack.

Per utilizzare lo script assicurati che sia attaccato a qualsiasi oggetto nella scena.

Scansione dei valori

La scansione dei valori è un processo per trovare valori rilevanti nella memoria allocata del gioco e sovrascriverli con valori diversi. Più comunemente utilizzato per aumentare la salute del giocatore, le munizioni per le armi o qualsiasi valore che possa dare a un hacker un vantaggio ingiusto nel gioco.

Tecnicamente parlando, ogni valore nel gioco può essere sovrascritto/modificato, ma significa che è necessario proteggerli tutti? Non necessariamente. In genere, gli hacker alle prime armi prendono di mira solo i valori visualizzati sullo schermo e sanno a cosa servono (ad esempio salute del giocatore, munizioni, ecc.). Pertanto, nella maggior parte dei casi è necessario proteggere solo i valori "exposed".

Schermata del gioco FPS di Unity

Ad esempio, nello screenshot qui sopra, ogni valore sullo schermo è un potenziale bersaglio per l'hacking.

Quindi la domanda è: come proteggere i valori importanti da un attacco Value Scanning? La risposta è Offuscamento.

L'offuscamento è l'azione di rendere qualcosa di oscuro, poco chiaro o incomprensibile.

Esistono molti modi per offuscare una variabile, ma utilizzerò un metodo che chiamo Randomizer. Il valore casuale viene generato all'inizio, poi gli viene sottratto il valore reale (successivamente nascondendolo), quindi, quando necessario, il valore nascosto viene sottratto da un valore casuale generato, con la differenza del numero originale. La chiave è che un valore visualizzato sullo schermo abbia un valore completamente diverso dalla variabile, portando gli hacker in una direzione completamente sbagliata durante la scansione.

  • Crea un nuovo script, chiamalo 'SC_Obf' e incolla al suo interno il codice seguente:

SC_Obf.cs

using UnityEngine;

public class SC_Obf : MonoBehaviour
{
    static float random = -1;

    public static void Initialize()
    {
        if(random == -1)
        {
            random = Random.Range(10000, 99999);
        }
    }

    public static float Obfuscate(float originalValue)
    {
        return random - originalValue;
    }

    public static float Deobfuscate(float obfuscatedValue)
    {
        return random - obfuscatedValue;
    }
}

Lo script sopra verrà utilizzato per generare un numero casuale e 2 semplici metodi per offuscare e deoffuscare i valori.

  • Passiamo ora a un esempio normale di script senza offuscamenti:
using UnityEngine;

public class SC_Test : MonoBehaviour
{
    public float health = 100;
    public int ammo = 30;

    public void Damage(float points)
    {
        health -= points;
    }

    void OnGUI()
    {
        GUI.Label(new Rect(5, 5, 150, 25), health + " HP");
        GUI.Label(new Rect(5, 30, 150, 25), ammo + " Ammo");
    }
}

Lo script sopra contiene 2 semplici variabili: salute (float) e munizioni (int). Entrambe le variabili vengono visualizzate sullo schermo:

Questo modo di fare le cose è semplice e conveniente in termini di manutenzione, ma gli hacker saranno facilmente in grado di scansionare i valori e sovrascriverli utilizzando Cheat Engine o software simili.

  • Ecco lo stesso script, ma utilizzando i metodi di offuscamento di 'SC_Obf.cs':
using UnityEngine;

public class SC_Test : MonoBehaviour
{
    public float health;
    public int ammo;

    void Awake()
    {
        SC_Obf.Initialize();
        health = SC_Obf.Obfuscate(100);
        ammo = (int)SC_Obf.Obfuscate(30);
    }

    public void Damage(float points)
    {
        health = SC_Obf.Obfuscate(SC_Obf.Deobfuscate(health) - points);
    }

    void OnGUI()
    {
        GUI.Label(new Rect(5, 5, 150, 25), SC_Obf.Deobfuscate(health) + " HP");
        GUI.Label(new Rect(5, 30, 150, 25), SC_Obf.Deobfuscate(ammo) + " Ammo");
    }
}

Invece di inizializzare direttamente le variabili salute e munizioni, le inizializziamo all'inizio in void Awake() (assicurati di chiamare SC_Obf.Initialize() prima di assegnare i valori utilizzando SC_Obf.Obfuscate(value)).

Quindi, quando visualizziamo i valori, li deoffuschiamo al volo chiamando SC_Obf.Deobfuscate(value) visualizzando così i valori reali.

L'hacker proverebbe a cercare 100 e 30 ma non riuscirebbe a trovarli perché i valori reali sono completamente diversi.

Per manipolare i valori offuscati (ad esempio sottraendo la salute), prima deoffuschiamo il valore, quindi sottraiamo il valore necessario, quindi offuschiamo nuovamente il risultato finale.

Per una soluzione più avanzata, non esitare a dare un'occhiata a questo Asset Store pacchetto.

Articoli suggeriti
Introduzione al linguaggio di scripting Unity C#
Metodi all'inizio del runtime che inizializzano i valori in Unity
Comprensione delle funzioni e delle chiamate ai metodi
Come riprodurre file video in Unity
Come modificare la risoluzione dello schermo in Unity Game
Rotazione sul posto in Unity
Creazione di un semplice sistema di proiettili 2D in Unity