Evitar trapaças para vários jogadores

10

Estou quase completo desenvolvendo um pequeno jogo multiplayer de estilo indie. Embora eu pretenda permitir que as pessoas trapaceiem no modo single player, isso obviamente não é aceitável no modo multiplayer. Alguém sabe alguma maneira de ajudar o Joe comum a usar algo como o Cheat-Engine para modificar partes do jogo? Atualmente, pretendo que o cliente faça o upload de um hash MD5 de cada arquivo de configuração que o jogo usa (armazenado como XML) no servidor do jogo para verificação a cada poucos segundos, mas há algo que eu possa fazer para interromper coisas como editores de memória etc. ?

Usuário093203920
fonte
2
Eu recomendo este artigo, de construção Jogos de Multijogador - Segurança a sua escrita para alguns API multiplayer, mas as idéias são boas e ainda se aplicam
Cyral

Respostas:

8

Se você está preocupado com o código modificado localmente, como pode ter certeza de que alguém simplesmente não modificou seu código de notificação para enviar uma lista estática de hashes MD5, os mesmos que você espera? Na verdade, você nem precisa de modificação de código para fazer isso, apenas precisa de um proxy bastante básico (assumindo que não há SSL, mas mesmo isso pode ser falsificado com um pouco mais de esforço).

A única maneira de fazer o que você quer é ter um servidor e simplesmente não confiar no cliente. Todos os cálculos devem ser manipulados no servidor e todas as ações verificadas como sendo pelo menos um pouco possíveis. Por exemplo, não permita que o cliente diga que deseja ir para um lado do mapa quando você souber que estava do outro lado há pouco. Sem um servidor no meio fazendo tudo o que é vital para o jogo, é impossível não trapacear, porque alguém inteligente sempreencontre uma maneira de contornar qualquer coisa que você possa criar no cliente. Mesmo com um, ainda é possível se você não pensar em todas as maneiras diferentes de manipular a situação um pouco. Por exemplo, a validação de movimento que mencionei antes: se você fizer um cálculo simples de ponto a ponto, as pessoas ainda poderão se teletransportar através das paredes.

Portanto, a questão é: qual é a média da média de 'Joe'? Você já mencionou a edição de código e os editores de memória. Isso está acima do que eu consideraria pessoalmente o nível médio, e se você quiser se preocupar com esse nível, um servidor confiável separado, que faz todo o trabalho pesado, é necessário e o cliente se resumirá a ser apenas dispositivos de exibição e entrada.

Matthew Scharley
fonte
2
@ user185812: Geralmente, é uma boa ideia aguardar pelo menos algumas horas antes de marcar uma resposta aceita. Embora pessoalmente eu ache a minha resposta muito boa (sou tendenciosa), outras provavelmente terão mais informações, e ver uma resposta aceita muitas vezes é um impedimento para que outras pessoas respondam.
Matthew Scharley
@MatthewScharley - não se preocupe. ;)
Martin Sojka
11

O cliente está nas mãos do inimigo. ( As Leis do Design Mundial Online )

Realmente, a única maneira de vencer a maioria dos truques é fazer com que o cliente seja um "thin client", ou seja: Atuar apenas como um dispositivo de entrada e saída e nunca fornecer mais informações do que precisa.

Isso não interrompe a automação e a coleta e análise passivas de informações, mas você pode projetar seu jogo de modo que não tenha um impacto significativo.

Isso não impedirá que as pessoas se invadam por meio de mensagens malformadas confiadas pelo servidor - seu cliente precisa se proteger contra mensagens do servidor, da mesma forma que você protegeria seus sites contra ataques de injeção de SQL.

Como você também deseja usar o mesmo cliente para o jogo para um jogador, uma solução seria executar um servidor local em um processo / thread separado e tratá-lo internamente como uma configuração de cliente / servidor. Os "truques" funcionariam no lado do servidor. O Minecraft faz algo semelhante, embora não seja o primeiro jogo a dividir o mecanismo de jogo de sua interface dessa maneira.

Leitura sugerida:

Martin Sojka
fonte
2

Em um jogo multiplayer básico, trapacear com o tipo de Cheat-Engine simplesmente não funciona. Os clientes estão enviando apenas os dados e as ações para as quais você os projetou. Geralmente isso não é muito mais do que o que o jogador "fez", por exemplo, em que direção ele está correndo, se está atirando e assim por diante. Portanto, as mudanças que ele faz na memória afetam apenas o seu próprio jogo, mas os outros jogadores não verão nenhuma mudança, a chamada dessincronização. A maioria dos jogos detecta dessincronizações assim e remove o jogador dessincronizado do jogo.

Agora também existem outras maneiras de trapacear, mas essas são todas sobre como o seu jogo foi projetado.

Para se proteger dos hacks mais fáceis, que estão falsificando as mensagens de rede, o servidor deve verificar a integridade desses pacotes. "Esse cara acabou de pular 5 telas? Isso é impossível, negar pacote." (Observe que você também pode seguir a rota totalmente sincronizada - o que significa que tudo está sincronizado e apenas "Quais botões o player pressionou". - tipos de mensagens são enviadas - o que torna as mensagens falsas da rede inúteis por design.)

A última maneira de trapacear no modo multiplayer são os hacks de visibilidade, que modificam o cliente para mostrar dados ao jogador que ele não conhece. Exemplos disso não são o nevoeiro da guerra, a possibilidade de olhar através das paredes, exibir um minimapa ou outras coisas. Isso é impossível de prevenir.

