Un big post que je travaille depuis un moment. Dans cet article j’explique la séquences de demarrage du système d’exploitation mobile iOS d’Apple.

Demarrage iOS

Je me suis amusé à étudier iOS avec les différents outils que j’ai pu présenter dans mon article précédent, j’ai lu un tas de trucs sur les différents composants d’iOS etc…

Tout d’abord il faut savoir que le demarrage d’iOS est particulier, chaque composant vérifie l’integrité du composant suivant puis le lance. Voici un exemple avec le schéma suivant :

pasmonimg

Les Bootloaders sont des fichiers IMG3 (32 bits) ou IMG4 (64 bits). Chaque composant de la bootchain est vérifié par son prédécesseur en comparant les signatures numériques des différentes sections de l’image.

BootROM

La BootROM (aussi connu comme Secure ROM), est le premier composant à demarrer lorsque vous pressez le bouton power de votre iBidule. Il a la particularité d’être en lecture seule (ROM = Read Only Memory). Celle-ci est basée sur une architecture ARM.

C’est un bootloader de 64 Kb. Ce composant peut permettre deux types des demarrages :

  • Mode normal que je vais expliquer tout au long de cet article
  • Mode DFU (Device Firmware Upgrade) qui est un genre de mode de récupération hardware. Je m’attarde pas trop dessus.

Si jamais une faille est découverte dans la BootROM, il est impossible de corriger celle-ci par une mise à jour iOS, cela signifie un jailbreak à vie.

De plus ce type d’exploit permet de totalement outrepasser les différentes vérifications de la Bootchain pour permettre de flasher de nouvelles images.

Un exemple avec iDroid Project qui avait pour but de porter le noyau Linux et Android sur l’iPhone, en exploitant une faille dans la BootROM des appareils pré-4S. Beaucoup de projets open source on pu être compilés et installables sur iOS (avec des pré-requis bien sûr) :

Il est aussi possible de dumper la BootROM au niveau logiciel pour ainsi l’analyser.

Le dernier exploit BootROM rendu public est limera1n écrit par Georges Hotz compatible avec l’iPhone 4, le 3Gs etc… Bref à partir de l’iPhone 4S il n’est pas possible de faire tout ça (pour l’instant).

Au jour d’aujourd’hui la BootROM est une vraie forteresse. Toutefois il est toujours possible d’extraire celle-ci comme le montre @key2fr dans son post pour ainsi l’analyser plus concrètement.

00000200  53 65 63 75 72 65 52 4f  4d 20 66 6f 72 20 73 38  |SecureROM for s8|
00000210  30 30 30 73 69 2c 20 43  6f 70 79 72 69 67 68 74  |000si, Copyright|
00000220  20 32 30 30 37 2d 32 30  31 34 2c 20 41 70 70 6c  | 2007-2014, Appl|
00000230  65 20 49 6e 63 2e 00 00  00 00 00 00 00 00 00 00  |e Inc...........|
00000240  52 45 4c 45 41 53 45 00  00 00 00 00 00 00 00 00  |RELEASE.........|
00000250  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000280  69 42 6f 6f 74 2d 32 32  33 34 2e 30 2e 30 2e 33  |iBoot-2234.0.0.3|
00000290  2e 33 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |.3..............|
000002a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

Voici le dump de la BootROM de l’iPhone 6S ci-dessus.

Et bien sur, la BootROM check l’intégrité du LLB puis le charge en mémoire.

Low Level Bootloader

Le Low Level Bootloader ou LLB est lancé par la BootROM après une vérification des signatures de celui-ci, c’est la seconde étape de la chaine de confiance iOS (aka Trusted Bootchain). Celui-ci initialise les horloges, la memoire physique de l’appareil, l’unité de gestion mémoire (ou MMU) pour charger l’iBoot et quelques fonctionnalités USB pour le mode DFU.

Lors du boot, c’est au LLB de verifier les signatures des APTickets qui sont une version 2.0 des SHSH blobs. Sauvegarder ses APTickets permet un possible downgrade avec Futurerestore ou Odysseus.

iBoot

