1 points par GN⁺ 2024-04-19 | 1 commentaires | Partager sur WhatsApp
  • Randar est un exploit pour Minecraft Beta 1.8 à 1.12.2 qui reconstruit l’état de java.util.Random du serveur à partir des coordonnées de drop d’objets générés lors de la destruction de blocs, puis remonte jusqu’à la position d’autres joueurs
  • La cause principale est la réutilisation du RNG : la génération du terrain/des structures et les événements de minage partagent le même générateur de nombres aléatoires, et les positions de drop observables deviennent des indices sur l’état interne
  • Les offsets X/Y/Z d’un drop d’objet sont trois sorties consécutives de World.rand.nextFloat(), ce qui expose les 24 bits de poids fort d’une seed de 48 bits et permet de reconstruire rapidement la seed avec la réduction de réseau LLL
  • La seed reconstruite est ensuite rembobinée pour vérifier si elle provient d’un test de Woodland Mansion ; si oui, cela permet d’identifier la région Woodland de 1280×1280 blocs chargée le plus récemment
  • Si des enregistrements de paquets passés, comme ceux de ReplayMod, contiennent des données de drop, l’emplacement d’activités datant de l’époque Beta 1.8 à 1.12.2 peut encore être révélé après coup, même une fois le serveur corrigé

Les informations visées par Randar

  • L’objectif est de retrouver les coordonnées en jeu d’autres joueurs dans le même monde
  • 2b2t est utilisé comme cas principal
    • 2b2t est un serveur Minecraft « anarchy » sans règles
    • La carte du serveur couvre 3,6 quadrillions de tuiles carrées, donc le secret de l’emplacement est la condition clé pour protéger ses objets
  • Avant Randar, 2b2t avait déjà connu Nocom, un exploit de coordonnées utilisé entre 2018 et 2021

Versions vulnérables et erreur de code

  • Le problème existe de la sortie de Minecraft Beta 1.8 en 2011 jusqu’à la sortie de 1.12.2 en 2017
    • 2b2t est resté en 1.12.2 jusqu’au 14 août 2023
  • L’erreur centrale vient de la réutilisation imprudente d’une instance de java.util.Random dans plusieurs chemins de code
    • Le RNG est partagé entre des actions de jeu comme la génération du terrain et le minage
    • java.util.Random n’est de toute façon pas un RNG conçu pour la sécurité
  • Minecraft utilise une génération déterministe afin de produire le même terrain avec la même seed de monde et la même position
    • L’usage de java.util.Random est naturel pour cet objectif
    • Le problème vient du fait que la manipulation d’un RNG de génération de monde, qui doit être prévisible, affecte aussi des événements qui, eux, devraient être imprévisibles

Vérification de Woodland Mansion et World.rand global

  • World.rand est réinitialisé lors du processus de vérification de la position de génération d’une Woodland Mansion
    • La région Woodland est calculée par unités de 80×80 chunks
    • Pour choisir le chunk où la Mansion apparaîtra dans cette région, random.nextInt(60) est appelé quatre fois
  • Le flux vulnérable vient de la structure de World.setRandomSeed(seedX, seedY, seedZ), qui définit une nouvelle seed sur this.rand global puis renvoie le même objet
  • La formule spécifique à 2b2t est la suivante
seed = x * 341873128712 + z * 132897987541 - 4172144997891902323 mod 2^48
  • setRandomSeed est appelé non seulement lorsqu’on est réellement près d’une Woodland Mansion, mais aussi à chaque chargement de chunk à des fins de vérification
  • L’impact diffère selon les dimensions
    • L’Overworld est la principale dimension concernée
    • Le Nether est sûr, car sa génération de structures utilise toujours un RNG sécurisé
    • The End est affecté lors de la génération initiale à cause des end cities, mais comme les mêmes chunks ne réaffectent pas le RNG à chaque rechargement, il est relativement plus sûr

