• CENTRE D’URGENCE | 24/7
  • Vous êtes victime d’une cyberattaque ?
  • Contactez notre centre d’urgence cyber :
  • +33 (0)1 83 07 00 06

Cas client : bypass anti-root sur une application Android

Lors des missions de test d’intrusion d’application mobile, l’analyse et le contournement des mécanismes anti-root et anti-virtualisation constituent une étape clé pour évaluer la résilience réelle d’une application Android face à un attaquant disposant d’un environnement contrôlé.

L’OWASP fournit plusieurs guides de bonnes pratiques et de méthodologies dédiés à la sécurité des applications mobiles :

Au travers d’un cas client, cet article met en lumière deux méthodes de contournement fréquemment rencontrées en audit mobile d’applications Android : le patching statique de l’APK (Android Package Kit) et le hooking dynamique à l’aide de Frida.

Par erwan.robin

Cas client : bypass anti-root sur une application Android

Contexte

Lors de nos tests d’intrusion, il arrive que certaines applications embarquent des mécanismes contre la modification et la rétro-ingénierie.

Dans le cadre de l’un de nos audits, nous avons été confrontés à l’utilisation de la librairie RootBeer, recommandée par l’OWASP. L’application, lorsqu’elle est lancée sur un terminal rooté ou virtualisé, affiche le message « Login not possible : rooted phone detected ».

Cas client : bypass anti-root sur une application Android

 

Nous allons voir deux méthodes distinctes pour contourner le mécanisme de détection implémenté dans cette application Android :

  • statiquement via la modification de l’APK ;
  • dynamiquement via Frida.

La première partie présentera les méthodes de récupération, d’analyse, de modification puis de déploiement de l’application. Dans la seconde, nous verrons l’utilisation de Frida pour s’attacher aux fonctions et en modifier le comportement.

Dans les étapes décrites ci-dessous, nous utiliserons l’outil Genymotion pour émuler un terminal Android disposant d’un environnement rooté.

Bypass statique : modification de l’APK

Récupération

Après avoir installé notre application via le Google Play, nous avons besoin de la récupérer en local pour pouvoir l’analyser et la modifier.

Pour ce faire, nous utilisons Android Debug Bridge (ADB) pour lister les paquets installés sur le téléphone :

Cas client : bypass anti-root sur une application Android

Nous récupérons alors le nom de notre application (« com.sysdream.app »), ce qui nous permet d’interroger l’emplacement des fichiers APK sur le téléphone :

Cas client : bypass anti-root sur une application Android

Comme l’indique la capture ci-dessus, 3 fichiers APKs sont identifiés (split APKs). Nous avons donc besoin de télécharger l’ensemble :

Cas client : bypass anti-root sur une application Android

Analyse

Maintenant que nous avons les fichiers en notre possession, nous pouvons analyser le code grâce à l’outil Jadx et la commande suivante : jadx-gui –deobf *.apk

Cet outil de rétro-ingénierie Android permet de convertir le bytecode Dalvik (DEX) en code Java lisible. Du moins, il fait de son mieux car il ne s’agit pas du code source tel qu’il a été écrit mais d’une reconstruction à partir du langage assembleur.

En parcourant le code obtenu, on s’aperçoit que l’application embarque RootBeer, une librairie permettant de détecter un matériel rooté au travers de plusieurs fonctions.

Cas client : bypass anti-root sur une application Android

 

Intéressons-nous à l’implémentation dans l’application. On retrouve une classe Java nommée RootDetection, qui importe la librairie RootBeer et l’utilise dans la fonction isRooted qui renvoie une valeur vraie ou fausse (‘boolean z’).

Cas client : bypass anti-root sur une application Android

 

Cette fonction inscrit la valeur de retour dans les journaux de l’application. Pour consulter les journaux Android, il est possible d’utiliser la commande adb logcat. Ici, on utilise l’outil Pidcat pour s’attacher à notre application à l’aide de la commande  pidcat.py com.sysdream.app