L’iBoot est l’un des plus importants de la séquence d’amorçage, c’est le second bootloader à démarrer après vérification de celui-ci par le LLB. L’iBoot continue d’initialiser toutes les fonctionnalités USB. C’est lorsque l’iBoot demarre que vous voyez la pomme :).

Celui-ci active le log pour la connexion série comme ci-dessous. J’en ai aussi parlé dans un précédent article

ibootout

L’iBoot est aussi le dernier composant de la Bootchain à avoir accès aux résultats du moteur de chiffrement AES 256 d’iOS. Certains hackers très connus de la scène du jailbreak ayant écrit des exploits iBoot ont pu avoir accès au moteur de chiffrement pour ainsi obtenir les clés permettant de déchiffrer presque toutes les images des firmware d’iOS.

Dechiffrer ces images a permis une meilleure documentation de chacune d’elles, et la facilitation de la création de custom firmware pour retrograder vers une version d’iOS précédente.

A noter que les versions d’iBoot qui tournent sur des appareils 64 bits (iPhone 5S et plus) peuvent communiquer avec SEP (Secure Enclave Processor) dont je parle un peu plus bas.

Ensuite l’iBoot vérifie puis charge l’images du Device Tree pour monter la partition d’iOS, enfin il localise l’adresse du kernel puis le charge en mémoire.

kcacheload

Si l’une des deux images est corrompu alors le demarrage d’iOS se stop et l’iBoot fait passer l’appareil en mode de récupération (Recovery Mode).

Pour revenir au fait d’avoir un exploit iBoot, ce type d’exploit permet à peu près autant de possibilités qu’un exploit dans la BootROM mise à part qu’il peut être corrigé via une simple mise à jour logicielle. C’est pour ça que personne ne publie de logiciel basé sur un exploit iBoot.

La hacker iH8sn0w a fait plusieurs démonstrations au cours de ces dernières années avec un exploit iBoot grâce auquel il peut demarrer l’iPhone en mode verbose (toutes les lignes blanches qui apparaissent). Il a aussi la possibilité de charger un autre noyau sans que l’iBoot ne vérifie l’integrité de celui-ci et aussi de désactiver les différentes sécurités du kernel. On peut citer Apple Mobile File Integrity (et son daemon amfid) qui est une extension du noyau (kext) permettant de renforcer la signature du code sur iOS.

Malheuresement l’iBoot est exploitable seulement si l’appareil est déjà jailbreak.

En résumé, si vous controlez la séquence de demarrage d’iOS, vous controlez tout le système.

Kernel

En fait c’est pas vraiment le kernel, mais plutot le kernelcache car il contient le fameux noyau XNU mais aussi les différentes extensions : les kexts.

Voici la dernière étape de la boot chain. Après que l’iBoot ai vérifié que tout est nickel dans le kernel (sisi la rime) celui-ci va initialiser les entrées et sorties, la sandbox et le codesigning (la vérification des signatures des différents executables d’iOS), bref il fait son job de noyau.

En plus de tout ça avec les versions un peu plus récentes d’iOS, de nouvelles fonctionnalités sont apparu notamment [K]ASLR ([Kernel] Address Space Layout Randomization) qui est une technique pour éviter les corruptions de mémoire en obtenant l’adresse en mémoire du kernel.

De plus les applications lancées après que le kernel ai booté sont dans une Sanbox, c’est à dire que l’execution des apps est limitée. Par défaut les apps de l’App Store n’ont pas accès à vos données personnelles tel que les photos, ou bien la possibilité de modifier les fichiers systèmes.

KPP

Avec l’arrivée d’iOS 9 est apparu une nouvelle fonctionnalité visant à empecher le kernel d’être patché : Kernel Patch Protection. KPP va vérifier aléatoirement l’integrité des pages de la mémoire du kernel qui sont en RX (Read/Execute) à l’aide du SEP. Il semble que le but de KPP est donc d’empecher désactiver AMFI ou la sandbox.

Voici le type d’erreur lorsque l’ont tente de modifier une page en RX :

panic(cpu 1 caller 0xffffff80098fde28): SError esr: 0xbf575401 far: 0xffffff8009898000

