
kfd, abréviation de kernel file descriptor, est un projet permettant de lire et d'écrire la mémoire du noyau sur les appareils Apple.
Avertissement rapide : je n'ai pas l'intention d'ajouter des offsets pour d'autres appareils et versions d'iOS.
kfd, abréviation de kernel file descriptor, est un projet pour lire et écrire la mémoire du noyau sur les appareils Apple. Il exploite diverses vulnérabilités qui peuvent être utilisées pour obtenir des PTEs pendants, ce qui sera appelé une primitive PUAF, abréviation de « physical use-after-free ». Ensuite, il réalloue certains objets du noyau dans ces pages physiques et les manipule directement depuis l'espace utilisateur via les PTEs pendants afin d'obtenir une primitive KRKW, abréviation de « kernel read/write ». Le code de l'exploit est entièrement contenu dans une bibliothèque, libkfd, mais le projet contient également de simples wrappers exécutables pour iOS et macOS. L'API publique de libkfd est assez réduite et intuitive :
enum puaf_method {
puaf_physpuppet,
puaf_smith,
puaf_landa,
};
enum kread_method {
kread_kqueue_workloop_ctl,
kread_sem_open,
};
enum kwrite_method {
kwrite_dup,
kwrite_sem_open,
};
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);
kopen() ouvre conceptuellement un « descripteur de fichier noyau ». Il prend les 4 arguments suivants :
puaf_pages: Le nombre cible de pages physiques avec des PTEs pendants.puaf_method: La méthode utilisée pour obtenir la primitive PUAF, avec les options suivantes :
puaf_physpuppet:
puaf_smith:
puaf_landa:
kread_method: La méthode utilisée pour obtenir la primitive kread() initiale.kwrite_method: La méthode utilisée pour obtenir la primitive kwrite() initiale.Si l'exploit réussit, kopen() renvoie un descripteur de fichier opaque de 64 bits. En pratique, il s'agit simplement d'un pointeur d'espace utilisateur vers une structure nécessaire à libkfd. Toutefois, étant donné que cette structure ne doit pas être accédée en dehors de la bibliothèque, elle est renvoyée sous forme d'entier opaque. Si l'exploit échoue, la bibliothèque affiche un message d'erreur, dort pendant 30 secondes, puis se termine avec un code de statut 1. Elle dort 30 secondes car le noyau pourrait paniquer à la sortie pour certaines méthodes PUAF qui nécessitent un nettoyage post-KRKW (par exemple puaf_smith).
kread() et kwrite() sont les équivalents côté espace utilisateur de copyout() et copyin(), respectivement. Veuillez noter que les options pour kread_method et kwrite_method sont décrites dans un write-up séparé. De plus, les primitives initiales accordées par ces méthodes peuvent être utilisées pour amorcer une meilleure primitive KRKW. Enfin, kclose() ferme simplement le descripteur de fichier noyau. Toutes prennent l'entier opaque renvoyé par kopen() comme premier argument.
Dans Xcode, ouvrez le dossier racine du projet et connectez votre appareil iOS.
Dans un terminal, placez-vous dans le dossier racine du projet.
Optionnellement, pour augmenter les limites de descripteurs de fichiers globale et par processus, ce qui améliorera le taux de réussite en particulier lors de plusieurs exécutions consécutives, entrez la commande make s et saisissez le mot de passe sudo.
make b.make r.make br.Ce README a présenté une vue d'ensemble de haut niveau du projet kfd. Une fois qu'une primitive PUAF a été obtenue, le reste de l'exploit est générique. Par conséquent, j'ai rassemblé la partie commune des exploits dans un write-up dédié :
De plus, j'ai réparti la partie spécifique à la vulnérabilité des exploits utilisés pour obtenir la primitive PUAF en write-ups distincts, listés ci-dessous dans l'ordre chronologique de leur découverte :
Cependant, veuillez noter que ces write-ups ont été écrits pour un public déjà familier avec le système de mémoire virtuelle XNU.