Au lancement de l’application, les journaux indiquent que plusieurs fichiers sont présents, indiquant un matériel rooté. À la suite, on retrouve la sortie de la fonction et la valeur true.

Cas client : bypass anti-root sur une application Android

 

Smali

Qu’est-ce que le Smali ? Il s’agit d’un type de langage assembleur pour la machine virtuelle Dalvik, utilisé par Android.

Au travers de Jadx, il est possible d’accéder au code Smali de notre fonction isRooted.

On observe donc, en premier lieu, les instructions invoke-virtual (appel d’une fonction d’une autre classe) et invoke-direct (appel d’une fonction dans la classe actuelle) permettant la détection. Les valeurs de retour booléennes sont alors stockées à l’aide de l’instruction move-result.

Cas client : bypass anti-root sur une application Android

 

Ensuite viennent les vérifications avec if-nez (if not equal to zero) pour les vérifications propres à RootBeer et if-eqz (if equal to zero) pour la fonction définie dans la classe RootDetection. En cas de détection, on assigne la valeur true (0x1) à p1 via l’instruction const/4 (1), sinon, on assigne la valeur false (0x0) à p1 (2). La valeur de p1 est alors retournée par la fonction (3).

Cas client : bypass anti-root sur une application Android

 

Modification

Étant donné qu’il s’agit d’un code reconstruit par Jadx, on ne pourra pas le modifier directement. On va alors s’attaquer au Smali.

L’outil apktool permet la décompilation et la recompilation d’un APK. Ici, on commence par décompiler (`d`) notre APK (`base.apk`), sans décoder les ressources (`-r`), en redirigeant (`-o`) dans le dossier `modified_apk`.

Cas client : bypass anti-root sur une application Android

 

Lorsque l’on accède au dossier, un sous-ensemble de fichiers et dossiers a été créé.

Cas client : bypass anti-root sur une application Android

Pour gagner du temps et accéder au fichier .smali contenant notre détection, on cherche les termes « Device is rooted or VM ? ». Le résultat nous indique alors que nous devons regarder du côté du fichier RootDetection.smali, aux alentours de la ligne 689.

Cas client : bypass anti-root sur une application Android

En ouvrant ce fichier, et en remontant au-dessus de la ligne 689, on retrouve nos deux instructions const/4 p1,0x0 et const/4 p1,0x1.

Cas client : bypass anti-root sur une application Android

Nous allons modifier la valeur de p1 ‘vraie’ par ‘faux’.

Cas client : bypass anti-root sur une application Android

 

Nous recompilons (b) le contenu du dossier `modified_apk`, toujours sans les ressources (`-r`) pour former notre nouvel APK `root_bypass.apk` dans le dossier `out` (`-o`).

Cas client : bypass anti-root sur une application Android

 

Dès lors, nous devons signer notre APK afin qu’il puisse être installé. Comme vu au départ, nous étions sur un split APK. Il faudra également signer les deux autres fichiers split_config, copiés eux aussi dans le répertoire out.

L’outil Uber APK Signer permet de resigner l’ensemble (`–allowResign`) des APKs du répertoire `out` (`–apk`). L’ensemble étant envoyé dans le répertoire `signed` (`–out`).

Cas client : bypass anti-root sur une application Android

 

Vérification

Notre nouvelle version est prête pour installation sur notre Android. On utilise ADB pour installer nos APK (`install-multiple`).

Cas client : bypass anti-root sur une application Android

On relance Pidcat pour consulter les journaux de l’application, qu’on lance sur le terminal. On observe que RootBeer détecte toujours un téléphone rooté (‘PRESENT!!!’), ce qui est légitime étant donné que l’on n’a pas modifié chaque valeur de retour pour chaque fonction. En revanche, on constate que la valeur de retour de la fonction isRooted est bien définie à false.

Cas client : bypass anti-root sur une application Android

 

Un tour du côté de l’application nous permet de valider que le contournement est bien en place et que l’on peut désormais commencer à tester l’application.

Cas client : bypass anti-root sur une application Android

 

