2 points par GN⁺ 2024-10-08 | 1 commentaires | Partager sur WhatsApp
  • Une expérimentation visant à démarrer une build iPhone XR d’iOS 15.0.2 jusqu’à PreBoard.app en utilisant Virtualization.framework sur Mac Apple silicon et l’environnement vma2
  • Le cœur de l’approche consiste à réutiliser la chaîne de démarrage de macOS 12.0.1 et à ne remplacer que l’image système iOS, mtree, root_hash et trustcache, afin de réduire la charge liée à la modification de la chaîne de démarrage initiale
  • En appelant l’API privée _setProductionModeEnabled(false) pour abaisser la VM à l’état CPFM 01, TSS signe des firmwares arbitraires pour les appareils vma2 publics, ce qui réduit le besoin de l’ancienne approche vma2pwn
  • Le démarrage réel nécessite des patches noyau et système touchant les vérifications de plateforme XNU, le system keybag, les contrôles de taille IOMFB, le ramdisk, launchd, mount, le DYLD shared cache, lockdownd et mobileactivationd
  • Le principal problème non résolu reste la compatibilité du system keybag ; il n’est pas encore confirmé non plus que la saisie tactile soit possible via les API privées de Virtualization.framework

Objectif de l’expérimentation et point de départ

  • Après la transition vers Apple silicon et Mac Catalyst, iOS et macOS se sont rapprochés ; avec la possibilité de virtualiser macOS, la question centrale est devenue de savoir si iOS pouvait lui aussi être virtualisé en modifiant une chaîne de démarrage de la même famille
  • Le travail précédent, vma2pwn, était un projet visant à créer une chaîne de démarrage macOS vma2 modifiable pour les VM invitées macOS, et sert de base à cette expérimentation
  • Parmi les exemples publics aboutis de virtualisation/émulation d’iOS figure le produit virtual iPhone cloud de Corellium
  • qemu-t8030, des travaux basés sur QEMU et les articles de Zhuowei Zhang ont aussi servi de référence ; en particulier, la relation entre IOSurfaceRoot sur macOS et IOCoreSurfaceRoot sur iOS a aidé ensuite à explorer les patches noyau
  • L’article de Zhuowei Zhang considérait que les apps macOS à interface graphique ne peuvent pas s’exécuter sur iOS, mais que les apps iOS graphiques peuvent s’exécuter sur macOS ; cette propriété s’applique aussi à une grande partie du système graphique d’iOS

Fonctionnalités privées de Virtualization.framework

  • Le Virtualization.framework d’Apple contient une fonction privée non documentée, _setProductionModeEnabled(false)
  • Cet appel, ainsi que la fonctionnalité correspondante dans la configuration de la VM, abaissent la VM au Chip Fuse Mode CPFM 01, configurant l’appareil virtuel dans un état à la fois « secure » et « non-production »
  • Sur un appareil physique, TSS refuse de signer les blobs SHSH nécessaires aux appareils non-production/non-secure tels que CPFM 00 ou 01
  • Pour les appareils vma2 publics, TSS signe le firmware arbitraire fourni, ce qui réduit fortement la nécessité de l’approche vma2pwn, qui consistait à construire une chaîne de firmware modifiée

Méthode de configuration de la VM iOS

  • L’approche qui a le mieux fonctionné consiste à conserver telle quelle la chaîne de démarrage de macOS 12.0.1 et à remplacer l’image de l’OS système par l’image et les fichiers associés de la build iPhone XR d’iOS 15.0.2
    • Les éléments remplacés sont l’image système, mtree, root_hash et trustcache
    • Cette méthode contourne en grande partie la nécessité de modifier la chaîne de démarrage et le ramdisk de récupération avant l’initialisation d’iOS
  • La build iPhone XR a été choisie en raison de sa prise en charge arm64e et de la possibilité d’une résolution plus faible
  • D’autres configurations d’appareils arm64e pourraient aussi réussir, mais le noyau vma2 est codé en dur pour renvoyer "iPad8,6" pour certaines clés sysctl
  • Les builds arm64 ont rencontré des problèmes supplémentaires et des incompatibilités binaires, et ont donc été jugées peu intéressantes à tenter
  • Pour exécuter la VM, l’auteur utilise super-tart, un fork de tart, une app tierce de gestion de VM Apple silicon
    • super-tart permet d’utiliser les fonctionnalités privées nécessaires de Virtualization.framework
    • Certaines modifications, comme le changement de réglage _setProductionModeEnabled(false), n’ont pas encore toutes été poussées
    • Les outils Virtualization.framework utilisant des API privées nécessitent de désactiver SIP, et il peut aussi être nécessaire de désactiver AMFI
  • Un fork d’idevicerestore est utilisé comme outil de restauration