Cette erreur conduit à un kernel panic. Il est donc plus difficile depuis iOS 9 d’appliquer un jailbreak untethered, qui permet de rester jailbreak après un redemarrage. Mais maintenant que les kernelcaches sont livrés non chiffrés dans les versions d’iOS publiques (merci radian) il est quand même plus facile d’y jeter un oeil.

kppshit

Et oui grace à joker on peut isoler KPP en tant que Mach-O, thanks J Levin !

$ joker -dec kernelcache.release.n69
Feeding me a compressed kernelcache, eh? That is fine, now. I can decompress!
Compressed Size: 12476157, Uncompressed: 24707072. Unknown: 0xd83709d0, Unknown 1: 0x1
btw, KPP is at 12476593 (0xbe60b1)..And I saved it for you in /tmp/kpp
Got kernel at 437
This is a 64-bit kernel from iOS 10.x (b7+), or later (3789.42.2.0.0)
ARM64 Exception Vector is at file offset @0x7f000 (Addr: 0xfffffff007083000)
$ file /tmp/kpp
/tmp/kpp: Mach-O 64-bit 64-bit architecture=12 executable

KPP (ou Watch Tower) est donc une sorte de Trust Zone.

BONUS : Voici un parfait exploit pour iOS 10.2 (Pré-i7) qui inclut les différents patches pour la sandbox et AMFI ainsi que le “bypass” de KPP par Luca Todesco et Marco Grassi. C’est un jailbreak.

Secure Enclave Processor

L’arrivée de l’iPhone 5S a introduit les premiers appareils iOS 64 bits sur la marché, ainsi que Touch ID qui permet de déverrouiller votre iPhone avec votre empreinte digitale.

C’est le SEP qui va donc se charger de chiffrer les empreintes digitales qui sont des données sensibles, mais aussi votre code de verrouillage. Et même si le kernel d’iOS a été compromit l’integrité des données qui passe par le SEP est toujours valide.

Le SEP est un co- processeur ARM qui a sa propre bootchain ainsi que son propre système d’exploitation : un kernel, des drivers, services et applications qui tournent en tant que Mach-O. L’OS nommé SEPOS il est au format IM4P comme ses camarades de la bootchain iOS.

Celui-ci a la particularité de communiquer avec KPP, en effet lors de l’initialisation du proc, une région du SEP nommé TZ1 (Trust Zone 1) est configurée pour Watch Tower.

SEPOS est tout comme son confrère Mach, un microkernel. C’est un fork de L4Ka::Pistachio (ARMv7 32 bits) modifié par la Pomme pour tourner sur le SEP.

Voici l’architecture du SEPOS.

separch

Le kernel du SEP ne fourni que le strict minimum avec environ 20 appels systèmes (syscalls pour les anciens). Certains appels peuvent avoir plus de privilèges que d’autres, comme L4_MapControl qui va mapper ou liberer de la mémoire virtuelle pour le kernel.

Seul le processus initial aussi nommé la root task peut appeler ces type syscalls qui ont des privilèges plus élevés.

Lors du demarrage du SEP le processus inital va utiliser les syscalls du kernel L4 pour initialiser SEPOS et ainsi activer les différentes tâches et processus. Puis il la root task va demarrer un serveur premettant au différentes applications de communiquer entre elles.

Conclusion

J’espère que vous comprenez maintenant pourquoi votre iPhone met tant de temps à démarrer :P. Avec l’arrivée d’Apple File System sur iOS 10.3 beta cela pourrait augmenter la vitesse de demarrage de l’iPhone, à voir.

J’ai survolé le jailbreak d’iOS 10.2, mais il faut savoir que ce type de jailbreak va devenir commun au fur et à mesure, car il n’y a plus besoin de travailler sur la persistance. Le simple fait de relancer une app après chaque redemarrage pour être de nouveau jailbreak est un gage de sécurité.

Quand j’aurai moins la flemme je ferai un page dédiée à toutes les ressources (slides, papers, videos) sur la sécurité iOS puis une autre pour Linux.

Si vous avez besoin d’infos contactez-moi sur twitter: @matteyeux 

Github : https://github.com/matteyeux