Comment les coordonnées de drop d’objets révèlent le RNG

  • Quand un bloc est miné, l’objet apparaît à une position aléatoire à l’intérieur du bloc
    • Par exemple, si les coordonnées du bloc sont (10, 20, 30), l’objet apparaîtra entre (10.25, 20.25, 30.25) et (10.75, 20.75, 30.75)
  • Cette position est déterminée par trois appels à world.rand.nextFloat() pour les offsets X, Y et Z
  • Il est possible de remonter des coordonnées de drop aux valeurs originales de nextFloat()
    • La multiplication du float par 0.5 ne fait que réduire l’exposant et ne provoque aucune perte d’information
    • La valeur est ensuite convertie en double, les coordonnées du bloc sont ajoutées, puis elle est transmise sur le réseau en pleine précision
  • java.util.Random.nextFloat() met à jour la seed 48 bits puis extrait ses 24 bits de poids fort sous forme d’entier avant de les diviser par 2^24
    • La formule du LCG est newSeed = oldSeed * 25214903917 + 11 mod 2^48
    • Trois floats consécutifs donnent donc les 24 bits de poids fort de trois seeds consécutives

Reconstruction de la seed par réduction de réseau LLL

  • La méthode simple consiste à tester les 2^24 candidats possibles pour les 24 bits de poids faible compatibles avec la première mesure
    • Cette approche fonctionne, mais elle est lente, d’où l’usage de la méthode par réseau
  • Les trois mesures donnent des intervalles pour les trois valeurs suivantes
    • seed
    • nextSeed(seed)
    • nextSeed(nextSeed(seed))
  • Si l’on voit ces trois valeurs comme un point 3D (seed, nextSeed(seed), nextSeed(nextSeed(seed))), l’ensemble des seeds possibles forme une structure de réseau
  • Les vecteurs de base sont définis ainsi
    • (1, a, a^2)
    • (0, c, 0)
    • (0, 0, c)
    • a = 25214903917, c = 2^48
  • La réduction de base LLL permet de trouver une base plus courte et presque orthogonale qui génère le même réseau
    • Exemple Mathematica : LatticeReduce[{{1, a, a^2}, {0, c, 0}, {0, 0, c}}]
    • La base obtenue est (1270789291, -2446815537, 2154219555), (-2355713969, 1026597795, 4110294631), (-3756485696, -2345310016, -2015749696)
  • En transformant le centre du cube de mesure dans l’espace de cette base réduite puis en arrondissant chaque coefficient à l’entier le plus proche, on obtient un point valide du réseau ; sa première coordonnée est la seed interne reconstruite
  • Un exemple de code Java optimisé peut reconstruire la seed à partir de trois mesures en environ 10 ns

Rembobiner la seed pour retrouver une position

  • Le LCG de java.util.Random peut avancer comme reculer
    • Sens direct : newSeed = oldSeed * 25214903917 + 11 mod 2^48
    • Sens inverse : oldSeed = (newSeed - 11) * 246154705703781 mod 2^48
  • On rembobine la seed reconstruite et on vérifie à chaque étape si elle pourrait provenir d’un test de Woodland Mansion
  • Le monde Minecraft s’étend de -30 millions à +30 millions de blocs
    • L’implémentation prend donc une plage de régions Woodland allant de -23440 à +23440 sur chaque axe
    • Le nombre total de régions Woodland possibles est (23440*2+1)^2, soit 2 197 828 161
  • Comparer les 2,2 milliards de candidats un par un est trop lent, et un gros HashSet consomme trop de mémoire
  • Comme le coefficient Z 132897987541 est impair, il possède un inverse modulo 2^48
    • Cet inverse est 211541297333629
    • Cela permet de parcourir seulement les 46 881 candidats X possibles et de calculer Z pour retrouver la région candidate

Optimisations GPU et table de lookup

  • Parcourir uniquement X reste raisonnable pour une seule seed, mais avec de nombreux bots minant plusieurs blocs par seconde et plusieurs milliers d’étapes RNG à vérifier par mesure, le traitement en temps réel devenait difficile sur un VPS peu puissant
  • L’implémentation a ensuite évolué vers des batchs CUDA et une table de lookup
    • La clé de la table est les 32 bits de poids faible de la mansion seed
    • La valeur est la coordonnée X de la région Woodland
    • Il est indiqué qu’il n’y avait pas de collision sur les clés 32 bits basses, sans explication claire de la raison
  • La table utilise 2^32 entrées et 2 octets par entrée, ce qui demande environ 9 Go de VRAM
  • Sur une RTX 3090, il était possible de casser environ 10 millions de seeds par seconde
  • Le résultat indique la région Woodland de 1280×1280 blocs correspondant au chargement de chunk le plus récent, ce qui suffit pour retrouver l’emplacement après quelques minutes de recherche

