Prevenir el engaño multijugador

10

Estoy casi completo desarrollando un pequeño juego multijugador de estilo indie. Si bien tengo la intención de permitir que las personas hagan trampa en un solo jugador, esto obviamente no es aceptable en multijugador. ¿Alguien sabe de alguna manera de ayudar a evitar que el Joe promedio use algo como Cheat-Engine para modificar partes del juego? Actualmente planeo que el cliente cargue un hash MD5 de cada archivo de configuración que el juego usa (almacenado como un XML) en el servidor del juego para su verificación cada pocos segundos, pero ¿hay algo que pueda hacer para detener cosas como editores de memoria, etc. ?

Usuario093203920
fuente
2
Recomendaría este artículo, Construyendo juegos multijugador: la seguridad está escrita para algunas API multijugador, pero las ideas son buenas y aún se aplican
Cyral

Respuestas:

8

Si le preocupa el código modificado localmente, ¿cómo puede estar seguro de que alguien no ha modificado simplemente su código de notificación para enviar una lista estática de hash MD5, los mismos que espera? De hecho, ni siquiera necesita modificar el código para hacer esto, solo necesita un proxy bastante básico (suponiendo que no tenga SSL, pero incluso eso podría ser falsificado con un poco más de esfuerzo).

La única forma de hacer lo que quiere es tener un servidor y simplemente no confiar en el cliente. Todos los cálculos deben manejarse en el servidor y todas las acciones deben verificarse como al menos algo posible. Por ejemplo, no permita que el cliente diga que quiere moverse a un lado del mapa cuando sabe que estaba en el otro lado hace un momento. Sin un servidor en el medio haciendo todo lo que es vital para el juego, es imposible no hacer trampa, porque alguien inteligente siempreencuentre una forma de evitar cualquier cosa que pueda incorporar al cliente. Incluso con uno, todavía es posible si no piensa en todas las diferentes formas de manipular la situación ligeramente. Por ejemplo, la validación de movimiento que mencioné antes: si haces un cálculo simple punto a punto, las personas aún podrán teletransportarse a través de las paredes.

Entonces la pregunta es, ¿qué tan promedio es 'Joe promedio'? Ya has mencionado la edición de código y los editores de memoria. Eso está por encima de lo que yo personalmente consideraría el nivel promedio, y si desea preocuparse por ese nivel, se requiere un servidor de confianza separado que haga todo el trabajo pesado y el cliente se reducirá esencialmente a dispositivos de visualización y entrada.

Matthew Scharley
fuente
2
@ user185812: Por lo general, es una buena idea esperar al menos unas horas antes de marcar una respuesta aceptada. Si bien personalmente creo que mi respuesta es bastante buena (soy parcial), es probable que otras tengan más información y ver una respuesta aceptada a menudo es un disuasivo para que otros respondan.
Matthew Scharley
@MatthewScharley: no te preocupes. ;)
Martin Sojka
11

El cliente está en manos del enemigo. ( Las leyes del diseño del mundo en línea )

Realmente, la única forma de vencer a la mayoría de los tramposos es hacer que el cliente sea un "cliente ligero", es decir: actuar solo como un dispositivo de entrada y salida, y nunca darle más información de la que precisa.

Esto no detendrá la automatización y esto no detendrá la recopilación y el análisis pasivo de información, pero puede diseñar su juego de manera que no tenga un impacto significativo.

Esto no impedirá que la gente se piratee entre sí a través de mensajes mal formados confiados por el servidor: su cliente debe protegerse contra los mensajes del servidor de la misma manera que protegería sus sitios web de los ataques de inyección SQL.

Dado que también desea usar el mismo cliente para el juego de un jugador, una solución sería ejecutar un servidor local en un proceso / hilo separado y tratarlo internamente como una configuración de cliente / servidor. Los "trucos" funcionarían en el lado del servidor. Minecraft hace algo similar, aunque de ninguna manera es el primer juego en separar el motor del juego de su interfaz de esa manera.

Lectura sugerida:

Martin Sojka
fuente
2

En un juego multijugador básico, hacer trampa en el tipo de Cheat-Engine simplemente no funcionará. Los clientes solo envían los datos y las acciones para las que lo diseñó. Por lo general, eso no es mucho más de lo que el jugador "hizo", por ejemplo, en qué dirección está corriendo, si está disparando, etc. Por lo tanto, los cambios que realiza en la memoria solo afectarán su propio juego, pero los otros jugadores no verán ningún cambio, un llamado desincronización. La mayoría de los juegos detectan desincronizaciones así y eliminan del juego al jugador desechado.

Ahora también hay otras formas de hacer trampa, pero se trata de cómo está diseñado tu juego.

Para protegerse de los hacks más fáciles, que son los mensajes de red falsos, el servidor debe verificar la integridad de esos paquetes. "¿Ese tipo acaba de saltar 5 pantallas? Eso es imposible, negar el paquete". (Tenga en cuenta que también puede ir a la ruta totalmente sincronizada, lo que significa que todo está sincronizado y solo "Qué botones presionó el reproductor", se envían un tipo de mensajes, lo que hace que los mensajes de red falsos sean inútiles por diseño).

La última forma de hacer trampa en el modo multijugador son los hacks de visibilidad, es decir, modificar el cliente para que muestre datos al jugador que no conoce. Ejemplos de esto no son mostrar la niebla de la guerra, poder mirar a través de las paredes, mostrar un minimapa u otras cosas. Estos son imposibles de prevenir.

