trivia - Haciendo un juego a prueba de truco en Javascript
test en javascript (13)
¿Hay alguna manera fundamental de proteger a las personas de este tipo de cosas mediante el diseño de su código de juego de cierta manera?
El único método sensato es mantener fragmentos críticos del código en los servidores que controlas y nunca entregarlos a las computadoras de los usuarios. La parte difícil es hacer que esto cuadre con mantener el juego lo suficientemente rápido como para ser jugable.
Supongamos que creó un juego en línea en HTML5 / JavaScript. Todo el código se descargaría en el navegador de los usuarios y ejecutarían el juego.
¿Qué impide que alguien copie el juego en su computadora e inyecta funciones y módulos para hacer trampa? Por ejemplo, podrían escribir una función que apunta automáticamente al sprite enemigo más cercano, por ejemplo.
¿Hay alguna manera fundamental de proteger a las personas de este tipo de cosas mediante el diseño de su código de juego de cierta manera?
¿Qué impide que alguien copie el juego en su computadora e inyecta funciones y módulos para hacer trampa?
Nada.
¿Hay alguna manera fundamental de proteger a las personas de este tipo de cosas mediante el diseño de su código de juego de cierta manera?
Nop.
Algunos pensamientos
Lado del servidor:
Almacene el lado del servidor de estado interno del juego y verifique la entrada enviada por los clientes en el servidor.
Autoaim : Crea sprites falsos que son invisibles para los jugadores normales, si los golpeas con demasiada frecuencia tienes un bot. (no siempre funcionará, ya que los bots pueden actualizarse para verificar la invisibilidad)
verifique el tiempo de reacción del cliente a los cambios en el servidor, verifique demasiadas reacciones demasiado rápidas. (tiene que aceptar una gran cantidad de respuestas rápidas antes de reaccionar como un humano podría reaccionar rápidamente y el tiempo tiene que dar cuenta de la demora de la red para atrapar cualquier cosa). Dale al jugador un tipo de captcha, un jugador regular nunca lo vería.
Lado del cliente:
utilice la ofuscación para dificultar la interfaz con su código
verifica las funciones definidas en los hacks que conoces. Tiene que ser modificado / actualizado a menudo ya que los creadores de dichos hacks pueden funcionar alrededor de ellos.
Diseño del juego: haciendo que tu juego sea menos repetitivo, esto hace que sea más difícil escribir herramientas / bots para él.
Actualice al cliente para cambiar partes de su estructura de vez en cuando. Si bien esto no detendrá los robots, tomará trabajo mantenerlos en funcionamiento. Haga que sea transparente para el usuario o disfrácela con una nueva función.
Importante: asegúrese de que la interfaz de su servidor verifique que la entrada del usuario, la ofuscación y las comprobaciones del lado del cliente no ayuden a alguien que escriba su propio cliente.
Creo que el camino a seguir sería escribir al cliente de forma que modifique dinámicamente el código del cliente y verifique el uso del código así creado en el servidor.
Por ejemplo, tener un espacio de nombres como este
window.mynamespace = {
foo : function(){
// some stuff here
},
bar : function(){
// some more stuff here
}
}
que contiene todo su código de cliente y hace que todos sus métodos de servidor requieran un token que es el resultado de una evaluación dinámica previa de la base de código. hacer esto más difícil mediante la redefinición de métodos y el cambio de nombres de métodos. Aquí hay algunos ejemplos de desafíos (esto solo tiene sentido si los desafíos se crean dinámicamente y no son predecibles). Todos contienen primero una tarea y luego un desafío que se usará para crear el token de autorización para la siguiente solicitud. (Estos son objetos de respuesta de las llamadas ajax). Básicamente, la tarea será evaluada y el resultado del desafío evaluado será el próximo token.
{
task: "mynamespace.baz=mynamespace.foo;mynamespace.foo=undefined;",
challenge: "mynamespace[11].toString().substr(10,22)"
// get part of a well-known functions source code
}
{
task: "mynamespace.bar=function(){ /* new code here */ }",
challenge: "var xy=0;mynamespace.each(function(item){xy+=item.toString().lastIndexOf('';'')}); xy"
// accumulate the last index of a semicolon in all elements
// of the namespace
}
Para superar eso y aún obtener tokens de autorización válidos, el cliente tendría que escribir una capa de emulación de JavaScript completa. Aunque eso se puede hacer, trataré de hacer que el código del servidor cambie de manera fundamental muy a menudo para hacer que esta técnica sea casi imposible (para que la capa de emulación no sepa qué emular).
Estás intentando hacer lo imposible. El mejor consejo que puedo darte es que si planeas persistir en datos como monedas / dinero / oro, niveles, no olvides nunca confiar en el cliente y hacer que haya tanto servidor lógico como sea posible.
Me gusta la pregunta, y si bien es probable que haya mejores respuestas, aquí hay algunas de las que pueden funcionar (o no):
- Ofuscación. Sí, no está garantizado y alguien finalmente puede llegar a él, pero a veces es un dolor de cabeza lidiar con eso.
- Genere el JS con un nuevo token temporal cada vez. Puede templatar el .js que ejecuta el código e insertar un token generado por el servidor que difiere por cada instancia. El token podría ser temporal y podría ser una forma de validar la autenticidad del código
- Probablemente haya alguna manera de determinar la ubicación correcta de la secuencia de comandos que se está ejecutando, pero esto probablemente podría ser falso
En general, es difícil, y todas las sugerencias anteriores se pueden solucionar. Supongo que la clave es hacer que les sea difícil engañar, pero dado que hay trampas para incluso los juegos en modo seguro en línea, será difícil evitar que los juegos JS también sean susceptibles a eso.
Puede poner todo lo que el código llama dentro de un cierre:
(function() {
var cantSeeMe = function() {
// do some game stuff!
};
})();
Fuera del cierre, será muy difícil obtener el código para los "ataques de inyección" (anulando una función en la consola, por ejemplo). Esto no impedirá que alguien reescriba tu código, pero pasar cosas a través de un empaquetador, o incluso el compilador de cierre puede hacer que tu código sea bastante difícil de leer / modificar ... (mira jQuery min
Con todo, CUALQUIER juego que ejecute el lado del cliente es pirateable.
travian ( http://www.travian.us/ ) es un buen ejemplo de un juego de mayor escala que se ejecuta en DHTML y tiene un montón de problemas con el abuso del lado del cliente. La simple instalación de un mono de grasa en Firefox abre una gran puerta a todo tipo de comportamiento de explotación. Dicho esto, parecen mantener el juego algo funcional ya que la mayoría de los exploits parecen girar en torno a la automatización de tareas comunes en el juego y no violaciones directas de la lógica de dominio interno del juego. Tenga en cuenta que este ejemplo está lejos de ejecutarse solo con JS y depende en gran medida de los controles del lado del servidor.
Descargo de responsabilidad : Este es un método terrible y probablemente demasiado esfuerzo de lo que vale.
Supongamos que tiene un método para procesar el código JavaScript antes de enviarlo.
En primer lugar, cada método tiene una variable ident que se adjunta al resultado de cada función (es decir, cada función devolvería {ident:"special code",result:"actual useful function result"}
). También tiene una función testIdent()
que aceptaría el nombre de la función para llamar así como también "datos de prueba" para proporcionarla (si es necesario). El objetivo de testIdent()
sería enviar el identificador devuelto desde dicha función al servidor para su verificación (la idea es que el servidor pueda solicitar una prueba siempre que lo considere apropiado). El identificador de cada función debe ser aleatorizado y registrado especialmente para el usuario especificado antes de ser enviado.
En segundo lugar, antes de que se envíe el código al cliente, el orden de las funciones se asigna de forma aleatoria y los nombres de las funciones se ofuscan en algún elemento aleatorio. De esta forma, no hay forma de que un hacker busque algún identificador de variable en la función x (), ya que se nombrará aleatoriamente. Además, sería otra ventaja si todos los nombres de variables se ofuscan al azar también, solo para agregar un paso más a la complicación y dolores de cabeza de ... bueno ... todos (les dije que este es un método terrible).
Ahora, suponiendo que se tomen los pasos adecuados para garantizar que el código siempre funcione correctamente, los hackers son personas muy inteligentes, y todavía hay formas para que los hackers sigan este código si están lo suficientemente determinados. Al menos, una forma será buscar estructuras de código clave, como una instrucción switch
con un cierto número de elementos, o un ciclo for con x número de instrucciones, etc. Mientras que cada una de estas opciones puede contrarrestarse, por ejemplo, agregando dummy case
declaraciones en los interruptores o un par de bits if(true)
al azar en todo el código, contrarrestar a los piratas informáticos siempre será una batalla constante (y posiblemente una pérdida).
Espero que esto pueda darte algunas ideas. No sé cómo alguien implementaría esto exactamente, pero al menos es una idea.
¡Buena suerte!
podrían escribir una función que se autoajuste en el sprite enemigo más cercano, por ejemplo.
¡Puedes hacer esto incluso para los juegos donde la mayoría de los procesamientos pasan por el lado del servidor! Solo necesita analizar la pantalla lo suficientemente rápido.
Incluso puedes volver a implementar partes del juego AI para tratar de predecir cómo se moverán los bots. No es una tarea fácil si no tienes acceso al código fuente del juego, pero si registras mucho tiempo de juego, puedes aplicar técnicas de aprendizaje automático.
¿Hay alguna manera fundamental de proteger a las personas de este tipo de cosas mediante el diseño de su código de juego de cierta manera?
No olvides que puedes cambiar el juego en sí , no solo cómo se implementa. Por ejemplo, use niveles generados aleatoriamente en lugar de estáticos, use jugadores humanos en lugar de bots, haga que sus arte / sprites sean más complejos, haga más uso del audio, ponga un límite a la velocidad con la que se puede mover el cursor, agregue tiempos de enfriamiento a armas, agregue peligros ocultos, etc.
Esta es la razón por la cual la mayoría de los juegos de JavaScript dependen en gran medida de un estado de servidor , para evitar trampas.
En teoría, estás jugando un juego contra los piratas informáticos. No puedes ganar este juego pero lo haces desafiante.
Mi sugerencia sería utilizar tanta lógica del lado del servidor como sea posible y usar la Ofuscación de JavaScript.
La ofuscación de Javascript hará que sea extremadamente difícil de entender el código, pero aún mejor, le permitirá lanzar varios miles de versiones de su código mientras mantiene la misma base de código.
He usado JScrambler para hacer esto en una ocasión. ¡En lugar de tener que piratear el código de 1 juego, los hackers tendrán que piratear miles de versiones del código! :)
En resumen, no. Sin embargo, puede ofuscar Javascript para hacerlo mucho más difícil.
Para cosas como los puntajes, un usuario podría, en teoría, colocar cualquier puntaje en el guión de su controlador. En este caso, puede usar una sesión y publicarla regularmente en el servidor a través de AJAX.