4 points par GN⁺ 2025-04-07 | 1 commentaires | Partager sur WhatsApp

Début du parcours d’émulation d’iOS 14 avec QEMU

  • Le projet open source existant alephsecurity/xnu-qemu-arm64 a été utilisé au départ, mais comme il était en lecture seule (read-only), il posait des problèmes de manque d’extensibilité
  • Le projet TrungNguyen1909/qemu-t8030 a ensuite été utilisé, ce qui a permis de tirer parti des fonctions suivantes :
    • Fonction de restauration iOS (avec un QEMU compagnon pour la connexion USB)
    • Exécution d’iOS 14
    • Basé sur une version récente de QEMU
    • Documentation wiki détaillée
  • En modifiant launchd.plist, l’accès au shell et en SSH a été obtenu, ce qui en a fait un bon point de départ
  • L’objectif est de construire un environnement d’émulation iOS complet capable d’exécuter l’interface UI et les applications

Patches noyau et adoption de PongoOS

  • Le projet t8030 appliquait les patches noyau directement dans QEMU → problèmes de maintenance et d’extensibilité
  • Fort de l’expérience du jailbreak, l’approche a été remplacée par une application des patches checkra1n via PongoOS
  • Exécution de PongoOS en augmentant la taille de la SRAM dans QEMU, puis injection du module checkra1n-KPF
  • Au démarrage, des fonctions absentes dans la bootrom et iboot provoquaient un problème de FPU non configurée → résolu en s’appuyant sur la documentation ARM
  • Depuis l’A13, l’introduction de PAC (Pointer Authentication) a rendu certains patches inopérants
  • Comparaison de binaires avant/après l’introduction de PAC avec l’exemple de task_for_pid0 (tfp0)

Développement d’un outil d’automatisation des patches noyau

  • L’ancienne méthode de patch dynamique de checkra1n était difficile à lire et peu pratique à modifier → adoption d’un format déclaratif de patchs textuels
  • Création de patchs texte après extraction des différences d’assembleur en comparant deux binaires Mach-O
  • Après démarrage via Pongo, dump mémoire puis réassemblage du noyau → tous les patches ont été organisés et commentés dans des fichiers texte

Rendu graphique : Metal vs rendu logiciel

  • iOS effectue tout le rendu de l’interface via l’API Metal → besoin d’un GPU
  • L’émulation GPU étant complexe, d’autres pistes ont été envisagées :
    • rendu logiciel
    • proxy des appels Metal vers un appareil physique
  • Dans iOS 14, le bootarg gpu=0 a été supprimé → analyse de QuartzCore pour vérifier le comportement de repli
  • En patchant QuartzCore sur un iPhone jailbreaké, le rendu logiciel a été validé (lent, mais fonctionnel)
  • Une approche de proxy Metal a aussi été testée, mais abandonnée à cause de la complexité d’Objective-C et de l’API

Débogage du framebuffer et d’IOSurface

  • Le QEMU de t8030 n’implémente pas de framebuffer → utilisation du fork ChefKissInc/QEMUAppleSilicon
  • Au démarrage initial, le logo Apple et l’indicateur de progression apparaissaient, puis écran noir → début du débogage
  • L’analyse du kext IOMFB a révélé deux modes :
    • framebuffer à adresse fixe (pour l’affichage initial)
    • configuration multi-plan basée sur DMA
  • Pendant le boot du système, le mode basé sur DMA est utilisé → vérification via les traces QEMU de la configuration des registres noyau
  • Malgré cela, toujours aucune sortie à l’écran

Désactivation de la randomisation des adresses

  • La randomisation des adresses du noyau peut être désactivée dans le code d’initialisation de la carte
  • La randomisation de l’espace utilisateur a été désactivée en patchant _load_machfile
  • Le cache dyld est un gros binaire contenant toutes les bibliothèques dynamiques → il est chargé à une adresse fixe au démarrage
  • Un outil en C a été créé pour faire un dlopen, puis vérifier les adresses avec les fonctions _dyld_*
  • Le débogage de la bibliothèque dyld a ainsi été rendu possible avec GDB → intérêt particulier pour IOMFB, SpringBoard et QuartzCore

Accès aux logs via USB et contournement de lockdownd

  • Sur un appareil réel, il est possible de collecter les logs système avec idevicesyslog → nécessite une authentification USB
  • lockdownd utilise un keybag nécessitant le SEP pour stocker les clés → absent dans l’émulateur
  • Du shellcode a été inséré à la place d’une fonction existante afin de charger directement depuis un fichier de clés
  • Le contournement de l’authentification par clés entre QEMU connectés en USB a réussi → collecte des logs possible
  • Confirmation que QuartzCore s’initialise correctement et utilise le rendu logiciel