Distribution des steps observée sur un vrai serveur

  • En théorie, l’écart moyen entre deux Woodland seeds est d’environ 128 000 RNG steps
  • Sur 2b2t, la plupart du temps une Woodland seed était trouvée en quelques dizaines de steps seulement
    • La mesure a lieu très tôt dans le tick, au moment du traitement des paquets
    • En général, un chunk avait été chargé au tick précédent
  • Les mesures fiables commencent à partir de 4 RNG steps minimum
    • Le code de Woodland Mansion appelle rand.nextInt quatre fois avant l’observation
  • De grands pics apparaissent à des multiples de 1354 steps
    • Une explosion d’end crystal ou un wither skull sont suggérés comme cause possible
    • Dans le cas d’une explosion d’end crystal, le calcul des dégâts de blocs 16^3-14^3=1352 plus deux effets sonores donne bien 1354 steps

ReplayMod et risque d’exposition a posteriori

  • Même si le serveur a été mis à jour vers une version récente ou a corrigé la manipulation du RNG, le risque Randar subsiste si d’anciennes données sont encore disponibles
  • Certains joueurs Minecraft enregistrent les paquets avec des mods comme ReplayMod
    • Si les fichiers enregistrés contiennent des drops d’objets, l’état du RNG du serveur au moment de l’enregistrement peut être reconstruit
    • Comme casser des blocs est une action extrêmement courante, il est probable que ces données soient présentes
  • Toute position active à l’époque de Beta 1.8 à 1.12.2 doit être considérée comme exposée, même si le serveur a été mis à jour depuis longtemps
  • Un outil web côté client est fourni pour tester Randar directement
    • Sur hobune.stream/randar, il suffit de glisser un fichier ReplayMod 1.12.2 pour obtenir les coordonnées
    • Le fichier d’enregistrement ne quitte pas le navigateur

Exploitation de Randar et heatmaps

  • SpawnMasons a commencé à enregistrer les coordonnées de drop d’objets sur des comptes qui minaient déjà de la stone/cobblestone en continu 24/7 pour d’autres projets
  • Le système headless Minecraft utilisé pour Nocom a été réemployé, avec ajout d’une base de données Postgres pour stocker les mesures
  • Le logiciel chargé de casser les mesures RNG a été amélioré plusieurs fois, avant de converger vers des batchs CUDA asynchrones
  • Quand une mesure cassée est ajoutée à la base, les tables d’analyse de heatmap sont aussi mises à jour
    • Elles stockent les nombres de hits pour toute la période, par jour et par heure
    • Une interface Plotly Dash permet de choisir dans le navigateur une plage temporelle et un niveau de granularité
  • Le spam de chargement de chunks lié à la chasse aux stashs en Elytra est filtré en ne retenant que les coordonnées chargées sur plusieurs heures distinctes
  • Un système simple d’annotations partagées a aussi été ajouté pour suivre les hotspots découverts
  • Des bots Baritone issus de Nocom automatisaient en AFK le vol et le tri des stashs d’objets

Région Woodland leurre pour la protection

  • Randar ne retrouve pas toujours exactement le chunk le plus récent
    • Si, en rembobinant le RNG, une région Woodland leurre plus récente apparaît d’abord, un exploit qui renvoie la première correspondance peut produire un faux positif
  • En moyenne, une Woodland seed apparaît environ une fois tous les 130 000 RNG seeds, mais la distribution comporte des valeurs aberrantes
  • Sur 2b2t, environ une région Woodland sur 20 000 possède une propriété spéciale de dissimulation où une autre région Woodland apparaît dans les 4 RNG steps suivants
  • SpawnMasons a créé des stashs dans de telles régions
    • Les structures restaient compactes pour éviter que des chunks hors de la région de protection ne soient chargés à cause de la distance de rendu
    • À l’emplacement leurre, ils plaçaient un compte AFK et une petite base pour pousser d’autres utilisateurs de Randar à voir ce faux emplacement
  • Selon leurs propres logs Randar, ces stashs sont restés « propres » pendant toute leur durée de vie, sans chargement accidentel d’une région Woodland voisine
  • Il est précisé qu’au moment de la publication, ces stashs avaient déjà été déplacés

