On pourrait nous reprocher de vouloir faire dans le sensationnel avec un tel titre sauf que ce n'est pas nous qui le crions haut et fort mais tout simplement un des hackeurs les plus talentueux que l'on connaisse, à savoir tmbinc.
Cette annonce, tmbinc l'a faite sur le site
debugmo.de où il explique en détails ce qu'il a découvert avec l'aide d'autres partenaires de "jeu".
Comme à notre habitude, voici une traduction complète de cet article fort intéressant.
Après la démonstration de Bushing concernant le premier exploit homebrew, beauoup de travail a été réalisé dans le monde de la Wii. L'exploit était basé sur une faille de la vérification/hash des disques, mais celui qui à l'origine avait découvert cette faille (Segher) ne souhaitait pas que ce bug soit diffusé. Cette décision a d'ailleurs fait couler beaucoup d'encre, mais la raison était que cette faille pouvait être facilement patchée via une mise à jour de firmware vu qu'aucune fonction "innée" n'était liée à cet exploit. L'étape suivant était donc de trouver un bug qui ne pouvait pas être patché si facilement, par exemple un exploit basé sur une sauvegarde jeu. Patcher ce genre de faille est considérablement plus difficile. Bien sûr vous pouvez patcher le code du jeu lorsqu'il est chargé (comme sur certains jeux gamecube qui sont patchés en mode compatibilité par le “gamecube compatibility IPL”), mais il suffit de trouver une faille identique sur un autre jeu pour déplacer le problème. En clair, on ne perdrait pas trop de "pouvoir" de hack si un bug de jeu est corrigé contrairement à la correction d'un bug critique du système. Je (ndgx: tmbinc) peut comprendre que certains soient exaspérés devant le manque d'explications qui sont diffusées. Cependant nous faisons de notre mieux pour mesurer les différents intérêts de chacun. Ce n'est pas toujours facile, même au sein d'une équipe. Reste que la règle est : si tu trouve un bug, c'est ton choix d'en faire ce que tu veux. Si tu n'aimes pas (cette idée), trouves ton propre bug.
Je me suis moins concentré sur les aspects de haut-niveau, je préfère généralement m'intéresser dans l'architecture du système et de la sécurité. Donc, je me suis concentré sur le bootloader.
Ce que nous savions auparavant était qu'il existe un bloc de code fixe appelé "boot1", qui est supposé être le premier code exécuté depuis le flash. Le code ARM ("Starlet") ainsi que le powerpc (Broadway) est booté bien plus tard. Nous ne savions pas comment était crypté le boot1 (des rumeurs laissaient comprendre le cryptage se situé entre un LFSR-based streamcipher et l'AES), ni si et comment il était hashé. Mais ce que nous avions était un programme nommé "BC" (title id: 1-100), extrait d'une mise à jour système. Nous ne savions absolument pas pourquoi BC existait (il était peut-être utilisé pour repasser du mode GC vers le mode Wii, mais à quoi cela servirait-il ?), mais ce que BC était capable de faire boot1 pouvait également le faire : lire un tas de secteurs depuis le flash, les décrypter, et vérifier une signature contre une chaine de certification précédemment décodée, puis s'y rendre. Jusqu'à ce que nous re-codions l'algorithme, il était clair qu'il s'agissait en fait de décrypter boot2. Encrypter boot2 nécessite de signer le nouveau hash. Mais il s'est avéré que BC contenait également "le bug" (enfin, une zone similaire), ce qui signifiait que les chances que Boot1 contienne également étaient grandes. Cependant, flasher un nouveau Boot2 est dangereux si vous n'avez pas de solution de retour. Il existe un méchanisme de backup pour booter une autre copie de Boot2, mais nous ne pouvions pas compter dessus pour différentes raisons (par exemple, si le code du nouveau Boot2 se bloquait, le backup n'aurait pas été déclenché, car pour Boot1 tout apparaissait normal).
Il est aussi devenu clair que jusqu'à ce que nous soyons capables d'exécuter le code Starlet, il y aurait de nombreux essais et erreurs. De ce fait, j'ai resorti mon vieil émulateur de NAND Flash FPGA, que j'avais fabriqué pour la Xbox 360. J'ai relié les pins du flash de la Wii au FPGA. Reste que le flash Wii a des propriétés différentes (largeur de block, taille différente, algorithme ECC utilisé différent), mais j'ai pu l'adapter en quelques heures. Je devais également corrigé la gestion du RESET (la Wii attend la chaine R/#B pendant un certains laps de temps), et d'autres petites choses, mais cela a fonctionné. Je pouvais booter depuis mon FPGA au lieu de la Flashrom originale. Ainsi je pouvais effectuer des modifications de code en quelques secondes, au lieu de devoir toujours reprogrammer la flashrom. Du fait que mon FPGA n'a "que" 512MB de RAM, je ne pouvais pas faire tenir tout le contenu du flash dans la RAM. Comme une partie de l'émulation de la NAND s'effectue sur le core PowerPC embarqué sur le FPGA (un Virtex 2 Pro), j'ai simplement ajouté une MAC ethernet, et utilisé lwip pour pour récupérer les parties de flash depuis un serveur TCP. Cela permettait ainsi de rendre le cycle de développement beaucoup plus simple puisque je pouvais modifier le contenu de la NAND virtuelle depuis mon PC.
Bushing avait préparé un boot2 corrigé pour moi (il avait juste modifié un byte dit dummy (ndgx: il s'agit d'un byte "inutile" de remplissage)), et cela a fonctionné ! Je pouvais désormais lancer du code sur le Starlet ! La première chose aurait été forcément de réaliser un "hello world", mais où le faire apparaitre ? Je voulais un UART software, tel que je l'avais fait en mode GC avant d'utiliser la ligne EXI_CS, mais je fût incapable de trouver un GPIO utilisable. Finalement j'ai pu faire clignoter la sensorbar. Malheureusement, tous ces IO ne sont pas TTL, et je ne voulais pas perdre de temps la dessus.
Un heure plus tard j'ai finallement eu l'idée que j'aurai dû avoir à la première minute : utiliser l'interface de la NAN déjà existante. Je devais juste délivrer une commande non-standard (le contrôleur de la NAND Starlet est assez simple pour être en mesure de délivrer n'importe quelle commande), et utiliser l'adresse des bytes comme conteneur. J'ai ajouté le code adéquat du côté du PGA (fort heureusement je n'ai pas eu à changer mon code VHDL...) pour envoyer l'adresse des bytes de la commande à l'UART du FPGA.
Quelques heures plus tard j'ai dumpé le boot1 (il était toujours en mémoire) et encore quelques heures plus tard j'ai dumpé un nouveau morceau de code, qui s'est avéré être quelque chose décryptant un morceau du début de la NAND flash dans la mémoire, puis calculant un hash SHA-1 par dessus, et le comparant à un hash lu depuis un genre de "mémoire interne" (que nous pensons être une section OTP). Il s'est avéré qu'il s'agissait de la Bootroom ! Super ! J'ai décidé d'appeler cette partie de code "boot0".
Bon, résumons:
- La première chose exécutée sur la Wii est le code "boot0", qui est probablement sotcké à l'intérieur du Hollywood dans une rom masque.
- boot0 charge les premières pages 0×2F (”boot1″) depuis le flash, les décrypte avec une clé AES fixe, calcule un hash SHA-1 (de manière assez obscure, que je ne pourrai pas calculer comme ça), et vérifie les valeurs prévues par opposition, lit depuis un genre de mémoire interne.
- Si le hash bytes de la "mémoire interne" est tout à zéro, la vérification du hash est sautée. Cela est probablement utilisé pour la production, et peut-être pour les devkits.
- Puis boot1 cherche un header spécifique dans le flash, d'où il extrait des informations particulières indiquant où trouver boot2.
- Durant cet instant, une chaine de certificat est vérifiée, et finalement le "tmd" boot1 est vérifié et le hash extrait.
- Le contenur de boot2 est chargé depuis le flash, décrypté, et le hash vérifié (par opposition au hash du tmd boot2).
- Puis boot2 charge le firmware, ou peu importe. Ce n'est pas ce qui m'intéresse pour le moment.
Si je devais évaluer la qualité de la sécurité, j'aurai des sentiments partagés. Avoir une bootrom est une bonne idée. Nous avons vu des système essayant de fonctionne de cette manière (par exemple la Gamecube), mais bien entendu un décryptage du hash, de la vérification de la signature est possible d'un point de vue hardware, et c'est souvent simplifié dans les faits (la gamecube par exemple avait un keystream statique, pas de hash, et une énorme faille hardware). De plus la bootrom fait plus de 512 bytes, et doit être assez grande pour utiliser certains vrais algorithmes (plus spécialement depuis que le hardware permet le SHA-1 et AES, ainsi tout ce qui est nécessaire de faire et de paramétrer les "moteurs") plutôt que d'autres buggués. Utiliser un secteur OTP, qui contient un hash fixe et également une bonne méthode, puisque cela permet de changer boot1 sans devoir changer la bootrom. Ils auraient pu faire du RSA dans la ROM (come Microsoft dans la Xbox 360) mais cette méthode suffisante, et cela retire également une trop grande complexité de la bootrom. De même, alors que le code du boot0 n'a pas l'air très "propre", il n'est pas non plus "terrible". Certains strings issue de GCC à l'intérieur du code démontrent que le code n'est pas assemblé "à la main" mais compilé. Cela est généralement une bonne chose , puisqu'il est plus facile de vérifier un code en C qu'un code en assembleur. Sauf présence d'un bug dans le bootloader (point sur lequel je ne souhaite pas m'étendre pour le moment, nous n'en avons pas trouvé), je considère qu'il s'agit d'un bon concept. Ce que je n'aime pas c'est que la clé de cryptage se trouve dans la ROM (elle aurait pu également être dans le secteur OTP), si bien que la vérification du hash est sautée lors le secteur OTP est vide. Bien que la production nécessite probablement cet état de fait, ils auraient pu remettre un hash de backup, ainsi avec un OTP non programmé, seul un type, précédemment déterminé, de software aurait pu être lancé (qui aurait ensuite écrit la clé adéquate dans l'OTP, en indiquant la partie programmable). En cas d'attaque hardware pour rendre inopérante le secteur OTP (ce qui est surement délicat, mais on ne sait pas), cela rendrait la ROM sans plus aucune sécurité (ou presque). Mais il s'agit là plus d'un risque théorique.
Cependant, il n'existe pas de mécanisme de révocation. Boot1 ne peut être mis à jour sur les machines commercialisées, comme le hash est OTP. Et boot1 est buggué. Les nouvelles Wii pourraient contenir une correction de Boot1, bien entendu, même sans modifier le masque de la rom, grâce l'approche flexible avec le hash OTP. La fonction de décryptage est dans sa majorité totalement chaotique (et bien que cela puisse être simplement une optimisation du compilateur, je parierai que les sources sont du même acabit...), et ne réalisant quasiment pas les vérifications usuelles requises, et contient, comme je l'ai dit, au moins 2 bugs pour le moins critiques. Etant donné que, dans la phase initiale de démarrage une véritable chaîne de confiance est utilisé (chaque code hérite des privilèges de sécurité du code l'appelant), voici de quoi casser la sécurité.
Pour la partie hardware, ce que j'aurai aimé est la possibilité "d'éteindre" la bootrom (et pas juste la masquer derrière une MMU), et MESSIEURS : vous avez réalisé un moteur AES parfait dans le hardware. Vous avez également un clé de sécurité stockée (OTP). Pourquoi n'avez vous tout simplement pas ajouté la possibilité d'utiliser le secteur OTP comme clé matérielle pour le moteur AES, et désactivé la lecteur de ces secteurs par le CPU ? Vous auirez pu cacher la clé boot1 dans le hardware par exemple. Ou voir même la clé boot2. Ou n'importe quelle partie importante. Mais tout est exposé au logiciel. Dès que vous ête dedans vous avez le contrôle. C'est LE problème de sécurité. La sécurité par l'obscurité ne fonctionne pas, mais l'obscurité additionné avec la sécurité (sans sacrifier de véritables sécurités, c'est important) aide souvent à gagner du temps. Ce n'est pas important si votre produit est hacké dans 10 ans, ça l'est s'il est hacké AUJOURD'HUI. En effectuant quelques modifications ici ou là vous pouvez rendre votre produit plus difficile à hacker, gagner du temps. Reste que, est c'est important, vous avez besoin d'une véritable sécurité. L'obscurité n'est pas un remplcement pour la sécurité.
Je souhaite ajouter que j'ai réellement apprécié notre travail d'équipe, même si ce ne fût pas facile tout le temps. Cela aide vraiment si plus d'une personne travaille sur quelque chose, même si (ou spécialement) tout le monde travaille dans une autre direction, mais tous dans le même endroit. Je souhaiterai également remercié d. d'avoir partagé ses logs NAND avec moi (il a également réalisé un sniffer&emulateur NAND bien avant que le mien ne soit prêt), cela a été très utile pour déterminer ce qui n'allait pas. Et bien entendu je suis heureux pour les personnes qui ont pris part à ces découvertes, qu'elles soient publiques ou non, en groupe ou non. Il y a beaucoup à apprendre au sujet de la Wii, et j'ai adoré faire parti de la communauté du développement Gamecube (au moins jusqu'à un certains point, mais c'est une autre histoire). C'est incroyable le travail réalisé par un relatif petit groupe de personne. Continuons comme ça.
Source : wii.gx-mod.com