Patches noyau

  • Le patch de vérification de signature utilisé dans vma2pwn peut être nécessaire, mais il n’est pas certain qu’il le soit absolument avec l’approche CPFM 01
  • Les patches liés aux signatures consistent à faire en sorte que les fonctions suivantes du noyau vma2 renvoient 0
    • _apfs_extract_root_hash_arm
    • _authenticate_root_hash
    • __img4_firmware_property_callback
    • _is_root_hash_authentication_required
    • _img4_firmware_evaluate
  • lookup_in_static_trust_cache doit être patché pour renvoyer 1
  • Comme les binaires iOS ne sont pas des binaires de plateforme simulateur, ils se terminent initialement avec EXEC, [0xe] Binary with wrong platform
    • Le problème se résout en patchant XNU pour sauter la ligne de vérification PLATFORM_IOS
    • Dans le noyau vma2, cela s’applique en remplaçant B.NE par B
  • En raison de l’incompatibilité du system keybag, PreBoard.app affiche « Swipe up to upgrade. » au lieu de Setup.app
    • En appliquant deux patches à ipc_make_system_keybag pour forcer la fonction à ne pas renvoyer d’erreur, il est possible d’atteindre PreBoard.app
    • Cette limite n’est pas encore totalement résolue
  • L’inadéquation de taille de la structure IOMFB entre les frameworks système iOS et le noyau macOS provoque une panique noyau avec la chaîne CLCDTransaction size mismatch. Returning error 0x%X.
    • Supprimer le contrôle de taille dans IOMobileFramebufferUserClient::swap_submit arrête la panique

Préparer les patches de fichiers système

  • Le ramdisk de récupération et les fichiers système iOS étant signés, ils se terminent à l’exécution s’ils ne sont pas resignés après patch
  • Dans l’environnement modifié, l’utilisation de ldid de Procursus est suggérée
    • Exemple d’installation : brew install ldid-procursus
    • Exemple de resignature : ldid_macosx_arm64 -S -M <binary>
    • -S pseudo-signe le binaire et -M conserve les entitlements existants
  • De nombreux binaires effectuent des vérifications d’identité ; avant resignature, il faut donc les renommer avec leur identity, puis les remettre à leur nom d’origine
    • keybagd confirme Identifier=com.apple.keybagd avec codesign -d -v keybagd
    • mv keybagd com.apple.keybagd
    • ldid_macosx_arm64 -S -M com.apple.keybagd
    • mv com.apple.keybagd keybagd
  • Les fonctions qui ne reçoivent pas automatiquement de symboles peuvent être trouvées en recherchant des XRef de chaînes, puis en suivant les fonctions appelantes via les références aux appels de journalisation
  • Pour obtenir un shell interactif sur le terminal série, il est possible de porter Bash et un LaunchDaemon
    • La méthode utilisée consiste à copier les fichiers associés depuis un payload de jailbreak iOS compatible en version, comme Procursus

Modification des DMG et du ramdisk

  • Pour patcher le système ou le ramdisk de récupération, il faut modifier directement le volume DMG
  • Dans l’exemple iOS 15.0.2, le volume iOS System inclus dans l’IPSW est converti en format lisible/inscriptible
    • hdiutil convert -format UDRW -o 018-66258-074-rw.dmg 018-66258-074.dmg
    • Après montage : sudo mount -uw /Volumes/Sky19A404.N104N841OS
    • Après modification : hdiutil convert -format ULFO -o 018-66258-074.dmg 018-66258-074-rw.dmg
    • Puis asr imagescan --source 018-66258-074.dmg
  • Avant le démarrage d’iOS, il faut modifier /usr/local/bin/restored_external dans le ramdisk de récupération
    • La version iOS de restored_external tente de créer le system keybag avec MKBKeyBagCreateSystem, mais ce n’est pas compatible avec le noyau macOS
    • Le contournement consiste à supprimer la vérification d’erreur
    • En patchant la condition d’appel de ramrod_set_NVRAM_variable, allow-root-hash-mismatch est réglé à true, c’est-à-dire 1, et l’authentification du root hash est ignorée
  • Il faut aussi modifier /usr/sbin/asr dans le ramdisk de récupération
    • asr64_patcher d’iSuns9 peut être utilisé
    • Il faut trouver la fonction qui affiche la chaîne "Image failed signature verification.", puis, dans la fonction qui la référence, remplacer l’appel ARMv8-A BL par un saut B vers le chemin "Image passed signature verification"
    • Dans le binaire asr d’iOS 15.0.2, b #0x7c est appliqué à l’offset fichier 0x27A18

