URL: https://linuxfr.org/users/imalpha/journaux/du-reverse-engineering-et-de-la-pomme Title: Du reverse engineering, et de la pomme Authors: imalpha Date: 2016年01月02日T19:01:54+01:00 License: CC By-SA Tags: apple, engineering, assembleur, hash et franglais Score: 108 Dans ce journal, qui se veut un peu long mais clairement divisé en parties relativement indépendantes, j'aimerai expliquer les expérimentations que j'ai faite pour pouvoir ajouter de la musique sur un iPod (Apple, donc) de 7ème génération, qui n'est pas supporté par les outils actuels sous GNU/Linux. Et ça ne se finit pas élégamment, mais ça se finit quand même : j'écris ce journal en écoutant la musique de cet iPod, musique transférée depuis GNU/Linux ! Le résultat en tant que tel n'a pas grand intérêt : ma solution n'est utilisable que pour ce type d'iPod là, et empêche l'utilisation d'iTunes, n'est pas graphique, etc... Mais comme c'est la première fois que je fais ce genre de chose, beaucoup d'éléments m'ont semblé intéressants, et j'espère aussi récupérer des avis et des conseils sur ces méthodes. # Contexte Pour faire court, j'ai reçu un iPod 7g à Noël il y a deux ans (oui, c'est une excuse courante pour les linuxiens), et j'aurai quand même aimé l'utiliser. Sauf qu'il n'est pas possible de transférer des morceaux depuis les lecteurs de musique libres qu'on peut trouver sur GNU/Linux. Après quelques recherches, il s'avère que libgpod ne le supporte pas, et il n'y donc aucune raison pour que ça puisse marcher avec un quelconque lecteur. On trouve vaguement une procédure sur Internet, mais c'est à base de .so dont on n'a pas les sources, et de toute façon ça ne marche pas chez moi (il semble que j'ai un firmware trop récent). Je laisse donc tomber dans un premier temps. Mais cet été, je retombe dessus, et ayant un peu avancé dans mes études, j'ai un peu plus d'idées qu'avant. Je me décide donc à essayer de faire un peu de reverse engineering là dessus. Il va de soi que je ne me suis pas devenu un expert dans ce domaine en un an et demi. # Un problème de signature ## Une approche large On a un peu de chance, tous les fichiers qu'écrit iTunes (en dehors du système lui même) sont lisibles normalement, comme si l'iPod était une vulgaire clé usb. Oui, ce [n'était](http://www.igeeksblog.com/how-to-use-your-iphone-as-a-usb-flash-drive/) [pas](http://www.cnet.com/au/products/apple-ipod-touch-2nd-generation/#!) gagné. Déjà, je redémarre sous windows, j'installe iTunes, je réinitialise l'iPod. Je redémarre sur Arch, copie l'intégralité des dossier de l'iPod sur mon ordinateur, je rédemarre, j'ajoute un morceau, et je fais un `diff` pour voir les fichiers qui ont changé. Évidemment il n'y a pas qu'un, mais ça reste raisonnable, je les remplace un par un jusqu'à trouver ceux qui sont vraiment responsables du changement. 3 fichiers ressortent du lot : `Locations.itdb`, `Library.itdb`, `Locations.itdb.cbk`. Là, agréable surprise, les deux premiers sont des bases de données SQLite. Victoire, je commence à bidouiller un peu, je peux changer le titre des morceaux en modifiant `Library.itdb`, ça marche bien. J'exulte. Sauf qu'ensuite, j'essaye d'ajouter un nouveau morceau. Pour ça, j'ajoute une entrée dans une table de `Locations.itdb`, et une autre dans `Library.itdb`. Et là, le drame, l'iPod me dit qu'il n'y a aucun morceau sur l'iPod. Donc non seulement ça a échoué, mais en plus, on a perdu les morceaux qui y étaient déjà. Je remets les bases de données dans un état antérieur qui fonctionne. Je commence à comprendre que le .cbk est une signature des autres fichiers. Je change un octet dans ce fichier avec [ghex](https://wiki.gnome.org/Apps/Ghex), et l'iPod déclare qu'il n'y a aucun morceau sur l'appareil. Maintenant on est certain qu'il s'agit d'une signature, et probablement seulement de Locations.itdb (déjà par son nom, et ensuite parce que les changements dans `Library.itdb` n'ont pas l'air de déranger l'iPod). ## Les grands moyens, le désassemblage Alors là, on examine un peu le fichier .cbk : 177 octets, ce qui ne correspond pas un standard largement répandu (i.e. je ne trouve pas ce que ça peut être), j'essaye quand même des trucs au hasard, mais bon, même en supposant que ça soit un [sha](https://duckduckgo.com/l/?kh=-1&uddg=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSha-256) quelconque, il suffit qu'il y ait simplement un masque appliqué sur Locations.itdb pour que je n'ai aucune chance de trouver. Donc ça, j'abandonne. Je me lance donc dans la décompilation d'iTunes, ou plutôt dans le désassemblage, puisque j'apprends au passage qu'il n'y a pas de [logiciel accessible](https://www.hex-rays.com/products/decompiler/index.shtml) pour décompiler un truc de cette taille là et avoir un résultat un peu intéressant (oui, [ça existe](http://boomerang.sourceforge.net/) mais ça ne marche pas bien du tout). Là surprise, les [outils classiques](http://www.sourceware.org/binutils/docs/binutils/objdump.html) fonctionnent bien, même si c'est un binaire Windows et qu'on désassemble sous Linux. Là, la seule chose que je peux chercher c'est "cbk". Gros coup de chance, il y a 2 occurences. L'une me mène dans le segment de data, je récupère l'adresse, je cherche dans l'assembleur où elle est utilisée, et pareil un nombre très réduit d'occurrences. Je tente de lire l'assembleur et de le décompiler à la main les morceaux qui semblent prometteurs : autant dire qu'au bout de quelques heures j'abandonne, c'est incompréhensible. Je fais quand même quelques expérimentations, j'écris un programme qui sépare l'asm en fonctions, et qui leur donne des noms d'animaux aléatoires à la demande. C'est rigolo, mais ça ne m'avance pas beaucoup. ## Une petite victoire, des maths, et le désespoir Pour poursuivre un peu dans cette voie, j'ai besoin de voir comment le code s'exécute. Je fais des recherche, je trouve un [débugguer](http://x64dbg.com/) pour Windows, je redémarre, je mets des breakpoints sur les adresses que j'ai remarquées à l'étape précédente. Je lance iTunes avec le débugguer, ça crash. Je recommence, pareil. Finalement je lance iTunes, et j'attache le débugguer ensuite (ça revient en gros au même). Ce n'est pas super stable (c'est le moins qu'on puisse dire), mais ça marche à peu près. J'ajoute un morceau à l'iPod, et le débugguer s'arrête sur un breakpoint. Ouf, je n'avais plus d'idées sinon. Alors là, j'y passe des heures, je fais marcher le débugguer pas à pas, entre les crash, j'essaye de faire une carte du code voir par où on va, si je comprends quelque chose. J'utilise mon programme qui sépare l'asm en même temps, pour donner des noms aux fonctions que je rencontre. Quand elles sont appelées à d'autres endroits, je ne les étudie pas, etc... Au bout d'un moment, j'arrive à comprendre à peu près dans quel ordre les bases de données et la signature sont écrites. Mais bon... Et à un moment, je tombe sur le code de chargement de 4 constantes, ça ressemble à l'initialisation d'un code de crypto. Je les mets dans mon moteur de recherche favori, et là, boum, c'est du [sha1](https://fr.wikipedia.org/wiki/SHA-1). Je passe encore quelques heures à étudier ça, et finalement, j'arrive à déterminer que sha1 est appelé sur les 1024 premiers octets de Locations.itdb, puis les 1024 suivant, et cela 4 fois. Hop, je split le fichier, je calcule le sha1, et je les retrouve dans le .cbk. Jubilation. Mais ça ne fait pas tout le fichier ça, il manque encore pas mal d'octets du cbk. Je réétudie l'assembleur, je me rends compte que les 4 hash calculés sont accolés et qu'ensuite on recalcule encore une fois le sha1 là dessus. Hop, ça ne laisse plus que 55 octets dans le .cbk. Et là... je continue de regarder l'asm et le débuggueur, je ne trouve plus rien. Pire, l'assembleur change d'un coup, il devient encore plus difficile à lire. Je ne suis pas arrivé à décider si c'est le débugguer qui bugguait ou si c'était fait exprès mais il semblerait que certains endroits du code incrémentent %pc de seulement quelques octets, ce qui décale le cadre de lecture de l'asm. En plus, les instructions qui font ça le font après avoir fait tout un tas de calculs absurdes (genre mutiplier par 0x452FE45 puis soustraction de 0x786798, puis on remultiplie... tout ça pour faire moralement %pc = %pc + %rax, avec %rax = 2). Alors je commence à me dire que c'est peut-être de l'obfuscation et que c'est juste fait exprès pour ne pas qu'on puisse continuer. Ça fait donc 55 octets, qui sont probablement calculés à partir de 122 premiers. Mes maigres connaissances en crypto me disent que je n'ai absolument aucune chance d'inverser ça par force brute, et que ce n'est absolument pas standard. Bref, c'est désespérant. C'est dommage, j'ai la majorité des octets, mais il en suffit d'un de faux... J'abandonne pour le moment. # La solution détournée, mais peu élégante Hop, ce sont les vacances de Noël, je retombe sur l'iPod que je n'ai toujours pas utilisé, et je n'y remets. Après quelques égarements dans l'asm et le débuggueur (qui avance un peu, j'ai trouvé un peu plus dans l'asm quelles étaient les fonctions qui généraient la signature), je commence à relaisser tomber. Mais en fait, on a pas besoin de générer la signature à chaque fois. Le contenu de Locations.itdb est assez inutile. Grossièrement, cette base de données ne sert qu'à associer un id à un fichier. Donc quand on ajoute un morceau, il faut rajouter une ligne. Oui mais en fait, je fais un test, et on peut avoir plus de ligne dans Locations.itdb que de morceaux dans `Library.itdb`. On va donc faire générer à iTunes une signature pour une bases qui contient des centaines de morceaux, puis les supprimer de `Library.itdb`, et on aura un certain nombre d'emplacements disponibles pour mettre nos morceaux. Quand on en ajoutera un, il suffira de prendre une ligne qui n'est pas encore associée à un vrai fichier dans Locations.itdb, et la rajouter dans Library.itdb, avec toutes les informations sur ce morceau (titre, artiste, album, etc). L'intérêt de la méthode c'est qu'on a besoin une seule fois d'iTunes, et ensuite ça marche (très probablement) pour tous les iPod du même modèle (enfin ça c'est à vérifier, mais j'y crois). Et ça marche ! Je sépare un mp3 en 10000 morceaux, j'importe ça dans iTunes, je les copie sur l'iPod (enfin là je suis passé à 3000, 10000 ça faisait tout planter), et ça génère bien un `Locations.itdb` avec 30000 entrées. Reste à coder de quoi ajouter automatiquement toutes les données aux bases de données de l'iPod, gérer les "emplacements" disponibles à chaque fois, etc... Après 2 petites journées à coder en Vala, je transfère la majorité de ma bibliothèque depuis Linux, sans avoir besoin d'utiliser Windows. Le code est [ici](https://github.com/i-malpha/ipod7linux), mais ça risque probablement de détruire toute la bibliothèque de votre iPod si vous l'utilisez... # Conclusion : les formats ouverts et les formats ouverts Ces expérimentations m'ont donc permis d'écrire un programme qui transfère bien des morceaux depuis Linux vers un iPod. La conclusion reste quand même qu'il faut acheter des produits qui ont des spécifications un minimum ouvertes, à défaut de matériel et de logiciel libre. Cependant, dans cette histoire qui peut sembler noire de logiciels propriétaires, on voit quand même les bienfaits des logiciels open source. Parce que oui, on s'aperçoit qu'Apple utilise des technologies largement répandues ou des spécifications standards : SQLite, sha1, etc... Sans cela, il est certain que ce travail aurait été très laborieux, voir impossible. L'autre aspect, c'est qu'il semble évident que les ingénieurs d'Apple ne cherchent pas à empêcher l'utilisation de leur matériel sur d'autres systèmes, ils ne l'encouragent pas, c'est vrai, mais il n'y a pas particulièrement de protection là dessus : les coups de chance que j'ai eu ne seraient pas possibles si les ingénieurs s'étaient sérieusement dit qu'il fallait l'empêcher (ou sinon c'est qu'il sont assez incompétents et négligents, mais je ne le crois honnêtement pas). Enfin, quelques mots sur le côté légal de la chose : désassembler le code d'iTunes comme je l'ai fait est probablement formellement interdit par la licence d'utilisation. Cela dit, on peut aussi voir cette démarche comme nécessaire pour faciliter l'interopérabilité, comme [le fait VideoLAN](http://www.videolan.org/developers/libbluray.html). C'est étonnamment clair dans le [code de la propriété intellectuelle](http://www.legifrance.gouv.fr/affichCodeArticle.do;jsessionid=257F3A2551AFEA654609264234C2CD43.tpdjo13v_3?cidTexte=LEGITEXT000006069414&idArticle=LEGIARTI000006278920&dateTexte=&categorieLien=cid) :> La reproduction du code du logiciel ou la traduction de la forme de ce code n'est pas soumise à l'autorisation de l'auteur lorsque la reproduction ou la traduction au sens du 1° ou du 2° de l'article L. 122-6 est indispensable pour obtenir les informations nécessaires à l'interopérabilité d'un logiciel créé de façon indépendante avec d'autres logiciels

AltStyle によって変換されたページ (->オリジナル) /