Estoy hablando de un juego de acción sin límite de puntaje superior y sin forma de verificar el puntaje en el servidor al reproducir movimientos, etc.
Lo que realmente necesito es el cifrado más fuerte posible en Flash / PHP, y una forma de evitar que las personas llamen a la página PHP a través de mi archivo Flash. He intentado algunos métodos simples en el pasado de hacer múltiples llamadas para un solo puntaje y completar una secuencia de suma de verificación / fibonacci, etc., y también ofuscar el SWF con Amayeta SWF Encrypt, pero todos fueron pirateados eventualmente.
Gracias a las respuestas de StackOverflow, ahora he encontrado más información de Adobe: http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.html y https://github.com/mikechambers/as3corelib , que creo que puede usar para el cifrado. Sin embargo, no estoy seguro de que esto me lleve a CheatEngine.
Necesito conocer las mejores soluciones para AS2 y AS3, si son diferentes.
Los principales problemas parecen ser cosas como los encabezados TamperData y LiveHTTP, pero entiendo que también hay herramientas de piratería más avanzadas, como CheatEngine (gracias Mark Webster)
Respuestas:
Este es un problema clásico con los juegos y concursos de Internet. Su código Flash funciona con los usuarios para decidir una puntuación para un juego. Pero los usuarios no son de confianza, y el código Flash se ejecuta en la computadora del usuario. Eres SOL No hay nada que puedas hacer para evitar que un atacante forje puntuaciones altas:
Flash es aún más fácil de realizar ingeniería inversa de lo que podría pensar, ya que los códigos de bytes están bien documentados y describen un lenguaje de alto nivel (Actionscript) --- cuando publica un juego Flash, está publicando su código fuente, ya sea que Lo se o no.
Los atacantes controlan la memoria de tiempo de ejecución del intérprete de Flash, de modo que cualquiera que sepa cómo usar un depurador programable puede alterar cualquier variable (incluida la puntuación actual) en cualquier momento, o alterar el programa en sí.
El ataque más simple posible contra su sistema es ejecutar el tráfico HTTP para el juego a través de un proxy, capturar el puntaje más alto guardado y reproducirlo con un puntaje más alto.
Puede intentar bloquear este ataque vinculando cada puntaje alto guardado a una sola instancia del juego, por ejemplo, enviando un token cifrado al cliente al inicio del juego, que podría verse así:
(También puede usar una cookie de sesión para el mismo efecto).
El código del juego devuelve este token al servidor con el guardado de puntaje alto. Pero un atacante aún puede iniciar el juego nuevamente, obtener una ficha y luego pegarla inmediatamente en una partida guardada de puntaje repetido.
Entonces, a continuación, alimenta no solo un token o una cookie de sesión, sino también una clave de sesión de cifrado de alta puntuación. Esta será una clave AES de 128 bits, encriptada con una clave codificada en el juego Flash:
Ahora, antes de que el juego publique la puntuación más alta, descifra la clave de sesión de cifrado de alta puntuación, lo que puede hacer porque codificó la clave de sesión de clave de cifrado de alta puntuación en el binario Flash. Cifras la puntuación más alta con esta clave descifrada, junto con el hash SHA1 de la puntuación más alta:
El código PHP en el servidor verifica el token para asegurarse de que la solicitud provenga de una instancia de juego válida, luego descifra el puntaje alto encriptado, verificando que el puntaje alto coincida con el SHA1 del puntaje alto (si omite este paso , el descifrado simplemente producirá puntajes aleatorios, probablemente muy altos, altos).
Entonces, el atacante descompila su código Flash y rápidamente encuentra el código AES, que sobresale como un pulgar dolorido, aunque incluso si no fuera así, sería rastreado en 15 minutos con una búsqueda de memoria y un rastreador ("Lo sé mi puntaje para este juego es 666, así que busquemos 666 en la memoria, luego capturemos cualquier operación que toque ese valor --- ¡mira, el código de cifrado de puntaje alto! "). Con la clave de sesión, el atacante ni siquiera tiene que ejecutar el código Flash; ella toma una ficha de inicio del juego y una clave de sesión y puede enviar una puntuación alta arbitraria.
Ahora estás en el punto en que la mayoría de los desarrolladores simplemente se dan por vencidos --- da o toma un par de meses jugando con los atacantes al:
Encriptando las teclas AES con operaciones XOR
Reemplazar matrices de bytes de clave con funciones que calculan la clave
Dispersión de cifrados de claves falsas y publicaciones de alta puntuación en todo el binario.
Todo esto es principalmente una pérdida de tiempo. No hace falta decir que SSL tampoco te ayudará; SSL no puede protegerlo cuando uno de los dos puntos finales SSL es malo.
Aquí hay algunas cosas que realmente pueden reducir el fraude de puntaje alto:
Solicite un inicio de sesión para jugar, haga que el inicio de sesión produzca una cookie de sesión y no permita múltiples lanzamientos de juegos pendientes en la misma sesión o múltiples sesiones simultáneas para el mismo usuario.
Rechace las puntuaciones altas de las sesiones de juego que duran menos que los juegos reales más cortos jamás jugados (para un enfoque más sofisticado, intente "poner en cuarentena" las puntuaciones altas para las sesiones de juego que duran menos de 2 desviaciones estándar por debajo de la duración media del juego). Asegúrate de estar rastreando las duraciones del juego en el servidor.
Rechace o ponga en cuarentena los puntajes más altos de los inicios de sesión que solo han jugado el juego una o dos veces, de modo que los atacantes tengan que producir un "rastro de papel" de juego de aspecto razonable para cada inicio de sesión que creen.
"Heartbeat" puntúa durante el juego, para que su servidor vea el aumento de la puntuación durante la vida de un juego. Rechazar puntajes altos que no siguen curvas de puntaje razonables (por ejemplo, saltar de 0 a 999999).
Estado del juego "Instantánea" durante el juego (por ejemplo, cantidad de municiones, posición en el nivel, etc.), que luego puede conciliar con los puntajes provisionales registrados. Ni siquiera tiene que tener una forma de detectar anomalías en estos datos para comenzar; solo tienes que recogerlo, y luego puedes volver y analizarlo si las cosas se ven sospechosas.
Inhabilite la cuenta de cualquier usuario que falle en una de sus comprobaciones de seguridad (por ejemplo, al enviar una puntuación alta encriptada que falla la validación).
Sin embargo, recuerde que aquí solo está disuadiendo el fraude de alta puntuación. No hay nada que puedas hacer para evitarlo. Si hay dinero en juego en tu juego, alguien derrotará cualquier sistema que se te ocurra. El objetivo no es detener este ataque; es hacer que el ataque sea más costoso que simplemente ser realmente bueno en el juego y vencerlo.
fuente
Puede que te estés haciendo la pregunta equivocada. Pareces concentrado en los métodos que las personas están usando para ascender en la lista de puntajes altos, pero bloquear métodos específicos solo llega hasta cierto punto. No tengo experiencia con TamperData, así que no puedo hablar de eso.
La pregunta que debe hacerse es: "¿Cómo puedo verificar que las puntuaciones enviadas sean válidas y auténticas? La forma específica de hacerlo depende del juego. Para juegos de rompecabezas muy simples, puede enviar la puntuación junto con el estado inicial específico y la secuencia de movimientos que dieron como resultado el estado final, y luego volver a ejecutar el juego en el lado del servidor utilizando los mismos movimientos. Confirme que el puntaje indicado es el mismo que el puntaje calculado y solo acepte el puntaje si coinciden.
fuente
Una manera fácil de hacer esto sería proporcionar un hash criptográfico de su valor de puntaje alto junto con el puntaje mismo. Por ejemplo, al publicar los resultados a través de HTTP GET: http://example.com/highscores.php?score=500&checksum=0a16df3dc0301a36a34f9065c3ff8095
Al calcular esta suma de verificación, se debe usar un secreto compartido; este secreto nunca debe transmitirse a través de la red, sino que debe codificarse tanto en el backend de PHP como en la interfaz flash. La suma de comprobación anterior se creó anteponiendo la cadena " secreto " a la puntuación " 500 " y ejecutándola a través de md5sum.
Aunque este sistema evitará que un usuario publique puntajes arbitrarios, no evita un "ataque de repetición", en el que un usuario vuelve a publicar un puntaje previamente calculado y una combinación hash. En el ejemplo anterior, una puntuación de 500 siempre produciría la misma cadena hash. Parte de este riesgo puede mitigarse incorporando más información (como un nombre de usuario, marca de tiempo o dirección IP) en la cadena que se va a codificar. Aunque esto no impedirá la reproducción de datos, asegurará que un conjunto de datos solo sea válido para un solo usuario a la vez.
Para evitar cualquier ataques de repetición se produzca, algún tipo de sistema de desafío-respuesta tendrá que ser creado, tales como los siguientes:
Tenga en cuenta que la seguridad de cualquiera de las técnicas anteriores se ve comprometida si el usuario puede acceder al secreto compartido.
Como alternativa, algo de esto podría evitarse forzando al cliente a comunicarse con el servidor a través de HTTPS y asegurándose de que el cliente esté preconfigurado para confiar solo en los certificados firmados por una autoridad de certificación específica a la que usted solo tiene acceso. .
fuente
Me gusta lo que dijo tpqf, pero en lugar de deshabilitar una cuenta cuando se descubren trampas, implemente un honeypot para que cada vez que inicien sesión, vean sus puntajes pirateados y nunca sospechen que han sido marcados como un troll. Google para "phpBB MOD Troll" y verá un enfoque ingenioso.
fuente
En la respuesta aceptada, tqbf menciona que puede hacer una búsqueda de memoria para la variable de puntuación ("Mi puntuación es 666, así que busco el número 666 en la memoria").
Hay una forma de evitar esto. Tengo una clase aquí: http://divillysausages.com/blog/safenumber_and_safeint
Básicamente, tiene un objeto para almacenar su puntaje. En el setter, multiplica el valor que le pasa con un número aleatorio (+ y -), y en el getter divide el valor guardado por el multiplicador aleatorio para recuperar el original. Es simple, pero ayuda a detener la búsqueda de memoria.
Además, mira el video de algunos de los chicos detrás del motor PushButton que hablan sobre algunas de las diferentes formas en que puedes combatir el pirateo: http://zaa.tv/2010/12/the-art-of-hacking-flash- juegos / . Ellos fueron la inspiración detrás de la clase.
fuente
Hice una especie de solución alternativa ... Tuve un dado donde los puntajes aumentaron (siempre obtienes +1 puntaje). Primero, comencé a contar desde un número aleatorio (digamos 14) y cuando visualizo los puntajes, solo mostraba los puntajes var menos 14. Esto fue así si los crackers están buscando, por ejemplo, 20, no lo encontrarán (se será 34 en la memoria). En segundo lugar, como sé cuál debería ser el siguiente punto ... Usé adobe crypto library para crear el hash de cuál debería ser el siguiente punto.. Cuando tengo que incrementar los puntajes, verifico si el hash de los puntajes incrementados es igual al hash. Si el cracker ha cambiado los puntos en la memoria, los hashes no son iguales. Realizo algunas verificaciones del lado del servidor y cuando obtuve diferentes puntos del juego y del PHP, sé que hubo trampa. Aquí hay un fragmento de mi código (estoy usando Adobe Crypto libraty clase MD5 y sal de criptografía aleatoria. CallPhp () es mi validación del lado del servidor)
Usando esta técnica + ofuscación SWF, pude detener las galletas. Además, cuando envío las puntuaciones al lado del servidor, uso mi propia función pequeña de cifrado / descifrado. Algo como esto (código del lado del servidor no incluido, pero puede ver el algoritmo y escribirlo en PHP):
Luego envío la variable entre otras falsificaciones y simplemente se pierde en el camino ... Es mucho trabajo para un pequeño juego flash, pero cuando se trata de premios, algunas personas simplemente se vuelven codiciosas. Si necesita ayuda, escríbame un PM.
Saludos, Ico
fuente
Cifrar usando una clave reversible (privada) conocida sería el método más simple. No estoy tan al tanto de AS, así que no estoy seguro de qué tipo de proveedores de cifrado hay.
Pero podría incluir variables como la duración del juego (cifrada, de nuevo) y un recuento de clics.
Todas estas cosas pueden ser de ingeniería inversa, así que considere incluir un montón de datos basura para dejar a la gente fuera del alcance.
Editar: También podría valer la pena tirar en algunas sesiones de PHP. Inicie la sesión cuando hagan clic en iniciar juego y (como dice el comentario de esta publicación) registre la hora. Cuando envían el puntaje, puedes comprobar que realmente tienen un juego abierto y que no están enviando un puntaje demasiado pronto o demasiado grande.
Puede valer la pena elaborar un escalar para ver cuál es la puntuación máxima por segundo / minuto de juego.
Ninguna de estas cosas es inevitable, pero ayudará tener algo de lógica que no esté en Flash, donde la gente pueda verla.
fuente
En mi experiencia, esto se aborda mejor como un problema de ingeniería social que como un problema de programación. En lugar de centrarse en hacer que sea imposible hacer trampa, concéntrese en hacerlo aburrido eliminando los incentivos para hacer trampa. Por ejemplo, si el incentivo principal son las puntuaciones altas visibles públicamente, simplemente retrasar cuando se muestran las puntuaciones altas puede reducir significativamente las trampas al eliminar el ciclo de retroalimentación positiva para los tramposos.
fuente
No puede confiar en ningún dato que devuelva el cliente. La validación debe realizarse en el lado del servidor. No soy un desarrollador de juegos, pero hago software de negocios. En ambos casos, el dinero puede estar involucrado y las personas romperán las técnicas de ofuscación del lado del cliente.
Tal vez envíe datos al servidor periódicamente y realice alguna validación. No se concentre en el código del cliente, incluso si allí es donde vive su aplicación.
fuente
Siempre que su sistema de puntaje alto se base en el hecho de que la aplicación Flash envía datos de puntaje alto no encriptados / sin firmar a través de la red, estos pueden ser interceptados y manipulados / reproducidos. La respuesta se deduce de eso: cifrar (¡decentemente!) O firmar criptográficamente datos de puntaje alto. Esto, al menos, hace que sea más difícil para las personas descifrar su sistema de puntaje alto porque necesitarán extraer la clave secreta de su archivo SWF. Mucha gente probablemente se rendirá allí mismo. Por otro lado, todo lo que se necesita es una persona individual para extraer la clave y publicarla en algún lugar.
Las soluciones reales implican una mayor comunicación entre la aplicación Flash y la base de datos de puntaje alto para que este último pueda verificar que un puntaje dado sea algo realista. Esto probablemente sea complicado dependiendo del tipo de juego que tengas.
fuente
No hay forma de hacerlo completamente inquebrantable, ya que es fácil descompilar SWF, y un hacker desarrollador experto podría rastrear su código y descubrir cómo evitar cualquier sistema encriptado que pueda emplear.
Sin embargo, si simplemente desea evitar que los niños hagan trampa mediante el uso de herramientas simples como TamperData, podría generar una clave de cifrado que pasará al SWF al inicio. Luego use algo como http://code.google.com/p/as3crypto/ para cifrar la puntuación más alta antes de pasarla nuevamente al código PHP. Luego descifrarlo en el extremo del servidor antes de almacenarlo en la base de datos.
fuente
Estás hablando de lo que se llama el problema de "confianza del cliente". Debido a que el cliente (en este efectivo, un SWF que se ejecuta en un navegador) está haciendo algo para lo que está diseñado. Ahorre un puntaje alto.
El problema es que desea asegurarse de que las solicitudes de "guardar puntaje" provengan de su película flash, y no de alguna solicitud HTTP arbitraria. Una posible solución para esto es codificar un token generado por el servidor en el SWF en el momento de la solicitud (mediante flash ) que debe acompañar a la solicitud para guardar una puntuación alta. Una vez que el servidor guarda ese puntaje, el token expira y ya no se puede usar para solicitudes.
La desventaja de esto es que un usuario solo podrá enviar una puntuación alta por carga de la película flash: debe obligarlos a actualizar / recargar el SWF antes de que puedan volver a jugar para obtener una nueva puntuación.
fuente
Normalmente incluyo "datos fantasma" de la sesión del juego con la entrada de puntaje más alto. Entonces, si estoy haciendo un juego de carreras, incluyo los datos de repetición. A menudo ya tienes los datos de repetición para la funcionalidad de repetición o la funcionalidad de carrera de fantasmas (jugando contra tu última carrera o contra el fantasma del tipo # 14 en la tabla de clasificación).
Verificar esto es un trabajo muy manual, pero si el objetivo es verificar si las 10 entradas principales en un concurso son legítimas, esto puede ser una adición útil al arsenal de medidas de seguridad que otros ya han señalado.
Si el objetivo es mantener la lista de puntajes altos en línea hasta el final de los tiempos sin que nadie tenga que mirarlos, esto no le traerá mucho.
fuente
La forma en que lo hace un nuevo mod de arcade popular es que envía datos desde el flash a php, de regreso a flash (o lo recarga), luego de vuelta a php. Esto le permite hacer cualquier cosa que desee para comparar los datos, así como omitir los hacks de descifrado / datos de publicación y similares. Una forma de hacerlo es asignando 2 valores aleatorios de php al flash (que no puede capturar ni ver incluso si ejecuta un capturador de datos flash en tiempo real), utilizando una fórmula matemática para agregar el puntaje con los valores aleatorios y luego verificarlo usando la misma fórmula para revertirlo y ver si la puntuación coincide cuando finalmente llega al php al final. Estos valores aleatorios nunca son visibles, así como también veces la transacción que tiene lugar y si '
Esta parece una solución bastante buena si me preguntas, ¿alguien ve algún problema con el uso de este método? ¿O posibles formas de evitarlo?
fuente
Creo que la forma más sencilla sería hacer llamadas a una función como RegisterScore (puntaje) cada vez que el juego registra un puntaje para agregarlo y luego codificarlo, empaquetarlo y enviarlo a un script php como una cadena. El script php sabría cómo decodificarlo correctamente. Esto detendría cualquier llamada directa al script php ya que cualquier intento de forzar una puntuación daría como resultado un error de descompresión.
fuente
Solo es posible manteniendo la lógica de todos los juegos en el lado del servidor, que también almacena la puntuación internamente sin el conocimiento del usuario. Por razones económicas y científicas, la humanidad no puede aplicar esta teoría a todos los tipos de juegos, excepto por turnos. Por ejemplo, mantener la física en el lado del servidor es computacionalmente costoso y difícil de responder como la velocidad de la mano. Incluso es posible, mientras juega ajedrez cualquiera puede igualar el juego de ajedrez AI con el oponente. Por lo tanto, los mejores juegos multijugador también deben contener creatividad a pedido.
fuente
Realmente no es posible lograr lo que quieres. Las partes internas de la aplicación Flash siempre están parcialmente accesibles, especialmente cuando sabes cómo usar cosas como CheatEngine , lo que significa que no importa cuán seguras sean las comunicaciones de tu sitio web y del navegador <-> del servidor, aún será relativamente fácil de superar.
fuente
Puede ser una buena idea comunicarse con el backend a través de AMFPHP . Debería desalentar al menos a los perezosos de tratar de impulsar los resultados a través de la consola del navegador.
fuente