Modification du volume système iOS

  • Pour adapter iOS lui-même au noyau macOS, la plupart des fichiers installés à la racine du système de fichiers doivent être déplacés dans /System/Library/Templates/Data sur le volume système
  • Une fois le système démarré, ces fichiers se trouvent dans /
  • Les dossiers vides de la racine ordinaire peuvent devoir rester sur le volume système même s’ils sont effectivement vides
    • Par exemple /Applications
    • Cette partie n’a pas été suffisamment testée

Patches de launchd et keybagd

  • Au début du démarrage d’iOS, /sbin/launchd s’exécute, et des patches sont nécessaires pour lancer le processus de démarrage initial sans échec
  • Le premier patch s’applique à la plist de configuration intégrée dans le binaire
    • Il faut chercher la chaîne <key>SIGTERMTimeout</key> et regarder environ 172 octets avant pour trouver le paramètre concerné
    • Ajouter <key>PerformAfterUserspaceReboot</key><true/> aux sections mount-phase-2, fips, tzinit, finish-demo-restore, fud, xpcroleaccountd, prng_seedctl et MSUEarlyBootTask
    • Changer RequireSuccess de la section data-protection en <false/>
  • La modification de data-protection est nécessaire parce que /usr/libexec/init_data_protection échoue lorsqu’il est exécuté dans la VM
    • Ce fichier est un lien symbolique vers /usr/libexec/seputil
  • Comme les modifications de la plist intégrée peuvent dépasser l’espace de chaînes existant, il est possible de coller un XML compressé avec un minimizer XML, puis de remplir la zone restante avec des espaces compatibles XML
  • launchd initialise aussi /usr/libexec/keybagd, mais ce binaire échoue en raison des différences de noyau précédentes
    • Un contournement consiste à compiler un exécutable qui se termine simplement avec le code de sortie 0 et à remplacer keybagd par celui-ci
    • Le projet fixkeybag a aussi été examiné, mais son code de création de system keybag appelle lui aussi MKBKeyBagCreateSystem, et échoue donc même dans l’état iOS démarré
  • launchd nécessite un patch supplémentaire qui remplace par NOP la branche conditionnelle TBZ déclenchant la chaîne de panique Userspace reboot changed system version: previous %s != current %s

Modification de mount, du DYLD shared cache et de la couche graphique

  • Comme la chaîne de démarrage macOS et le ramdisk macOS gèrent le processus de restauration, le /sbin/mount d’iOS ne traite pas correctement les volumes APFS créés
  • La solution consiste à prendre le binaire mount du volume système macOS, à modifier ses métadonnées Mach-O pour qu’il puisse s’exécuter sur iOS, puis à le remplacer
    • Cela peut se faire manuellement, ou avec vtool, inclus dans macOS
  • La modification plus difficile concerne le DYLD shared cache
    • IOSurfaceRoot sur macOS et IOCoreSurfaceRoot sur iOS sont fondamentalement le même pilote, mais ils sont incompatibles à cause de la différence de nom
    • Le DYLD shared cache d’iOS contient la chaîne plus longue "IOCoreSurfaceRoot" ; il faut donc la remplacer par "IOSurfaceRoot" et remplir les octets restants avec 0x00
  • L’outil ipsw de blacktop est utilisé pour analyser et extraire le DYLD shared cache
    • ipsw dyld split <dsc file> sépare les dylib intégrées
    • Dans le binaire /System/Library/Frameworks/IOSurface.framework/IOSurface, il faut trouver la référence à "IOCoreSurfaceRoot" dans la fonction __iosConnectInitalize
    • ipsw dyld a2o convertit l’adresse virtuelle en offset fichier
    • Dans l’exemple, l’offset 0x28fde373 de dyld_shared_cache_arm64e est patché
  • Après modification du DYLD shared cache, une exception se produit parce que le cdhash d’un autre emplacement ne correspond plus
    • Le GDB stub fourni par le frontend Virtualization.framework permet de placer un breakpoint sur la fonction noyau cs_validate_hash afin de vérifier le cdhash complet
    • Dans l’exemple iOS 15.0.2, les anciens octets à l’offset fichier 0x5a9cffc0 sont patchés avec le nouveau cdhash

