Ghidra est un logiciel libre et open-source permettant de faire du reverse engeneering sur des programmes exécutables (binaires), y compris les applications mobiles.
L’objectif ici est de comprendre le fonctionnement de base et les étapes à suivre pour contourner une protection « Anti-Jailbreak » au sein d’une application iOS.
Pour rappel, s’assurer que l’application fonctionne sur un environnement non rooté / non jailbreaké fait partie des meilleures pratiques de sécurité recommandées par l’OWASP.
Le reverse de l’application est une technique parmi d’autres. En effet, l’utilisation de Frida peut permettre d’éviter cette modification. Néanmoins, ayant déjà beaucoup parlé de Frida, il est temps de sauter le pas et de passer du côté sombre de la force, le reverse.
Installation de Ghidra
Afin de disposer de l’ensemble des fonctionnalités de Ghidra, il est nécessaire d’avoir :
- La dernière version de Ghidra
- La dernière version d’OpenJDK
- Le script python SavePatch
- L’application SecureStorev2.ipa à auditer
Rappel sur les IPA
Les fichiers IPA (iOS App Store Package) sont des archives compressées au format ZIP qui contiennent tout le code et les ressources nécessaires à l’exécution de l’application. Une fois au format ZIP, il est possible d’accéder à l’ensemble des informations présentes au sein de l’archive au sein du dossier Payload/.
Chaque fichier .ipa comprend un binaire et ne peut être installé que sur un appareil MacOS basé sur iOS ou ARM.
Contrairement aux applications Android, il n’est pas possible de décompiler une application iOS mais seulement
Allons dans les entrailles de cet IPA
Sans modification, l’application SecureStorev2 crash automatiquement au démarrage sur un périphérique jailbreaké alors qu’elle fonctionne parfaitement bien sur un périphérique non jailbreaké.
Les prérequis étant en place, il ne reste plus qu’à lancer Ghidra grâce au script ghidraRun, créer un projet :
Puis importer notre fichier binaire (au sein de l’IPA dezippé) :
Dès lors, le type de binaire est automatique identifié et le code désassemblé au sein de Ghidra :
La fonction de recherche de Ghidra est particulièrement puissante ! Il est possible d’effectuer des recherches par dichotomie ou bien d’utiliser des outils comme class-dump afin de savoir ou chercher les fonctions potentiellement intéressantes (isDeviceJailBroken dans notre cas) :
Sur la droite, il est possible d’avoir le code C de l’application, pratique pour une meilleure compréhension :
Il est alors possible de retrouver cette fameuse fonction isDeviceJailBroken et rentrant dans une fonction terminant par une fermeture du programme (exit()) en fonction du retour.
Comme au bon vieux temps des crack-me, il devient alors simplement nécessaire de modifier la condition pour entrer dans la fonction. Il est alors possible de changer le != en == en modifiant directement le code assembleur (tbz (Test bit and Branch if Zero) devient tbnz (Test bit and Branch if Nonzero)) :
Le changement peut se faire directement via Ghidra en faisant un clic droit sur l’instruction à modifier (tbz), choisir « Patch Instruction » puis remplacer par notre changement conditionnel (tbnz) :
La modification est donc effective au sein du code assembleur mais également au sein du code C changeant ainsi le fonctionnement de la fonction isDeviceJailBroken :
Sauvegarde de l’IPA
Une fois les modifications apportées, il est nécessaire à présent de sauvegarder notre fichier binaire. Ghidra ne prenant pas en compte par défaut la sauvegarde des binaires corrigés, il est nécessaire de faire appel au script SavePatch.
Pour cela, il est nécessaire d’inclure le fichier dans le « Script Manager » :
Une fois le script SavePatch inclus, il est possible de l’exécuter en cliquant deux fois dessus. Dès lors, il est nécessaire de spécifier l’adresse de début du patch (adresse de l’instruction tbz) et la taille du patch (j’ai pris pour habitude de mettre 2048).
Il ne reste plus qu’a sauvegarder ce binaire en remplaçant le binaire initial, recréer le fichier zip, le renommer en IPA.
La fonction de détection de jailbreak n’étant plus, l’application est à présent en mesure de se lancer sans problème :
Conclusion
Bien que l’utilisation de Frida puisse être plus pratique car un même script peut être réutilisé dans le temps, il est nécessaire de garder en mémoire que d’autres techniques de contournement existent.
Pour les reverseurs, j’espère ne pas vous avoir fait trop mal aux yeux avec mes explications, pour les autres, j’espère que ce cas pratique vous sera utile.
Source
https://materials.rangeforce.com/tutorial/2020/04/12/Patching-Binaries/