Exemple complet et limites selon les versions

  • Un exemple Java est fourni : il détecte dans SPacketSpawnObject les objets qui ressemblent à des drops de minage, reconvertit leurs coordonnées en trois mesures float, puis applique le cassage basé sur LLL et la remontée vers la région Woodland
  • Un exemple tiré de mesures réelles sur 2b2t donne le résultat suivant
    • item drop: 0.41882818937301636, 0.6833633482456207, 0.46088552474975586
    • RNG measurements: 5664934 14541261 7076144
    • seed interne : 95041827771683
    • région Woodland : -12008 0
    • plage de position : de -15370368,-128 à -15369089,1151
  • L’exemple de diagramme retrouve la Woodland Region 123,456
    • La plage finale est de 157312,583552 à 158591,584831
    • Elle contient la coordonnée d’entrée d’origine x=157440 z=583680
  • Les versions antérieures à 1.11 nécessitent un code différent, car la structure exploitable n’est pas la Woodland Mansion mais une autre structure
  • Avant la 1.9, la position des objets n’était pas transmise en double mais en point fixe 5 bits pour la partie fractionnaire ; casser l’état du RNG à partir d’un seul objet devient alors irréaliste et exige une autre stratégie de mesure

Méthodes de patch

  • La méthode la plus simple consiste à trouver un patch ou une configuration qui désactive la manipulation du RNG
  • Dans l’implémentation vulnérable, World.setRandomSeed définit la seed sur this.rand global et renvoie cet objet
public Random setRandomSeed(int seedX, int seedY, int seedZ) {
    this.rand.setSeed(seedX * 341873128712L + seedY * 132897987541L + seedZ + this.getWorldInfo().getSeed());
    return this.rand;
}
  • Pour une protection complète, on peut le modifier afin qu’il renvoie un nouveau Random à chaque appel
public Random setRandomSeed(int seedX, int seedY, int seedZ) {
    return new Random(seedX * 341873128712L + seedY * 132897987541L + seedZ + this.getWorldInfo().getSeed());
}
  • Si les performances inquiètent, il est possible de créer un champ RNG séparé, dédié à la génération du monde, par exemple separateRandOnlyForWorldGen, afin d’éviter tout partage avec d’autres usages
  • Un patch pour PaperMC 1.12.2 est fourni via le commit PaperWithRandarPatched et un fichier patch alternatif

Annexe de n0pf0x : autres méthodes de recherche de coordonnées et The End

  • n0pf0x a utilisé une recherche de coordonnées basée sur un cache plutôt qu’une énorme table de lookup GPU comme celle du camp Mason
    • Lorsqu’un hit survient, cette méthode place cette coordonnée et celles dans un certain rayon dans un HashMap
    • Le premier passage rembobine le RNG et vérifie rapidement soit un hit de cache, soit un doublon avec la seed traitée juste avant
    • Le second passage n’est exécuté que si le premier échoue, en utilisant alors l’algorithme coûteux de recherche de coordonnées décrit plus haut
  • Cette approche par cache peut aider à limiter les faux positifs en sautant des emplacements valides mais moins plausibles
  • Dans The End, le RNG n’est affecté qu’au moment où un chunk est créé pour la première fois, ce qui rend plus difficile l’observation répétée du chargement de chunks de base comme dans l’Overworld
  • Deux situations peuvent toutefois être exploitées dans The End
    • Un joueur présent dans une base se déplace et génère des chunks encore inexplorés
    • Un joueur allant vers une base crée sur sa trajectoire une traînée de nouveaux chunks
  • Cette traînée pourrait faire l’objet d’un système d’identification automatique, mais n0pf0x ne l’a pas implémenté et la suivait visuellement à la main
  • Pour identifier les joueurs, il a utilisé l’idée de l’End Occupancy Tracker (EOT)
    • L’hypothèse est que le nombre d’appels RNG par tick est corrélé dans une certaine mesure au nombre de chunks chargés, lui-même lié au nombre de joueurs présents dans cette dimension
    • En observant une hausse ou une baisse brutale du nombre d’appels RNG juste après les joins/leaves de joueurs, on peut estimer quels joueurs se trouvent dans The End
  • EOT n’a été testé que sur 9b9t et pourrait ne pas être valable dans d’autres conditions de serveur comme 2b2t
    • Il faut pouvoir échantillonner le RNG de manière fiable à chaque tick
    • Si l’activité des joueurs dans The End est beaucoup plus forte, cela peut devenir plus difficile