Patches des démons système et de l’activation

  • watchdogd vérifie s’il s’exécute dans une VM et provoque une boucle de crash, car il n’existe pas de chemin de code macOS permettant une sortie normale, mais ce crash est considéré comme inoffensif
  • Dans backboardd, des patches d’appels liés à la migration des données susceptibles de déclencher PreBoard.app ont été expérimentés, mais aucune différence n’a été observée en dehors d’un blocage sur le logo Apple
  • Dans la fonction get_device_type_internal_block_invoke de lockdownd, l’appel getMGInt pour "ShouldHactivate" est patché en mov x0, #1 afin de forcer la hactivation, qui contourne les restrictions d’activation iOS normales en environnement de développement
  • mobileactivationd peut aussi être patché pour autoriser la hactivation
    • La fonction shouldHactivate est remplacée par les instructions ARMv8-A mov x0, #0 et ret
  • Les modifications supplémentaires nécessaires au device tree vma2 sont laissées au lecteur
  • Certaines opérations peuvent nécessiter des mesures non conventionnelles comme chmod -R 777 /

Limites restantes et saisie tactile

  • Pour dépasser le problème du system keybag, il faut mieux comprendre la structure correspondante dans le système iOS et le noyau, puis créer des patches supplémentaires
  • Le projet a déjà demandé au moins plusieurs centaines d’heures, et l’état d’avancement public actuel se limite à un démarrage jusqu’à PreBoard.app
  • Il n’est pas encore confirmé que la fonction tactile fonctionne via le noyau et le firmware publics vma2 Mac
  • Virtualization.framework contient des API privées liées au tactile
    • _VZAppleTouchScreenConfiguration
    • _VZUSBTouchScreenConfiguration
    • _VZTouch
    • _VZMultiTouchEvent
  • Ces API peuvent envoyer des événements tactiles, mais l’usage exact des paramètres n’est pas entièrement compris
    • L’enum TouchPhase est une enum simple implémentant les valeurs du même nom que NSTouch.Phase
    • Le code d’exemple peut parfois générer des exceptions
    • Il n’est pas non plus confirmé que les coordonnées soient mappées comme la VM l’attend, ni que la VM puisse les traiter
  • La démo montre la séquence de démarrage, avec une attente d’environ 30 secondes au milieu qui a été coupée

