Unity Obfuscation Methods och Anti-Hack Protection

Du släppte äntligen spelet som du har jobbat så hårt med, och kanske till och med lagt till en leaderboard för att lägga till en utmaning till spelet. Men dagarna går och du märker att några spelare dyker upp ovanpå resultattavlan med orealistiskt höga poäng. Din första tanke är naturligtvis att de hackar, men hur gör de det?

Svaret är att de med största sannolikhet använder ett program för att injicera sina egna värden i minnet, och det mest populära av sådana program är Cheat Engine. Nu, i enspelarspel, spelar hacking egentligen inte så stor roll, men det blir ett problem när det är ett flerspelarspel där de andra spelarna är inblandade.

I det här inlägget kommer jag att visa hur du gör ditt spel säkrare mot sådana attacker, vilket i sin tur kommer att förbättra upplevelsen för icke-hackande spelare.

OBS: Den här artikeln täcker bara kortfattat de vanligaste attackerna och grundläggande skydd mot dem. Om du behöver fler färdiga lösningar, kolla gärna detta Asset Store-paket.

När det kommer till hackning med Cheat Engine finns det 2 vanligaste attacker: Speed ​​Hacking och Value Scanning.

Speed ​​Hack

Eftersom Speed ​​Hack är det enklaste att köra (kräver bara 2 klick), är Speed ​​Hack vanligtvis förstahandsvalet för nybörjare.

Speed ​​hack fungerar genom att snabba upp spelets uppdateringshastighet, vilket gör allt snabbare, vilket ger hackare ett försprång gentemot spelarna som spelar i normal hastighet.

Lyckligtvis finns det ett sätt att upptäcka detta hack i Unity. Kontrollera skriptet nedan:

OBS: Från och med idag fungerar den här metoden inte längre, därför har det blivit mycket svårare att upptäcka hastighetshack i spel för en spelare. Flerspelarspel kan dock fortfarande göra det genom att förlita sig på kontroller på serversidan för att upptäcka eventuella missmatchningar i spelare-servertiden och vidta lämpliga åtgärder (att sparka/banna spelaren, etc.).

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.");
    }
}

Skriptet ovan jämför tiden i spelet med en dators (system)tid. Normalt uppdateras båda tiderna i samma takt (förutsatt att Time.timeScale är inställd på 1), men när SpeedHack aktiveras accelererar den uppdateringsfrekvensen i spelet, vilket gör att in -speltiden ackumuleras snabbare.

När skillnaden mellan båda tiderna blir för stor (i det här fallet 7 sekunder, men du kan välja vilket värde som helst, se bara till att det inte är för litet för att undvika falska positiva resultat) anropar skriptet SpeedhackDetected()-metoden som signalerar närvaron av SpeedHack.

För att använda skriptet, se till att det är bifogat till alla objekt i scenen.

Värdeskanning

Värdeskanning är en process för att hitta relevanta värden i spelets allokerade minne och skriva över dem med olika värden. Används oftast för att öka spelarens hälsa, vapenammunition eller något värde som skulle ge en hackare en orättvis fördel i spelet.

Tekniskt sett kan alla värden i spelet skrivas över/ändras, men betyder det att alla måste skyddas? Inte nödvändigtvis. Generellt sett riktar sig nybörjare bara till de värden som visas på skärmen och är kända för vad de används till (till exempel spelarhälsa, ammunition, etc.). Så för det mesta behöver bara "exposed"-värden skyddas.

Unity FPS Game Skärmdump

Till exempel på skärmdumpen ovan är varje värde på skärmen ett potentiellt mål för hackning.

Så frågan är hur man skyddar de viktiga värdena mot en Value Scanning-attack? Svaret är Obfuscation.

Obfuscation är handlingen att göra något dunkelt, otydligt eller oförståeligt.

Det finns många sätt att fördunkla en variabel, men jag kommer att använda en metod som jag kallar Randomizer. Det slumpmässiga värdet genereras i början, sedan subtraheras det verkliga värdet från det (döljer det sedan), sedan vid behov subtraheras det dolda värdet från ett genererat slumpmässigt värde, med en skillnad som det ursprungliga talet. Nyckeln är att ha ett värde som visas på skärmen för att ha ett helt annat värde än variabeln, vilket leder hackare på ett helt fel sätt när de skannar.

  • Skapa ett nytt skript, kalla det 'SC_Obf' och klistra in koden nedan i det:

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;
    }
}

Skriptet ovan kommer att användas för att generera ett slumpmässigt tal och 2 enkla metoder för att fördunkla och deobfuskera värdena.

  • Låt oss nu gå till ett vanligt exempel på ett skript utan någon förvirring:
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");
    }
}

Skriptet ovan innehåller 2 enkla variabler: hälsa (float) och ammunition (int). Båda variablerna visas på skärmen:

Det här sättet att göra saker är enkelt och bekvämt när det gäller underhåll, men hackare kommer enkelt att kunna skanna värdena och skriva över dem med hjälp av Cheat Engine eller liknande programvara.

  • Här är samma skript, men med obfuskationsmetoder från '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");
    }
}

Istället för att initiera hälso- och ammunitionsvariabler direkt, initierar vi dem i början i void Awake() (se till att anropa SC_Obf.Initialize() innan du tilldelar värdena med SC_Obf.Obfuscate(value)).

Sedan när vi visar värdena, deobfuskerar vi dem i farten genom att anropa SC_Obf.Deobfuscate(value) och visar de verkliga värdena.

Hackaren skulle försöka söka efter 100 och 30 men skulle inte kunna hitta dem eftersom de verkliga värdena är helt annorlunda.

För att manipulera de obfuskerade värdena (t.ex. subtrahera hälsa) deobfuskerar vi först värdet och subtraherar sedan det nödvändiga värdet och fördunklar det slutliga resultatet tillbaka.

För en mer avancerad lösning, kolla gärna detta Asset Store-paket.