1 commentaires

 
GN⁺ 2024-04-19
Avis de Hacker News
  • En 1999-2000, il y a eu l’International RoShamBo Programming Competition, où s’affrontaient des bots informatiques de pierre-feuille-ciseaux [1]
    Le bot de référence choisissait au hasard, une stratégie théoriquement imbattable, mais une participation humoristique avait été conçue pour remonter l’état du générateur de nombres aléatoires et prédire avec 100 % d’exactitude le coup du joueur aléatoire
    Mise à jour : ce bot était « Nostradamus » de Tim Dierks, déclaré vainqueur de la catégorie « supermodified » lors de la première compétition [2]
    [1] https://web.archive.org/web/20180719050311/http://webdocs.cs...
    [2] https://groups.google.com/g/comp.ai.games/c/qvJqOLOg-oc

    • C’était moi. Ça fait plaisir de revoir cette vieille citation : « Avec d’excellentes compétences techniques et une attitude “triche tôt, triche souvent”, Tim pourrait avoir une carrière prometteuse comme programmeur IA dans l’industrie du jeu vidéo :) »
      En réalité, je suis parti dans la sécurité, j’ai rédigé des RFC TLS et je suis devenu ingénieur principal dans la sécurité chez Google. Merci d’avoir ravivé ce souvenir
    • La première année, j’avais soumis cheesebot, une participation optimalement mauvaise
      https://web.archive.org/web/20180719050236/http://webdocs.cs...
    • Toute la description des participations de la catégorie « supermodified » est hilarante
      Nostradamus a été écrit par Tim Dierks, VP engineering chez Certicom, avec une forte expertise en cryptographie, et a battu le joueur optimal en rétro-ingéniérant l’état interne du générateur random(). Selon lui, c’était « à la fois plus facile et plus difficile que prévu ». Par esprit sportif, il jouait tout de même de manière optimale contre tous les autres adversaires
      Fork Bot est né d’une idée venue à Dan Egnor quelques minutes après avoir entendu parler du concours : exploiter le fait que les « routines de bibliothèque » étaient autorisées pour lancer trois processus avec fork(), leur faire jouer chacun un coup différent, puis tuer les deux qui perdaient. Andreas Junghanns l’a implémenté en une dizaine de lignes de code, mais après le premier tour, les trois coups ont tous perdu contre Psychic Friends Network, le programme s’est terminé, et les matchs restants ont été déclarés forfait
      Psychic Friends Network était un code C obfusqué vraiment hilarant, écrit par Michael Schatz et les gens de RST Corporation : fonctions auxiliaires pour trouver le bon karma, consultations astrologiques, cuisine de spaghettis et de pizzas mystiques, #define transformant les démocrates en communistes, undef de Dieu, etc. On cherche encore à comprendre exactement ce qu’il fait avec les stack frames, mais tant qu’il n’affronte pas un méta-méta-tricheur, il ne marque jamais moins de +998 sur un match
      The Matrix a été écrit par Darse Billings, titulaire du prestigieux titre de « Student for Life », et battait tous ses adversaires avec un score parfait grâce au principe simple selon lequel « il n’y a pas de cuillère »
      The Matrix étant aussi le programme du tournoi, il a un accès complet à tous les autres algorithmes, structures de données et routines de sortie ; il est donc peu probable qu’il soit un jour dépassé. Cette catégorie a par conséquent été déclarée résolue et supprimée des compétitions suivantes
    • Je me souviens que quelqu’un avait fait la même chose sur un site de poker en ligne qui, dans une tentative louable d’améliorer la transparence, avait documenté son générateur de nombres pseudo-aléatoires
      Au final, cette transparence a effectivement amélioré la sécurité
    • Donc ils utilisaient bien un générateur de nombres pseudo-aléatoires ?
  • La réduction de réseau LLL est justement l’algorithme qui a aussi été utilisé dans une CVE d’il y a quelques jours pour casser des clés PuTTY à partir de nonces biaisés
    tptacek a un peu expliqué l’attaque et a aussi mis en lien un exercice cryptopals qu’on peut presque faire semblant de comprendre en plissant les yeux https://news.ycombinator.com/item?id=40045377
    Dans un registre similaire, le serveur Minecraft SciCraft avait une ferme à creepers avec une sorte de dispositif de magie noire qui manipulait de façon déterministe l’état du générateur aléatoire afin que, à chaque frame, un éclair « aléatoire » frappe un bloc précis et améliore les drops des creepers https://youtu.be/TM7SutJyDCk

    • Sean et Kelby expliquent bien mieux ce qu’est LLL, mais pour ce qui est de comprendre pourquoi LLL existe, cet article est presque le meilleur que j’aie vu jusqu’ici
      Dans les trois cas, il suffit d’un peu d’algèbre linéaire de base, et même pas beaucoup. Kelby aimerait que l’on comprenne Gram-Schmidt, ce qui arrive à peu près juste avant le partiel de mi-semestre d’un cours d’introduction à l’algèbre linéaire en licence
      Je n’ai pas les mots pour dire à quel point cet article est excellent. Il a embelli ma semaine
      Une explication très concise du même processus, que l’on peut suivre plus tard en Python :
      https://crypto.stackexchange.com/questions/37836/problem-wit...
    • Il existe aussi une manipulation de l’aléatoire qui fait toujours tomber le nombre maximal de blocs, expliquée ici
      https://youtu.be/ZcdN1wCJPqM?t=390
    • « Dispositif de magie noire » et « on peut presque faire semblant de comprendre en plissant les yeux », c’est exactement moi quand je regarde de la cryptographie :D
  • Je me figure la scène : tu te réveilles le matin et des blocs qui n’étaient pas là la veille flottent dans le ciel ; au début on dirait une sorte de brume fantomatique, puis on distingue vite de la redstone, des observateurs, des blocs de slime, et on voit une chute infinie de TNT.
    Tout ça simplement parce que le serveur a laissé fuiter ta position. Tu peux encore fuir, cela dit : peut-être quelques secondes pour récupérer des affaires dans un coffre et te barrer, ou le temps de construire un abri en obsidienne. Mais c’est tout.
    Tu n’as pas assez de temps pour construire un canon à visée précise, et de toute façon tu n’arriveras pas à régler l’altitude. Si tu as des élytres et des fusées, tu pourrais aller les gêner, mais il y a un énorme trou de world eater à 16 chunks de là. Est-ce qu’ils ont piégé tous les portails du Nether des environs avec de la lave ?

  • J’ai vu beaucoup de problèmes de générateur de nombres aléatoires intéressants et drôles, mais celui-ci est l’un des exploits les plus sophistiqués par rapport à ce qu’il permet d’obtenir. On dirait une belle œuvre d’art.

    • S’ils avaient vendu l’objet, ils auraient peut-être pu gagner un peu d’argent, peut-être quelques milliers de dollars. Bien sûr, vu la quantité de travail investie, ça reste une maigre récompense.
    • J’adore la façon dont des décisions apparemment anodines des développeurs de Mojang sont détournées ici. C’est vraiment impressionnant.
  • C’est un exploit assez génial.
    L’idée d’un serveur où l’exploitation de bugs est libre est aussi intéressante, et ça ressemble à une phase complètement différente du jeu.
    Si le métavers devait vraiment arriver, j’imagine que « se battre pour de vrai » ressemblerait à ça, plutôt qu’à simplement utiliser des mécaniques de combat intégrées au jeu.

    • Les combats sur 2b2t ne ressemblent pas non plus à du Minecraft ordinaire.
      Comme il existe depuis longtemps beaucoup d’objets de grande valeur dupliqués, le PvP est devenu une affaire de spam continu de cristaux de l’End, qui infligent d’énormes dégâts quand on les détruit, tandis que la défense consiste à posséder autant de « totems d’immortalité » que possible pour absorber les dégâts mortels.
      Évidemment, les clients de hack automatisent le placement des cristaux de l’End, le rechargement des totems, l’identification des positions faibles et fortes, et le joueur suit ces indications pour continuer à infliger des dégâts.
      Un peu avant cela, il y avait aussi des épées hackées infligeant +32 767 dégâts, capables de tuer instantanément, jusqu’à ce qu’elles soient patchées sur le serveur.
    • Le fait que l’équilibre converge autour des bugs et des exploits est assez typique des jeux sandbox PvP très compétitifs, même quand les serveurs ne l’autorisent pas.
      ARK: Survival Evolved et Eve Online sont tristement célèbres pour leurs immenses clans de plusieurs milliers de joueurs qui poussent le métagame et l’exploitation de bugs à l’extrême.
      Ce n’est pas toujours romantique. Dans ARK, il existait des mécanismes permettant de doxxer les joueurs et leurs différents comptes Steam, et il semble que, pendant la Great War, certaines relations en jeu aient aussi débordé dans la vie réelle.
      Parfois, les méthodes sont très basiques. Par exemple, lorsqu’on était attaqué, construire une immense tour puis la faire s’effondrer provoquait un déni de service sur le serveur et le faisait crasher ; le serveur revenait alors à une sauvegarde d’il y a 10 à 20 minutes, ce qui rendait très difficile l’attaque des bases où des joueurs étaient actifs. C’est une très vieille technique, corrigée il y a des années.
      Rust a aussi eu une politique qui encourageait à diffuser les bugs et exploits sur YouTube et à les rendre publics, mais dans un autre but : faire en sorte que les développeurs les remarquent et les corrigent plus vite. Résultat, le jeu est devenu assez solide, au point qu’il est très difficile d’en abuser sans utiliser de vrais hacks externes.
    • À mi-chemin, il y a Super Smash Bros Melee. Beaucoup de tactiques autorisées en tournoi reposent sur des bugs.
      Mais seulement celles qu’on peut exploiter manuellement avec une manette normale, pas de vrais hacks. Un exploit appelé Wobbling a été interdit en 2019, alors que le jeu date de 2001.
    • Du point de vue du gameplay, l’idée d’un vrai serveur anarchique me plaisait assez, mais sur le vrai 2b2t, j’ai arrêté parce que le chat était beaucoup trop rempli du n-word.
    • Un « serveur où l’exploitation de bugs est libre », ce n’est pas en gros tous les serveurs CS 1.6 sans VAC ?
  • Je viens de voir la vidéo sur ce sujet. C’est un excellent avertissement sur les risques liés aux interactions entre différentes sources d’aléa, et ça s’applique aussi à beaucoup de systèmes importants.
    Pour des raisons de performance, on partage souvent un générateur de nombres aléatoires dans le code, et ce genre d’histoire fait clairement réfléchir.

    • Je ne crois pas avoir déjà utilisé de générateur pseudo-aléatoire dans un logiciel sérieux, mais intuitivement, j’aurais pensé qu’utiliser le même générateur aléatoire au plus grand nombre d’endroits possible rendrait ce genre d’attaque plus difficile.
      Je pensais qu’il deviendrait trop difficile d’observer suffisamment de points de mise à jour. Mais cet exemple montre de façon assez frappante et amusante que cette intuition est fausse.
  • Cette vidéo est incroyable : https://www.youtube.com/watch?v=maMpMOnIJDE
    Je ne savais pas que la communauté était aussi sophistiquée.

  • Pour aller plus loin, ce type de craquage de générateur de nombres aléatoires a même déjà été implémenté dans le jeu.
    https://youtu.be/FPmQ0rnJjNc?si=tTFObcfZ-ILanL_A

  • Étonnamment, il existe une machine construite à l’intérieur même de Minecraft, le Mess Detector. Au lieu des drops de blocs, elle utilise la position de TNT amorcées pour prédire l’état interne du générateur de nombres aléatoires.
    https://www.youtube.com/watch?v=FPmQ0rnJjNc

  • Ça ressemble à une attaque par extension de compromission d’état (https://en.wikipedia.org/wiki/Random_number_generator_attack)
    C’est le genre d’attaque auquel un PRNG non cryptographiquement sûr, contrairement à un CSPRNG, peut être vulnérable.
    Aujourd’hui, le simple fait que des bibliothèques proposent un PRNG par défaut ne me paraît plus très sûr. C’est un peu comme autoriser TLSv1.0 ou Blowfish par défaut en 2024.