1 commentaires

 
GN⁺ 2024-10-08
Avis sur Hacker News
  • Corellium a gagné son litige, ce qui lui permet de louer des VM iOS dans le cloud pour la recherche en sécurité https://hn.algolia.com/?query=corellium
    Si l’on peut virtualiser iOS sur un MacBook Apple Silicon, la demande pour des services commerciaux de virtualisation iOS pourrait diminuer
    Les particuliers paient environ 400 $ par mois, et les entreprises 60 000 $ par an https://support.corellium.com/subscriptions/pricing

    • Mon Dieu, c’est 4 à 8 $ de l’heure ; je me demande qui paie pour ce genre de VM
  • Bonne nouvelle. La prochaine étape, ce serait de trouver comment installer macOS sur un iPad, pour qu’on puisse enfin utiliser cet ordinateur qu’on espérait voir Apple fabriquer

    • On peut commencer par Windows XP
      https://www.theverge.com/2024/7/22/24200536/windows-xp-ipad-...
    • D’après la partie sur les travaux antérieurs, [Zhuowei Zhang] a conclu que les applications macOS avec GUI ne peuvent pas s’exécuter sur iOS, mais que les applications iOS graphiques peuvent s’exécuter sur macOS
      Mac Catalyst semble aussi fonctionner dans un seul sens, comme prévu
    • Tellement d’accord, mille fois. Ces dernières semaines, je cherchais exactement ça : une tablette avec un système d’exploitation pour le développement
      En termes de taille, l’iPad Mini serait idéal, mais iPadOS est inutile ; en ce moment je regarde du côté de la Surface Go. Elle est toutefois un peu grande
      Je sais qu’il n’existe pas de produit avec macOS, mais si quelqu’un a une recommandation de petite tablette compatible Win11, je suis preneur. Je suis même prêt à commander en Chine si nécessaire
    • L’iPad Pro est l’appareil le plus rapide équipé du M4
    • Si on l’appelle un MacBook Air avec une excroissance à l’envers et un clavier détachable, ça suffit ?
  • À voir le profil GitHub de l’auteur, il semble tout juste diplômé en informatique ; c’est un travail vraiment impressionnant

    • Je pense qu’une offre d’embauche d’Apple ne devrait pas tarder
  • J’ai l’impression qu’Apple n’a pas fait du Simulator un Emulator parce qu’ils ne veulent pas que les gens fouillent dans les couches internes d’iOS

    • Une autre raison pour laquelle c’était un Simulator dès le départ, et non un Emulator, pourrait être qu’à l’époque beaucoup de composants d’iOS, ou d’iPhone OS, étaient des forks de bibliothèques Mac OS X existantes
    • Des développeurs utilisent encore des Mac Intel, sur lesquels on ne peut pas virtualiser iOS ARM
    • Maintenant que l’iPhone, le Mac et l’iPad sont tous en arm64, et même basés sur Apple Silicon, je me demande vraiment à quel point les bootloaders d’iOS et de macOS diffèrent
      Une fois le bootloader passé, surtout quand Apple contrôle aussi le matériel, je me demande s’il y a vraiment une raison de maintenir autant de différences entre les deux systèmes d’exploitation
  • La personne qui a créé qemu-t8030 a réussi à lancer SpringBoard https://mastodon.social/@ntrung03/109712247237110967, mais n’a pas publié le code
    Ce serait formidable si cette avancée pouvait être combinée avec le présent travail

  • Ancien commentaire : https://news.ycombinator.com/item?id=40219423

  • Article lié : https://worthdoingbadly.com/hv/
    Il traite des machines virtuelles accélérées matériellement sur un iPhone 12 jailbreaké / iOS 14.1

  • C’est un peu hors sujet, mais je me demande si quelqu’un a déjà virtualisé macOS ARM sur x86-64

    • C’est impossible. En général, « virtualisation » signifie exécuter un système d’exploitation via la virtualisation matérielle : le CPU hôte exécute le code nativement et délègue toutes les entrées/sorties à l’hyperviseur
      On ne peut donc virtualiser que des systèmes d’exploitation compilés pour la même architecture CPU que le système hôte
      Dans les autres cas, par exemple exécuter du logiciel ARM sur x86 ou l’inverse, il faut passer par l’émulation, qui interprète le code ou le recompile dynamiquement
      Par définition, n’importe quoi peut être émulé sur n’importe quoi d’autre. Récemment, on a même vu Linux pour MIPS démarrer sur le tout premier microprocesseur, l’Intel 4004, mais les performances peuvent poser problème
    • Si vous virtualisez de l’ARM générique dans QEMU, vous verrez que les performances sont inférieures à celles d’un Raspberry Pi. Les versions récentes devraient l’inclure par défaut
      Virtualiser des CPU Mn serait encore moins utile, à mon avis
    • Il vaudrait la peine de regarder du côté des projets Hackintosh
  • Apple fournit déjà un iOS Simulator dans Xcode ; je me demande en quoi ce projet est meilleur que les outils fournis par Apple

    • Le Simulator n’exécute pas un véritable iOS ni un build iOS de l’app. Quand on lance une app dans le Simulator, elle est compilée pour le jeu d’instructions natif du Mac actuel, puis liée à des frameworks et bibliothèques Mac qui imitent le comportement attendu d’iOS, ou n’en fournissent parfois qu’une coquille
      Par exemple, on ne peut pas prendre un binaire iOS depuis l’App Store et l’exécuter tel quel dans l’iOS Simulator, encore moins sur un Mac Intel
      Comme le Simulator n’exécute pas un iOS complet, il ne permet pas non plus d’étudier et de comprendre le fonctionnement interne réel d’iOS. Si l’on creuse suffisamment profondément dans les frameworks du Simulator, on finit par retomber sur macOS
      Un émulateur, en revanche, exécute un build complet d’iOS identique à celui d’un vrai appareil. En théorie, il peut exécuter n’importe quel binaire iOS sans modification et permettre d’étudier le fonctionnement du véritable système d’exploitation
      C’est comparable à la différence entre exécuter une app avec Wine et l’exécuter dans une VM Windows. Sauf que, dans le cas du Simulator, c’est plutôt comme s’il fallait recompiler et lier séparément l’app pour l’environnement Wine avant d’exécuter une app Windows
      Si vous voulez étudier les entrailles de Windows, vous n’apprendrez pas grand-chose en lançant simplement Wine, alors qu’en examinant une VM Windows, vous en apprendrez beaucoup plus
  • Ce sera un cadeau de Noël en avance pour les fermes à clics