Explorer les fonctions natives avec Frida sur Android – partie 1
Tout d’abord, nous devons comprendre si l’application utilise réellement des fonctions natives, nous devons donc localiser ces bibliothèques natives. Une bibliothèque native est un fichier .so, où «so» signifie Shared Object, qui est essentiellement un fichier C compilé. Sur Android, nous pouvons avoir deux types de bibliothèque native: système (par exemple libc.so) et application personnalisée (par exemple myApp.so).
Quelques exemples sont présentés ci-dessous. Où se trouvent les bibliothèques sur l’appareil Android (/ system / lib64); ou des bibliothèques personnalisées pour les applications sociales Spotify et Facebook Messenger dans leurs répertoires d’applications respectifs (/ data / app / package_name / lib / arm64).
Une fois les bibliothèques natives identifiées utilisées, l’étape suivante consiste à inspecter le code de la classe Java pour comprendre où et quand ces bibliothèques natives sont réellement chargées par l’application. Cette tâche peut être effectuée en recherchant la méthode Java: System.loadLibrary ().
Une fois que nous connaissons et comprenons le flux de travail des bibliothèques natives en cours de chargement, nous devons identifier les fonctions C réelles implémentées dans ces bibliothèques natives. Ceux-ci sont invoqués directement dans l’application et constituent le lien entre le C et Java. Ce lien est défini par la JNI (Java Native Interface), qui nécessite que ces fonctions soient déclarées dans un fichier de classe Java en utilisant le mot clé « originaire de», Puis enveloppé dans une méthode Java normale. Par conséquent, pour identifier toutes les fonctions de l’application, nous pouvons utiliser une expression de recherche dans notre dossier d’application décompilé:
egrep -r « (privé | public) natif statique » *
Prenons maintenant un exemple simple pour mieux comprendre comment fonctionne JNI. Dans notre scénario, nous avons une application hypothétique nommée « ma banque« , Avec le nom du package co.uk.mybank, où nous avons une fonction native que nous souhaitons invoquer dans une classe Java. Cette fonction est implémentée dans un fichier C nommé «verifyCertJNI.c»Qui est utilisé pour l’épinglage du certificat SSL; à l’intérieur se trouve une classe Java nommée « SSLpinning»Qui vérifie si un certificat a été vérifié et renvoie vrai ou faux.
Nous pouvons observer la structure qu’une fonction doit suivre qui est requise par le JNI. La déclaration du nom de la fonction doit commencer par «Java_», Suivi du nom du package, puis du fichier de classe Java réel.
Notez que JNIEXPORT et JNICALL sont des mots clés appropriés de JNI, il est donc nécessaire d’inclure le fichier d’en-tête jni.h, ainsi que la conversion de type de C en Java: jboolean, jstring et jobject.
De plus, gardez à l’esprit qu’il peut y avoir d’autres fonctions C / C ++ en cours d’utilisation lors de l’exécution de l’application mais non directement invoquées par l’application utilisant Java, ces fonctions n’ont donc pas besoin de suivre la structure JNI ou déclarées comme «Java_».
Jusqu’à présent, nous avons adopté une approche plus statique pour identifier les bibliothèques natives et la façon dont elles sont chargées. L’utilisation de Frida nous permettra d’approfondir pour examiner ces fonctions de plus près.