Métodos de ofuscação do Unity e proteção anti-hack

Você finalmente lançou o jogo no qual tem trabalhado tanto e talvez até tenha adicionado uma tabela de classificação para adicionar desafio ao jogo. Mas os dias passam e você percebe alguns jogadores aparecendo no topo do placar com pontuações irrealistas. Seu primeiro pensamento é que eles estão hackeando, mas como eles fazem isso?

A resposta é que eles provavelmente estão usando um programa para injetar seus próprios valores na memória, sendo o mais popular desses programas o Cheat Engine. Agora, em jogos para um jogador, hackear não importa muito, mas se torna um problema quando é um jogo multijogador em que os outros jogadores estão envolvidos.

Neste post, mostrarei como tornar seu jogo mais seguro contra tais ataques, o que por sua vez irá melhorar a experiência para jogadores que não são hackers.

NOTA: Este artigo aborda apenas brevemente os ataques mais comuns e a proteção básica contra eles. Se você precisar de mais soluções prontas para uso, sinta-se à vontade para verificar este Asset Store Pacote.

Quando se trata de hackear com o Cheat Engine, existem 2 ataques mais comuns: Speed ​​Hacking e Value Scanning.

Hack de velocidade

Por ser o mais fácil de executar (requer apenas 2 cliques), o Speed ​​Hack costuma ser a primeira escolha para usuários novatos.

O speed hack funciona acelerando a taxa de atualização do jogo, tornando tudo mais rápido, dando assim aos hackers uma vantagem sobre os jogadores que jogam na velocidade normal.

Felizmente, existe uma maneira de detectar esse hack em Unity. Confira o roteiro abaixo:

NOTA: A partir de hoje, este método não funciona mais, portanto, detectar speed hack tornou-se muito mais difícil em jogos single-player. Os jogos multijogador, no entanto, ainda são capazes de fazer isso contando com verificações do lado do servidor para detectar qualquer incompatibilidade no tempo jogador-servidor e tomar as medidas apropriadas (expulsar/banir o jogador, 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.");
    }
}

O script acima compara o tempo do jogo com o tempo do computador (sistema). Normalmente ambos os tempos são atualizados na mesma taxa (assumindo que Time.timeScale está definido como 1), mas quando o SpeedHack é ativado, ele acelera a frequência de atualização no jogo, tornando o in - o tempo do jogo se acumula mais rápido.

Quando a diferença entre os dois tempos se tornar muito grande (neste caso 7 segundos, mas você pode escolher qualquer valor, apenas certifique-se de que não seja muito pequeno para evitar falsos positivos) o script chama o método SpeedhackDetected() que sinaliza a presença do SpeedHack.

Para usar o script, certifique-se de que ele esteja anexado a qualquer objeto na cena.

Varredura de valor

A varredura de valores é um processo de encontrar valores relevantes na memória alocada do jogo e substituí-los por valores diferentes. Mais comumente usado para aumentar a saúde do jogador, a munição da arma ou qualquer valor que daria a um hacker uma vantagem injusta no jogo.

Tecnicamente falando, todos os valores do jogo podem ser substituídos/alterados, mas isso significa que todos eles precisam ser protegidos? Não necessariamente. Geralmente, os hackers novatos visam apenas os valores exibidos na tela e sabem para que são usados ​​(por exemplo, saúde do jogador, munição, etc.). Portanto, na maioria das vezes, apenas valores "exposed" precisam ser protegidos.

Captura de tela do jogo Unity FPS

Por exemplo, na captura de tela acima, cada valor na tela é um alvo potencial para hackers.

Portanto, a questão é: como proteger os valores importantes contra um ataque de varredura de valor? A resposta é Ofuscação.

Ofuscação é a ação de tornar algo obscuro, pouco claro ou ininteligível.

Há muitas maneiras de ofuscar uma variável, mas usarei um método que chamo de Randomizer. O valor aleatório é gerado no início, depois o valor real é subtraído dele (posteriormente ocultando-o) e, quando necessário, o valor oculto é subtraído de um valor aleatório gerado, com a diferença sendo o número original. O segredo é fazer com que um valor exibido na tela tenha um valor completamente diferente da variável, levando os hackers a um caminho completamente errado durante a varredura.

  • Crie um novo script, chame-o de 'SC_Obf' e cole o código abaixo dentro dele:

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

O script acima será usado para gerar um número aleatório e 2 métodos simples para ofuscar e desofuscar os valores.

  • Agora vamos passar para um exemplo normal de script sem qualquer ofuscação:
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");
    }
}

O script acima contém 2 variáveis ​​simples: saúde (float) e munição (int). Ambas as variáveis ​​são exibidas na tela:

Essa maneira de fazer as coisas é simples e conveniente em termos de manutenção, mas os hackers poderão facilmente escanear os valores e substituí-los usando o Cheat Engine ou software semelhante.

  • Aqui está o mesmo script, mas usando métodos de ofuscação do '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");
    }
}

Em vez de inicializar variáveis ​​de saúde e munição diretamente, nós as inicializamos no início em void Awake() (certifique-se de chamar SC_Obf.Initialize() antes de atribuir os valores usando SC_Obf.Obfuscate(value)).

Então, ao exibir os valores, nós os desofuscamos instantaneamente chamando SC_Obf.Deobfuscate(value), exibindo assim os valores reais.

O hacker tentaria procurar por 100 e 30, mas não seria capaz de encontrá-los porque os valores reais são completamente diferentes.

Para manipular os valores ofuscados (por exemplo, subtraindo saúde), primeiro desofuscamos o valor, depois subtraímos o valor necessário e ofuscamos o resultado final de volta.

Para uma solução mais avançada, sinta-se à vontade para verificar este Asset Store Pacote.

Artigos sugeridos
Introdução à linguagem de script Unity C#
Métodos no início do tempo de execução que inicializam valores no Unity
Como reproduzir arquivos de vídeo no Unity
Como alterar a resolução da tela no jogo Unity
Rotação no local na unidade
Criando um sistema de marcadores 2D simples no Unity
Um guia para carregar cenas no Unity