Broken Synapse Désactivation du brouillard de guerre dans un jeu de stratégie en ligne
$> whoami Ivan Kwiatkowski Consultant en sécurité informatique pour AMIR Consulting Deux projets FOSS Manalyze (manalyzer.org) ApkTrack
Frozen Synapse Sorti en 2011 Jeu de stratégie en tour par tour Orienté « compétition » Objectif : désactiver le brouillard de guerre
Idée #1 : Wireshark Filtre : ip.addr == Login du client de jeu : Password : MD5(salt + MD5(password)) Protocole cleartext, séparateur = \t textcomprelogon textcomcommandsaltRec textcomlogin[user][pwd_hash]33 textcomloggedIn30787 [user] textcomcommandsetMyOSwindows.steam writeFile[…].txt121gz161 textcomcommandrefreshPeopleOnline
Idée #1 : Wireshark Récupération des données d’une partie Client : textcom command selectMT [game ID] Serveur : blob.gz 0000h: D 75 6C....ˆ mul 0010h: E E F titurn.caffinato 0020h: D D r Matchmad 0030h: E A 77 e SniperZw 0040h: 6F 6C D olf h: h: caffi 0070h: 6E F E A 77 6F 6C nator.SniperZwol 0080h: D E f h: D 0A 6D machi 00A0h: 6E E FF neGun ÿ 00B0h: FF FF FF BF ÿÿÿ..€¿ C0h: AB D0 44 CE D0h: BF E €¿ E0h: AB D0 44 CE 41 Header ???
Idée #2 : OllyDbg Breakpoint sur recv Boucle infinie (?) dans un switch-case géant Jeu bâti sur le moteur Torque Game Engine Langage de script « maison » Fichiers.cs.dso dans le répertoire du jeu
Idée #3 : Décompiler les.cs.dso Code du Torque Game Engine publié en 2013 Lecture moteur pour comprendre : Structure des fichiers.cs.dso Rappelle les.class de Java Présence de tables qui contiennent valeurs immédiates / noms de variables Fonctionnement de l’interpréteur Pas de registres Trois piles Aucune optimisation
Idée #3 : Décompiler les.cs.dso Ecriture d’un émulateur/décompilateur en Python Torque VM (floats) Emulateur (floats) Opcode OP_LOADIMMED_FLT [2] 2 2 OP_LOADIMMED_FLT [5] 55 OP_ADD 7 "5 + 2" OP_SETCURVAR [%var] pCurrentVariable = lookup_local("var"); curvar = "%var" OP_SAVEVAR_FLT pCurrentVariable->setValue(stack.top()); Code source : %var = 5 + 2;
Idée #3 : Décompiler les.cs.dso Structures de contrôle plus compliquées à gérer : BytecodeEmulateur [test] OP_JMPIFNOT if ? while ? [branche « True »] Où est-ce que je referme l’accolade ? [suite du code] BytecodeEmulateur [test] OP_JMPIFNOT if ? while ? / Ajout de META_ENDIF [branche « True »] Où est-ce que je referme l’accolade ? META_ENDIF OK, ici ! [suite du code]
Idée #3 : Décompiler les.cs.dso Détection du type de structure : regarder l’opcode avant la destination du saut [test] OP_JMPIFNOT [branche "True"] OP_JMP [branche "False"] [suite du code] if-then-else [test de sortie de boucle] OP_JMPIFNOT [instructions de la boucle] [test de sortie de boucle] OP_JMPIFNOT [suite du code] for / while [test] OP_JMPIFNOT [branche "True"] [suite du code] if (sans else)
Idée #3 : Décompiler les.cs.dso Déroulement git clone Ecrire des scripts.cs et les faire compiler en.cs.dso par le moteur Avoir un décompilateur qui marche ! Décompiler les scripts de Frozen Synapse !
Idée #3 bis : Décompiler les.cs.dso Nouvelle mission : identifier les évolutions du bytecode IDA Pro Pro tip : version GNU/Linux de Frozen Synapse non strippée :) Indices dans le code du moteur …mais premier commit seulement en février 2013 Différences découvertes : Liste des opcodes décalée à deux endroits Taille des offsets : 4 octets au lieu de 8 Adaptation du décompilateur
Idée #3 bis : Avec un décompilateur Possibilité de lire le code source du jeu Si un.cs plus récent est détecté dans le répertoire, Torque le recompile et l’utilise Possibilité de modifier le client du jeu ! Désactivation du brouillard de guerre Acquisition de succès Steam Modding ? Démonstration
Conclusion Données « sensibles » masquées mais transmises Décompilateur et scripts disponibles sur GitHub Tricher c’est mal Writeup et slides sur mon blog : Frozen Synapse 2 annoncé pour 2016 Même moteur ? Même décompilateur ? Des questions ?