212 votes

Quel est le meilleur moyen d'empêcher les gens de pirater la table des scores élevés basée sur PHP d'un jeu Flash ?

Je parle d'un jeu d'action sans limite supérieure de score et sans possibilité de vérifier le score sur le serveur en rejouant les mouvements, etc.

Ce dont j'ai vraiment besoin, c'est du cryptage le plus fort possible en Flash/PHP, et d'un moyen d'empêcher les gens d'appeler la page PHP autrement que par mon fichier Flash. J'ai essayé quelques méthodes simples dans le passé, en faisant plusieurs appels pour un seul score et en complétant une somme de contrôle / une séquence de fibonacci, etc., et aussi en obscurcissant le SWF avec Amayeta SWF Encrypt, mais elles ont toutes été piratées par la suite.

Grâce aux réponses de StackOverflow, j'ai trouvé plus d'informations auprès d'Adobe. http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.html y https://github.com/mikechambers/as3corelib - que je pense pouvoir utiliser pour le cryptage. Mais je ne suis pas sûr que cela me permette de contourner CheatEngine.

J'ai besoin de connaître les meilleures solutions pour AS2 et AS3, si elles sont différentes.

Les principaux problèmes semblent être des choses comme les en-têtes TamperData et LiveHTTP, mais je crois savoir qu'il existe également des outils de piratage plus avancés, comme CheatEngine (merci Mark Webster).

414voto

tqbf Points 6629

C'est un problème classique des jeux et concours sur Internet. Votre code Flash travaille avec les utilisateurs pour décider du score d'un jeu. Mais les utilisateurs ne sont pas dignes de confiance et le code Flash s'exécute sur l'ordinateur de l'utilisateur. Vous êtes SOL. Il n'y a rien que vous puissiez faire pour empêcher un attaquant de falsifier des scores élevés :

  • Flash est encore plus facile à désosser que vous ne le pensez, car les bytecodes sont bien documentés et décrivent un langage de haut niveau (Actionscript) --- lorsque vous publiez un jeu Flash, vous publiez votre code source, que vous le sachiez ou non.

  • Les attaquants contrôlent la mémoire d'exécution de l'interpréteur Flash, de sorte que toute personne sachant utiliser un débogueur programmable peut modifier n'importe quelle variable (y compris le score actuel) à tout moment, ou modifier le programme lui-même.

L'attaque la plus simple contre votre système consiste à faire passer le trafic HTTP du jeu par un proxy, à récupérer la sauvegarde du meilleur score et à la rejouer avec un meilleur score.

Vous pouvez essayer de bloquer cette attaque en liant chaque sauvegarde de score élevé à une seule instance du jeu, par exemple en envoyant un jeton crypté au client au démarrage du jeu, qui pourrait ressembler à ceci :

hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))

(Vous pourriez également utiliser un cookie de session pour le même effet).

Le code du jeu renvoie ce jeton au serveur avec la sauvegarde du meilleur score. Mais un attaquant peut toujours relancer le jeu, obtenir un jeton, puis coller immédiatement ce jeton dans une nouvelle sauvegarde de score élevé.

Ensuite, vous fournissez non seulement un jeton ou un cookie de session, mais aussi une clé de session chiffrant les scores élevés. Il s'agit d'une clé AES de 128 bits, elle-même cryptée avec une clé codée en dur dans le jeu Flash :

hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))

Avant que le jeu n'affiche le meilleur score, il décrypte la clé de session de cryptage du meilleur score, ce qu'il peut faire car vous avez codé en dur la clé de décryptage de la session de cryptage du meilleur score dans le binaire Flash. Vous cryptez le score élevé avec cette clé décryptée, ainsi que le hachage SHA1 du score élevé :

hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))

Le code PHP sur le serveur vérifie le jeton pour s'assurer que la requête provient d'une instance de jeu valide, puis décrypte le score élevé crypté, en vérifiant que le score élevé correspond au SHA1 du score élevé (si vous sautez cette étape, le décryptage produira simplement des scores élevés aléatoires, probablement très élevés).

