TRANSFORMERS: Forged to Fight est un jeu de combat en 3D où vous prenez le contrôle de certains des soldats les plus charismatiques de l'univers Transformers. On parle de grands noms comme Optimus Prime, Megatron, Bumblebee, Ratchet, Soundwave et Grindor – ni plus ni moins. Oui, vous avez bien lu. Vos personnages préférés de n'importe quel Transformers
Ce paquet contient un démarrage hors ligne fonctionnel de Transformers: Forged to Fight, ainsi que tous les outils, correctifs et notes d'ingénierie inverse utilisés pour y parvenir. Il est destiné à être repris par quelqu'un qui a le temps et l'énergie pour franchir la prochaine étape, bien plus vaste, qui consiste à reconstruire le contenu serveur du jeu à partir de zéro. Tout ici est documenté pour que vous n'ayez pas à repartir de zéro comme je l'ai fait.
Lisez l'intégralité de ce fichier avant de toucher à quoi que ce soit. La section « Pièges » en particulier vous fera gagner des jours.
Le jeu démarre complètement hors ligne et atteint son écran d'accueil interactif réel sans aucun serveur en ligne. Depuis l'écran d'accueil, les menus naviguent sans planter : la base, le roster des bots (avec un bot possédé présent dans le compte), la sélection du mode de combat, l'écran des cristaux, ainsi que les popups et astuces habituels. Le flux de connexion complet s'effectue, chaque sous-système en ligne se connecte, et l'expérience de première fois et les tutoriels sont passés. Le combat scripté d'introduction (Optimus contre Starscream) va même assez loin pour commencer à charger la bataille, et les modèles 3D des personnages s'affichent et s'animent.
C'était la partie difficile et elle est résolue. Le client lui-même est à nouveau vivant hors ligne.
Le gameplay réel ne fonctionne pas. L'histoire n'affiche aucune mission, et les combats ne peuvent pas se charger complètement. Ce n'est pas un bug et ce n'est pas quelque chose qu'un correctif peut résoudre.
Forged to Fight était entièrement piloté par le serveur. L'application sur le téléphone n'est essentiellement qu'un écran avec des commandes. Presque rien du jeu ne résidait dans l'application. Chaque mission, chaque combat, chaque alignement d'ennemis, l'intégralité des statistiques et capacités du roster, l'économie et tout l'équilibrage vivaient sur les serveurs de Kabam et étaient diffusés vers l'appareil à chaque session. Lorsque les serveurs ont été arrêtés début 2020, cette base de données de contenu a disparu avec eux, et elle n'a jamais été publiée ni archivée publiquement là où je puisse l'atteindre.
La situation se divise donc clairement en deux. L'art et l'audio ont survécu, car ils sont livrés dans l'application (voir re_notes/ASSET_INVENTORY.txt). Chaque personnage est un bundle Unity complet contenant le modèle, les textures, le squelette, les clips d'animation, les contrôleurs d'animateur, les effets et l'audio. Les environnements, les bâtiments, l'interface utilisateur, les portraits, les cinématiques et les dialogues sont également tous présents. Ce qui n'a pas survécu, ce sont les données qui disaient au jeu quels assets utiliser, comment les assembler en un combat ou une mission, et quels étaient les chiffres réels de chaque bot. Toutes les pièces sont là. Il ne reste plus rien qui sache comment les assembler. Reconstruire cela est l'intégralité du travail qui reste.
Il y a quatre parties mobiles. Ensemble, elles font croire au jeu non modifié qu'il communique avec Kabam.
Correctifs binaires natifs. Le jeu est en Unity IL2CPP, donc la logique vit dans une bibliothèque ARM compilée, libil2cpp.so, et non dans des fichiers de script modifiables. patches/patch_il2cpp.py réécrit six fonctions dans cette bibliothèque pour contourner les vérifications de serveur mort : il neutralise deux chemins d'épingle de certificat pour que notre propre certificat TLS soit accepté, force l'exécution du bloc d'enregistrement du gestionnaire même si la configuration en direct est nulle, permet à la connexion de réussir avec notre session de périphérique local, et fait taire les erreurs fatales des sous-systèmes qui autrement afficheraient la boîte de dialogue « échec de la connexion ». Il réinjecte également une seule entrée de dépendance (voir la section Pièges) pour que le hook d'exécution se charge effectivement. La sortie est libil2cpp.patched.so.
Un faux serveur Sparx. server/fakeserver.py se fait passer pour le backend de Kabam. Il écoute sur TLS 443 et HTTP simple 80 et répond aux appels API du jeu. Les réponses préfabriquées se trouvent dans server/responses/, un fichier par endpoint, nommé par méthode et chemin, par exemple GET__account_data.json. Quelques endpoints sont répondus dynamiquement dans le code plutôt que depuis un fichier, car le jeu s'attend à ce qu'ils renvoient des valeurs de la requête (les endpoints du tutoriel et l'endpoint des détails du héros). L'enveloppe de réponse est {"error":null,"result": ...}. Notez que dans les charges utiles d'erreur Sparx, le champ est orthographié err, et non error. Ce détail compte et est facile à manquer.
Un hook d'exécution natif. tools/nativehook/ compile libdothook.so, une petite bibliothèque chargée au démarrage du jeu qui enregistre chaque clé de données que le jeu lit, ainsi que quelques ajustements comportementaux ciblés. C'est la boucle de rétroaction qui a rendu tout le reste possible : elle vous dit exactement ce que le jeu demande, afin que vous puissiez synthétiser une réponse et la vérifier. Il s'agit d'un hook inline pur par réécriture de byte installé avant l'exécution, car l'outil normal pour cela (Frida) plante sous la couche de traduction ARM de l'émulateur.
Câblage du périphérique. L'émulateur doit envoyer les domaines de Kabam vers le PC et faire confiance au faux certificat. tools/provision_ldplayer.sh fait cela en une seule fois : il pousse la bibliothèque corrigée et le hook, redirige les noms d'hôte Kabam vers l'adresse LAN du PC via le fichier hosts, monte l'AC fictive dans le magasin de confiance système et assouplit SELinux. Exécutez-le après chaque redémarrage de l'émulateur, car ces montages ne survivent pas à un redémarrage.
Le flux de données à l'exécution est le suivant : le jeu effectue un appel HTTPS vers un domaine Kabam, le fichier hosts l'envoie au PC, le faux serveur répond avec une réponse de server/responses/, la bibliothèque corrigée accepte le certificat et la réponse, et le hook enregistre ce qui a été lu. C'est cette boucle qui a permis d'afficher chaque écran de cette version.
README.md ce fichier
TECHNICAL_NOTES.md la référence technique approfondie : correctifs, formes de données récupérées, découvertes
patches/
patch_il2cpp.py les six correctifs natifs plus la réinjection de dépendance
disasm_fn.py aide : désassembler une fonction à un offset
find_callers.py aide : trouver les appelants d'une fonction
find_str_ref.py aide : trouver les références à une chaîne
server/
fakeserver.py le faux serveur Sparx
gen_certs.sh régénérer le certificat TLS et l'AC (exécutez ceci, voir ci-dessous)
setup_device.sh référence de configuration réseau et de confiance côté périphérique
iterate.sh boucle de redémarrage et de capture rapide
responses/ un fichier JSON par endpoint appelé par le jeu
tools/
provision_ldplayer.sh reprovisionnement unique de l'émulateur à l'état de fonctionnement
setup_arm64.sh notes de configuration de la chaîne d'outils
decompile_targets.py piloter le décompilateur headless Ghidra à des offsets choisis
find_xrefs.py recherche de références croisées sur le binaire
apply_labels.py appliquer les étiquettes de symbole IL2CPP
light_analyze.py aides d'analyse statique légères
frida_attach.py aides Frida (conservées pour référence, voir la note libnb)
frida_run.py
hook_dot.js
nativehook/
hook.c source de libdothook.so, le hook d'exécution
libdothook.so hook précompilé, arm64
deploy.sh compiler et déployer le hook
relaunch_and_capture.sh relancer le jeu et capturer les logs
hook/dothook.c variante plus ancienne du hook, conservée pour référence
re_notes/
dump.cs le dump IL2CPP complet : chaque classe, méthode et champ du jeu
decomp_out.c corps décompilés des fonctions clés
decompile_targets.txt les offsets qui valent la peine d'être décompilés
ASSET_INVENTORY.txt les éléments artistiques et audio déjà livrés dans l'application
re_notes/dump.cs est le fichier le plus précieux pour le travail qui reste. C'est le modèle de type complet du jeu : chaque classe, chaque méthode, et surtout chaque champ de données que le client lit depuis le serveur. C'est votre carte de l'API backend entière. Lorsque vous avez besoin de connaître la forme d'une réponse, la réponse s'y trouve.
Ces éléments ont été volontairement omis, car ils sont volumineux, ou protégés par des droits d'auteur, ou secrets, ou vous devriez générer les vôtres.
com.kabam.bigrobot, version 9.2.0). Il fait environ 800 Mo. Procurez-vous votre propre copie. Le nom du paquet et la version sont dans TECHNICAL_NOTES.md.libil2cpp.so original et les assets du jeu. Les deux proviennent directement de l'APK. Dézippez l'APK, la bibliothèque se trouve sous lib/arm64-v8a/, les assets sous assets/.server/gen_certs.sh pour créer votre propre paire correspondante, puis pointez le magasin de confiance du périphérique vers la nouvelle AC.patches/patch_il2cpp.py contre le libil2cpp.so original de l'APK.re_notes/dump.cs à partir de la bibliothèque et des métadonnées globales de l'APK.Vous avez besoin de l'APK installé sur un émulateur capable de traduction ARM (LDPlayer 9 a été utilisé, avec root et système inscriptible), Python sur le PC, et les éléments de la section ci-dessus.
bash server/gen_certs.sh.python patches/patch_il2cpp.py chemin/vers/libil2cpp.so/original --apply.tools/nativehook/deploy.sh.python server/fakeserver.py. Il doit être accessible sur les ports 443 et 80 depuis l'émulateur.bash tools/provision_ldplayer.sh <votre-adresse-IP-LAN-PC>. Réexécutez après chaque redémarrage de l'émulateur.Si cela bloque à la connexion, vérifiez le tout premier élément de la section Pièges avant toute autre chose.
Ce sont ceux qui m'ont coûté des heures. Ils sont écrits pour qu'ils ne vous coûtent pas la même chose.
libdothook.so. Les octets et offsets exacts sont documentés dans le script de correctif et dans TECHNICAL_NOTES.md.provision_ldplayer.sh sinon rien ne se connectera.err, pas error. Utiliser le mauvais produit des réponses que le client ignore ou traite mal silencieusement.C'est le vrai travail, et il est vaste. Voici sa forme et par où commencer.
L'objectif est de recréer, à la main, le contenu serveur qui était autrefois diffusé vers le client : les quêtes et missions, les cartes et leurs alignements ennemis, le roster complet avec les statistiques et capacités de chaque bot, les formules de combat et l'économie. Rien de tout cela n'existe plus, donc tout doit être créé à nouveau, dans les formes exactes attendues par le client.
La méthode qui fonctionne est la boucle autour de laquelle ce projet est construit. Exécutez le jeu avec le hook attaché. Le hook enregistre chaque clé que le client lit. Lorsque le client demande quelque chose que vous n'avez pas fourni, vous voyez exactement ce qu'il voulait. Vous synthétisez ensuite une réponse dans la bonne forme, la placez dans server/responses/ ou l'ajoutez au gestionnaire dynamique dans fakeserver.py, redémarrez, et vérifiez que le client l'accepte et avance. Répétez. Chaque écran de la version actuelle a été affiché de cette manière exacte. re_notes/dump.cs vous indique la forme de chaque structure avant même d'exécuter, car il liste tous les champs que le client lit.
Un ordre raisonnable pour l'attaquer :
decompile_targets.py) et lisez les champs exacts.ASSET_INVENTORY.txt, donc vous ne créez que des chiffres et des définitions de capacités, pas des assets.TECHNICAL_NOTES.md pour les clés.Soyez réaliste quant à l'ampleur. Même pour les jeux où les fans ont sauvegardé les données du serveur en direct avant l'arrêt, mettre en place un serveur privé est un long projet. Ici, il n'y a pas de données sauvegardées pour commencer, donc chaque nombre et chaque capacité doit être recherché ou réinventé puis vérifié contre le client. C'est un effort multi-personne et multi-années si l'objectif est le vrai jeu. Cela dit, le chemin n'est plus un mystère. Le démarrage est résolu, la boucle de rétroaction existe, le modèle de type est extrait et les assets sont intacts. Ce qui reste est une très grande quantité de reconstruction minutieuse de données, et non plus de l'ingénierie inverse de l'inconnu.
Commencez par TECHNICAL_NOTES.md. C'est la référence technique plus approfondie, avec les correctifs exacts, les formes de données récupérées et les découvertes spécifiques, plus détaillées que ce README. Ensuite, exécutez la boucle.
Bonne chance. C'est maintenant une vraie machine. Il faut juste reconstruire son contenu.