API-Beast
fonte
Eu discordo dos hacks de visibilidade. Isso não poderia ser evitado se você não desse informações ao cliente até que seu personagem estivesse ciente disso? Não me interpretem mal, isso pode não ser um bom design. Mas isso é diferente de ser impossível impedir.
Xuincherguixe
@xuincherguixe Eu acho que é impossível em algumas circunstâncias. Por exemplo, os dois clientes estão jogando no mesmo IP e na mesma porta. Nesse caso, é apenas a boa vontade de um cliente que o impede de ler os dados destinados ao outro.
Wodzu
1

Para evitar hackers básicos do Cheat Engine que manipulam os valores de suas variáveis, você deve ocultar esses valores. Normalmente, o Cheat Engine é usado para identificar a localização da memória de variáveis ​​interessantes (por exemplo, a quantidade de ouro ou a vida ou o nível de atualização de uma habilidade), fazendo uma busca pelo valor conhecido da referida variável, jogando mais do jogo e fazendo com que o valor mudar, o Cheat Engine faria uma nova pesquisa a partir do resultado da pesquisa anterior pelo novo valor. Isso permite que o trapaceiro aumente o zoom na localização da memória do valor, agora eles podem alterar o valor dessa localização de memória usando o Cheat Engine.

Por exemplo, tenho 245 GOLD ... com o Cheat Engine, procuro 245 e encontro muitos locais de memória. Depois jogo um pouco mais e trago meu ouro até 314, depois procuro o valor 314 da saída de pesquisa anterior e encontro facilmente o local da memória onde o GOLD está armazenado.

A maneira de evitar isso é nunca ter o valor real armazenado em um local de memória. Por exemplo, armazeno o valor em um objeto que precisa calcular o valor real sob demanda quando necessário. Então, digamos que o jogador tenha 245 GOLD. Se eles pesquisarem um local de memória com o valor 245, poderão encontrar muitos, mas nenhum deles será o local de memória onde o valor de ouro está realmente armazenado, ou seja, porque você não armazena o valor 245 para ouro. Quando o jogo precisar saber quanto ouro, ele perguntará ao objeto que possui o valor, que o calculará sob demanda.

Portanto, a pergunta agora é: como exatamente você armazena um valor de uma maneira que não o revele? Isso fica um pouco complicado e feio e tenho certeza de que há muitas maneiras de fazer isso. O que eu gosto de fazer é armazenar uma matriz booleana (ou matriz de bytes). O comprimento da matriz pode ser qualquer coisa, mas digamos que seja 13. Então você tem um contador que representa quantas vezes 13 entra nesse valor real. Portanto, se quisermos representar 245, o contador terá um valor de 18. Agora, o array terá todos os booleanos configurados como true pelo restante de 245/13 ... basicamente o módulo. Nesse caso, são 11, portanto, os 11 primeiros booleanos da matriz serão configurados para true, e o restante para false. Para recuperar o valor, tudo o que você precisa fazer é multiplicar o contador pelo comprimento da matriz e adicionar 1 para cada conjunto booleano como true (parando no primeiro false). Agora, o número 245 nunca seria armazenado em nenhum lugar e seria difícil encontrar o local da memória que precisaria ser manipulado para alterar a quantidade de ouro. Convém definir o comprimento da matriz para tamanhos diferentes (talvez escolha um número aleatoriamente entre um intervalo razoável) quando esse objeto for criado.

EDIT: Isso é útil para multiplayer e single player. Há trapaça que também pode ser feita no modo multiplayer, onde os valores nos pacotes podem ser alterados. Isso exigiria diferentes técnicas para impedir, como assinar cada pacote.

Jose Martinez
fonte
1
Normalmente, para evitar trapaças, os jogos multiplayer calculam tudo no servidor, portanto, modificar um valor no cliente ou em um pacote enviado ao servidor não muda nada no jogo real. Mas, ainda assim, o restante da resposta é interessante.
Vaillancourt
@AlexandreVaillancourt Good point. Estou preocupado em atolar as assinaturas de cálculo da CPU do servidor. Quero manter o servidor rápido, apenas passando pacotes entre os dois jogadores, mas examinarei mais de perto agora que você apontou.
Jose Martinez
Se você enviar apenas as entradas do cliente para o servidor, não precisará assinar todos os pacotes. Uma vez no servidor, se a entrada não faz sentido, eles são simplesmente rejeitados ou o cliente é expulso por trapaça. O servidor calcula o próximo estado do jogo e envia o novo estado a todos os jogadores. É assim que a trapaça é evitada (você não se livra de bots como esse, mas pelo menos evita trapaça ocasional dos jogadores) .
Vaillancourt
1
Para evitar isso, você deixa o servidor atualizar a nova vida e envia a nova vida para o cliente. Tudo é calculado no servidor e deixe que os clientes sejam "terminais burros" para todas as coisas importantes: o cliente será responsável por capturar as entradas do player ("clicou em x, y no tempo T", "aperte botão X no momento T "), enviando-os para o servidor e recebendo o novo estado do servidor (" o jogador agora está na posição X, Y "," o jogador tem vida útil ZZZ ") e exibindo-o ao jogador.
Vaillancourt
1
Com isso, o trapaceiro (homem do meio) pode bagunçar tudo o que quiser com os pacotes; ele não mudará o estado do jogo no servidor porque o servidor garantirá que a entrada seja válida ("hmm, o cliente clicou em cinco locais diferentes nos últimos 0,03 segundos, isso não é normal, vamos rejeitar esses cliques ") e executar toda a simulação em si.
Vaillancourt