Ainsi, l'attaquant décompile votre code Flash et trouve rapidement le code AES, qui se distingue comme un pouce endolori, bien que même si ce n'était pas le cas, il serait retrouvé en 15 minutes avec une recherche en mémoire et un traceur ("Je sais que mon score pour ce jeu est de 666, alors trouvons 666 en mémoire, puis attrapons toute opération qui touche cette valeur --- oh regardez, le code de cryptage du score le plus élevé !) Avec la clé de session, l'attaquant n'a même pas besoin d'exécuter le code Flash ; il saisit un jeton de lancement de jeu et une clé de session et peut renvoyer un score élevé arbitraire.

Vous en êtes maintenant au point où la plupart des développeurs abandonnent --- après quelques mois d'efforts pour contrer les attaquants :

  • Brouillage des clés AES avec des opérations XOR

  • Remplacement des tableaux d'octets de clé par des fonctions qui calculent la clé

  • Disperser de fausses clés de chiffrement et des affichages de scores élevés à travers le binaire.

Tout cela n'est qu'une perte de temps. Il va sans dire que le SSL ne vous aidera pas non plus ; le SSL ne peut pas vous protéger si l'un des deux points d'extrémité du SSL est mauvais.

Voici quelques éléments qui peuvent réellement réduire la fraude au score élevé :

  • Exigez une connexion pour jouer au jeu, faites en sorte que la connexion produise un cookie de session, et n'autorisez pas plusieurs lancements de jeu en cours sur la même session, ou plusieurs sessions simultanées pour le même utilisateur.

  • Rejetez les scores élevés des sessions de jeu dont la durée est inférieure à celle des parties réelles les plus courtes jamais jouées (pour une approche plus sophistiquée, essayez de "mettre en quarantaine" les scores élevés des sessions de jeu dont la durée est inférieure de 2 écarts types à la durée moyenne des parties). Assurez-vous que vous suivez la durée des parties sur le serveur.

  • Rejetez ou mettez en quarantaine les scores élevés des connexions qui n'ont joué au jeu qu'une ou deux fois, de sorte que les attaquants doivent produire une "trace écrite" d'un jeu d'apparence raisonnable pour chaque connexion qu'ils créent.

  • Les scores "en cœur" pendant le jeu, de sorte que votre serveur voit la croissance du score au cours de la durée d'une partie. Rejetez les scores élevés qui ne suivent pas des courbes de score raisonnables (par exemple, un saut de 0 à 999999).

  • des "instantanés" de l'état du jeu pendant la partie (par exemple, la quantité de munitions, la position dans le niveau, etc.), que vous pouvez ensuite rapprocher des scores intermédiaires enregistrés. ), que vous pouvez ensuite rapprocher des scores intermédiaires enregistrés. Il n'est même pas nécessaire de disposer d'un moyen de détecter des anomalies dans ces données pour commencer ; il suffit de les collecter, puis de revenir en arrière et de les analyser si les choses semblent suspectes.

  • Désactivez le compte de tout utilisateur qui échoue à l'un de vos contrôles de sécurité (par exemple, en soumettant un score élevé crypté qui échoue à la validation).

N'oubliez pas cependant que vous ne faites que décourager la fraude aux scores élevés. Il y a rien que vous pouvez faire pour prévenir si. S'il y a de l'argent en jeu dans votre jeu, quelqu'un va déjouer tous les systèmes que vous mettez en place. L'objectif n'est pas de arrêter cette attaque ; il s'agit de rendre l'attaque plus coûteuse que le simple fait de devenir très bon au jeu et de le battre.

25voto

Stephen Deken Points 2418

Vous posez peut-être la mauvaise question. Vous semblez vous concentrer sur les méthodes que les gens utilisent pour se frayer un chemin dans la liste des meilleurs scores, mais bloquer des méthodes spécifiques ne va pas plus loin. Je n'ai pas d'expérience avec TamperData, donc je ne peux pas en parler.

La question que vous devriez vous poser est la suivante : "Comment puis-je vérifier que les scores soumis sont valides et authentiques ?". La manière spécifique de le faire dépend du jeu. Pour les jeux de puzzle très simples, vous pouvez envoyer le score ainsi que l'état de départ spécifique et la séquence de mouvements qui a abouti à l'état final, puis relancer le jeu sur le serveur en utilisant les mêmes mouvements. Confirmez que le score indiqué est le même que le score calculé et n'acceptez le score que s'il correspond.

18voto

stormlash Points 827

Une façon simple de le faire serait de fournir un hachage cryptographique de la valeur de votre highscore en même temps que le score lui-même. Par exemple, lors de l'affichage des résultats via HTTP GET : http://example.com/highscores.php?score=500&checksum=0a16df3dc0301a36a34f9065c3ff8095

Lors du calcul de cette somme de contrôle, un secret partagé doit être utilisé ; ce secret ne doit jamais être transmis sur le réseau, mais doit être codé en dur à la fois dans le backend PHP et le frontend Flash. La somme de contrôle ci-dessus a été créée en ajoutant la chaîne " secret "au score " 500 ", et le passer au md5sum.

Bien que ce système empêche un utilisateur de publier des scores arbitraires, il n'empêche pas une "attaque par rejeu", où un utilisateur publie une combinaison de score et de hachage calculée précédemment. Dans l'exemple ci-dessus, un score de 500 produirait toujours la même chaîne de hachage. Une partie de ce risque peut être atténuée en incorporant davantage d'informations (telles qu'un nom d'utilisateur, un horodatage ou une adresse IP) dans la chaîne à hacher. Bien que cela n'empêche pas le rejeu des données, cela permet de s'assurer qu'un ensemble de données n'est valable que pour un seul utilisateur à un seul moment.

Pour éviter tout Pour empêcher les attaques par rejeu, il faudra créer un système de défi-réponse, tel que le suivant :

  1. Le jeu flash ("le client") effectue un HTTP GET de http://example.com/highscores.php sans paramètres. Cette page renvoie deux valeurs : une valeur générée de façon aléatoire. sel et un hachage cryptographique de cette valeur de sel combiné au secret partagé. Cette valeur de sel doit être stockée dans une base de données locale des requêtes en cours, et doit être associée à un horodatage afin qu'elle puisse "expirer" au bout d'une minute peut-être.
  2. Le jeu flash combine la valeur du sel avec le secret partagé et calcule un hachage pour vérifier qu'il correspond à celui fourni par le serveur. Cette étape est nécessaire pour empêcher la falsification des valeurs de sel par les utilisateurs, car elle permet de vérifier que la valeur de sel a bien été générée par le serveur.
  3. Le jeu flash combine la valeur du sel avec le secret partagé, la valeur du meilleur score et toute autre information pertinente (surnom, ip, horodatage), et calcule un hachage. Il renvoie ensuite cette information au backend PHP via HTTP GET ou POST, avec la valeur du sel, le meilleur score et d'autres informations.
  4. Le serveur combine les informations reçues de la même manière que sur le client, et calcule un hash pour vérifier que celui-ci correspond à celui fourni par le client. Il vérifie également que la valeur du sel est toujours valide, comme indiqué dans la liste des requêtes en attente. Si ces deux conditions sont remplies, il écrit le meilleur score dans la table des meilleurs scores et renvoie un message signé de "succès" au client. Il supprime également la valeur du sel de la liste des requêtes en attente.

N'oubliez pas que la sécurité de toutes les techniques ci-dessus est compromise si le secret partagé est accessible à l'utilisateur.

On peut aussi éviter une partie de ce va-et-vient en obligeant le client à communiquer avec le serveur via HTTPS et en s'assurant que le client est préconfiguré pour ne faire confiance qu'aux certificats signés par une autorité de certification spécifique à laquelle vous seul avez accès.

11voto

DGM Points 14007

J'aime ce que tpqf a dit, mais plutôt que de désactiver un compte lorsque la tricherie est découverte, mettez en place un pot de miel de sorte que chaque fois qu'ils se connectent, ils voient leurs scores piratés et ne soupçonnent jamais qu'ils ont été marqués comme un troll. Cherchez sur Google "phpBB MOD Troll" et vous verrez une approche ingénieuse.

4voto

divillysausages Points 5991

Dans la réponse acceptée, tqbf mentionne que vous pouvez simplement faire une recherche en mémoire pour la variable score ("Mon score est 666, je cherche donc le nombre 666 en mémoire").

Il y a un moyen de contourner ce problème. J'ai une classe ici : http://divillysausages.com/blog/safenumber_and_safeint

En gros, vous avez un objet pour stocker votre score. Dans le setter, il multiplie la valeur que vous lui passez avec un nombre aléatoire (+ et -), et dans le getter, vous divisez la valeur enregistrée par le multiplicateur aléatoire pour récupérer l'original. C'est simple, mais cela aide à arrêter la recherche de mémoire.

Regardez aussi la vidéo de certains des gars derrière le moteur PushButton qui parlent des différentes façons de combattre le piratage : http://zaa.tv/2010/12/the-art-of-hacking-flash-games/ . Ils ont été la source d'inspiration de ce cours.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X