Contournement de PAC (Pointer Authentication)

  • Une erreur PAC est apparue lors de la modification de backboardd → fonctionnalité de sécurité introduite avec ARMv8.3
  • Remplacer les instructions PAC par des NOP était trop intrusif
  • Les instructions PAC peuvent être compilées de manière compatible → l’exécution devient possible si QEMU ignore PAC
  • QEMU 7 ne permettait pas de contourner PAC → migration vers QEMU 8.2.1
  • Il a fallu porter de nombreux morceaux de code custom QEMU, notamment des instructions spécifiques à Apple et les niveaux d’exception GL
  • Résultat : démarrage réussi d’iOS sur QEMU 8 et neutralisation possible de PAC

Vérification de backboardd et de la sortie graphique

  • backboardd fonctionne, mais rien ne s’affiche à l’écran → plusieurs causes possibles
  • Même en dumpant la mémoire DMA, aucune sortie significative n’a été observée
  • L’adresse a été retrouvée dans iosurface_lock et des frames ont été dumpées, mais elles semblaient envoyées au GPU sous une forme compressée
  • Sur l’iPhone X (t8015), une sortie non compressée a été confirmée → modification du DTB de QEMU pour changer le chip-id de t8030 à t8015
  • Résultat : le logo Apple s’est affiché après le démarrage

Barre de progression et suivi des erreurs système

  • Après le logo, une barre de progression blanche s’affiche → blocage à 90 %
  • L’analyse des logs a révélé des problèmes dans mobileactivationd et SpringBoardFoundation → l’interface a changé après patch
  • Pour résoudre ce blocage de progression, il a fallu analyser un grand nombre de logs système

Automatisation des patches du cache dyld et de l’espace utilisateur

  • Comme pour le noyau, l’espace utilisateur a adopté une méthode de patchs textuels
  • Le cache dyld fait 2 Go et est inefficace à modifier → amélioration des outils internes pour :
    • suivre les offsets dans dyld
    • patcher directement des positions spécifiques avec la commande dd
  • Il a aussi fallu appliquer en parallèle un patch de contournement de la vérification de signature du noyau

Exécution de PreBoard et vérification de l’interface

  • L’application PreBoard est une application système affichée en cas d’erreur → elle peut être exécutée directement
  • Un serveur VNC a été ajouté afin de tenter un déverrouillage de l’écran au clavier
  • Après le déverrouillage, le framework vImage utilisait des instructions AMX (Apple Matrix Coprocessor) → non prises en charge par QEMU
  • Le problème a été résolu en patchant vers le chemin de repli logiciel de vImage
  • Après patch, l’affichage a pu aller jusqu’à un écran permettant la saisie de texte

Conclusion

  • Le système atteint désormais l’étape juste avant l’exécution de SpringBoard → le lancement d’une interface complète n’est plus qu’une question de temps
  • Des analyses et patches ont été menés sur plusieurs fronts : noyau, espace utilisateur, graphismes et fonctions de sécurité (PAC, etc.)
  • La possibilité d’un environnement concret de débogage et de test d’applications iOS basé sur QEMU a ainsi été démontrée

1 commentaires

 
GN⁺ 2025-04-07
Commentaires Hacker News
  • J’aimerais que le projet https://github.com/devos50/qemu-ios évolue au point de prendre en charge iPhone OS 3.x. Cela permettrait de redécouvrir les premières apps iPhone dans une optique de préservation numérique
  • https://github.com/touchHLE/touchHLE est également excellent, mais nécessite des correctifs pour autre chose que les apps de base
  • J’ai essayé de le lancer en suivant les instructions de https://github.com/TrungNguyen1909/qemu-t8030/…, mais il a planté plusieurs fois. Cela reste quand même assez impressionnant
  • J’ai déjà émulé les NumWorks N0100 et HP Prime G1 avec QEMU. C’était suffisamment abouti pour faire tourner le firmware officiel
  • Une manière amusante d’utiliser ce projet : installer postmarketOS sur un téléphone avec un bon support matériel, puis utiliser QEMU pour démarrer iOS sur un téléphone Android. Il devrait être possible de personnaliser QEMU pour transmettre le matériel du téléphone à la VM iOS
  • Je me demande si cela signifie qu’on pourrait tester Safari et compiler pour iOS sur un système Linux sans matériel Apple
  • https://github.com/ChefKissInc/QEMUAppleSilicon
  • Rien n’est mentionné au sujet de la connectivité réseau. Il ne semble pas y avoir d’émulation de chipset Wi‑Fi ou de modem cellulaire. Je me demande comment connecter l’appareil émulé à Internet. Cela pourrait passer par quelque chose comme Ethernet via USB
  • Version archivée : https://archive.ph/l1CwO
  • Je me demande s’il existe un dépôt permettant de reproduire cela
  • Je me demande ce qu’il faudrait pour qu’Apple accepte le développement iOS multiplateforme