Bypass dynamique : Frida

L’outil

Frida est une bibliothèque d’instrumentation dynamique de code. L’instrumentation dynamique d’application consiste en un ensemble de mécanismes permettant de rajouter des fonctionnalités à un programme, sans modifier ses instructions initiales. Assez souvent, cela se traduit par l’injection de code machine dans un processus, permettant de créer des hooks (points d’ancrage) sur des fonctions du programme originel.

Avec ces modifications, il devient possible de modifier le comportement du programme lors de son exécution, sans avoir à modifier le programme initial.

Environnement

Pour pouvoir utiliser Frida, il est nécessaire de déployer un programme serveur sur le terminal.

Ici, nous utilisons Frida en version 16.7.19 (note : il existe des versions 17.x.x mais pas de commentaire sur ça, on reste sur une version stable et qui fonctionne).

On récupère la bonne version frida-server pour notre Android (note : attention à l’architecture). On pousse le programme sur le téléphone (`adb push`), on le rend exécutable et on le lance.

Cas client : bypass anti-root sur une application Android

En utilisant la commande frida-ps -Uai, on peut lister les applications (`-a`) installées (`-i`) sur le terminal connecté en USB (`-U`).

Cas client : bypass anti-root sur une application Android

Hooking

Comme identifié lors de l’analyse de l’APK avec Jadx, la fonction isRooted de la classe RootDetection est responsable de la détection.

Nous allons créer un script hooking.js qui contient, dans un premier temps, les instructions permettant de s’attacher à la classe com.sysdream.app.utils.RootDetection (1), réimplémenter la fonction isRooted (2), afficher la valeur de retour (3) et la renvoyer sans modification (4).

Cas client : bypass anti-root sur une application Android

On utilise Frida pour lancer l’application (`-f`) sur le terminal via USB (`-U`) en chargeant notre fichier hooking.js (`-l`). On observe alors les différentes sorties console.

Cas client : bypass anti-root sur une application Android

 

Ces résultats sont confirmés par l’observation des journaux de l’application.

Cas client : bypass anti-root sur une application Android

 

Maintenant que l’on parvient à s’attacher à la fonction souhaitée, il faut modifier la valeur de retour pour qu’elle soit toujours vraie. Rien de plus simple, on reprend notre script et au lieu de retourner la valeur actuelle, on retourne false.

Cas client : bypass anti-root sur une application Android

Côté application, plus de message de détection, on arrive sur la page de connexion.

Cas client : bypass anti-root sur une application Android

Lorsque l’on regarde les journaux de l’application, ces derniers affichent toujours une détection root.

Cas client : bypass anti-root sur une application Android

 

Ce comportement est normal étant donné que nous avons modifié la valeur de retour de la fonction. Cette étape arrive à la fin de la fonction, juste après la journalisation, qui indique l’état réel du terminal.

Cas client : bypass anti-root sur une application Android

 

Pour supprimer ces informations dans les journaux, il est possible de remplacer function(context) par function() et supprimer les deux lignes récupérant la valeur actuelle de retour de isRooted.

Conclusion

Les techniques employées dans cet article sont connues et sont adaptables en fonction du contexte des applications auditées. Bien que ces détections doivent être mises en place, il faut garder à l’esprit qu’elles ne participent qu’à ralentir un attaquant et ne protégeront pas à 100% de la rétro-ingénierie et pourront être contournées par un attaquant.

Comme pour un réseau interne, cette démarche doit s’inscrire dans un principe de défense en profondeur de la résilience d’une application et être adoptée avec d’autres mécanismes, dont :

Chez SysDream, la résilience n’est qu’une partie des points de contrôle adoptés dans notre méthodologie de tests d’intrusion d’applications mobile (Android et iOS). Ces dernières doivent être vérifiées dans leur globalité en prenant en compte le contexte métier des applications. Notre expertise dans le domaine nous permet également de transmettre ce savoir-faire dans notre formation dédiée à la sécurité des applications mobiles.

 

 

 

 

 


Contactez-nous