API-Bestia
fuente
No estoy de acuerdo con los trucos de visibilidad. ¿No podrían evitarse esto si no le damos información al cliente hasta que su personaje se dé cuenta? No me malinterpreten, esto puede no ser un buen diseño. Pero eso es diferente de ser imposible de prevenir.
xuincherguixe
@xuincherguixe Creo que es imposible en algunas circunstancias. Por ejemplo, ambos clientes están jugando con la misma IP y el mismo puerto. En tal caso, es solo la buena voluntad del cliente lo que le impide leer los datos destinados al otro.
Wodzu
1

Para evitar hacks básicos de Cheat Engine que manipulan los valores de tus variables, entonces debes ocultar esos valores. Por lo general, Cheat Engine se usa para identificar la ubicación de la memoria de variables interesantes (por ejemplo, la cantidad de oro o vida o el nivel de actualización de una habilidad) haciendo una búsqueda del valor conocido de dicha variable, jugar más del juego y hacer que el valor cambiar, entonces Cheat Engine haría una nueva búsqueda a partir del resultado de la búsqueda anterior del nuevo valor. Esto permite que el tramposo amplíe la ubicación de la memoria del valor, ahora puede cambiar el valor de esa ubicación de memoria usando Cheat Engine.

Por ejemplo, tengo 245 GOLD ... con Cheat Engine busco 245 y encuentro muchas ubicaciones de memoria. Luego juego un poco más y llevo mi oro hasta 314, luego busco en la salida de búsqueda anterior el valor 314 y encuentro fácilmente la ubicación de la memoria donde se almacena GOLD.

La forma de evitar esto es nunca tener el valor real almacenado en una ubicación de memoria. Por ejemplo, almaceno el valor en un objeto que tiene que calcular el valor real a pedido cuando es necesario. Entonces, digamos que el jugador tiene 245 ORO. Si realizan una búsqueda de una ubicación de memoria con el valor 245, pueden encontrar muchas, pero ninguna de ellas será la ubicación de la memoria donde realmente se almacena el valor de oro, eso es porque no almacena el valor 245 para el oro. Cuando el juego necesita saber cuánto oro, le preguntará al objeto que tiene el valor, que lo calculará a pedido.

Entonces, la pregunta ahora es: ¿cómo exactamente almacena un valor de una manera que no lo revele? Esto se vuelve un poco complicado y feo, y estoy seguro de que hay muchas maneras de hacerlo. Lo que me gusta hacer es almacenar una matriz booleana (o matriz de bytes). La longitud de la matriz puede ser cualquier cosa, pero digamos que es 13. Luego tienes un contador que representa cuántas veces va 13 a ese valor real. Entonces, si queremos representar 245, entonces el contador tendría un valor de 18. Ahora la matriz tendría todos los valores booleanos establecidos en verdadero para el resto de 245/13 ... básicamente el módulo. En este caso, son 11, por lo que los primeros 11 booleanos en la matriz se establecerían en verdadero, el resto en falso. Para recuperar el valor, todo lo que necesita hacer es multiplicar el contador por la longitud de la matriz, luego agregar 1 para cada conjunto booleano a verdadero (deteniéndose en el primer falso). Ahora, el número 245 nunca se almacenaría en ningún lugar y sería difícil encontrar la ubicación de la memoria que necesitaría manipular para alterar la cantidad de oro. Es posible que desee establecer la longitud de la matriz en diferentes tamaños (tal vez elegir aleatoriamente un número entre un rango razonable) cuando se crea este objeto.

EDITAR: Esto es útil para jugadores múltiples y un jugador. Hay trampas que también se pueden hacer en el modo multijugador, donde los valores en los paquetes pueden alterarse. Esto requeriría diferentes técnicas para prevenir, como firmar cada paquete.

Jose Martinez
fuente
1
Por lo general, para evitar trampas, los juegos multijugador calculan todo en el servidor, por lo que modificar un valor en el cliente, o en un paquete enviado al servidor, no cambia nada en el juego real. Pero aún así, el resto de la respuesta es interesante.
Vaillancourt
@AlexandreVaillancourt Buen punto. Me preocupa empantanar las firmas de cálculo de la CPU del servidor. Quiero mantener el servidor rápido simplemente pasando paquetes entre los dos jugadores, pero lo examinaré de cerca ahora que lo has señalado.
José Martínez
Si solo envía las entradas del cliente al servidor, no necesita firmar cada paquete. Una vez en el servidor, si la entrada no tiene sentido, simplemente son rechazados o el cliente es expulsado por hacer trampa. El servidor calcula el siguiente estado del juego, luego envía el nuevo estado a todos los jugadores, así es como se evita la trampa (no se deshace de bots como este, pero al menos evita las trampas casuales de los jugadores) .
Vaillancourt
1
Para evitar eso, deje que el servidor actualice la nueva vida y luego envíe la nueva vida al cliente. Todo se calcula en el servidor y permite que los clientes simplemente sean "terminales tontos" para todas las cosas importantes: el cliente será responsable de capturar las entradas del jugador ("cliqueado en x, y en el momento T", "presione botón X en el momento T "), enviándolos al servidor y recibiendo el nuevo estado del servidor (" el jugador está ahora en la posición X, Y "," el jugador tiene vida ZZZ ") y mostrándolo al jugador.
Vaillancourt
1
Con esto, el tramposo (hombre en el medio) puede meter todo lo que quiera con los paquetes, no cambiará el estado del juego en el servidor porque el servidor se asegurará de que la entrada sea válida ("hmm, el cliente ha hecho clic en cinco lugares diferentes en los últimos 0.03 segundos, eso no es normal, rechacemos estos clics ") y ejecute toda la simulación en sí.
Vaillancourt