Résolution du problème de hook Frida sur des fonctions natives ARM dans un émulateur x86

Lors de l'analyse d'applications Android contenant des bibliothèques natives ARM sur des émulateurs x86 (comme LDPlayer ou Nox), Frida échoue souvent à localiser les modules .so ARM, même si l'application fonctionen correctement. Ce comportement est dû à la traduction dynamique d'instructions ARM vers x86 effectuée par ces émulateurs.

Contexte du problème

  • L'émulateur (LDPlayer, Nox, etc.) fonctionne en architecture x86.
  • L'APK cible inclut uniquement une bibliothèque native ARM : libpp.so.
  • L'émulateur utilise un mécanisme de traduction binaire pour exécuter le code ARM.
  • Frida ne détecte pas libpp.so via Process.enumerateModules(), Module.findBaseAddress() ou Module.findExportByName().

Analyse approfondie

En inspectant /proc/<pid>/maps via ADB, on constate que libpp.so est bien chargé en mémoire :

0b544000-0b548000 r--p ... /data/app/.../lib/arm/libpp.so
0b548000-0b549000 r--p ... /data/app/.../lib/arm/libpp.so
0b549000-0b54a000 rw-p ... /data/app/.../lib/arm/libpp.so

Cependant, Frida ne le voit pas car il n’est pas chargé via le chargeur dynamique standard (linker) mais via un mécanisme propriétaire de traduction binaire. Frida s’appuie sur les strcutures internes du chargeur ELF pour énumérer les modules, ce qui échoue ici.

Un script Frida classique comme celui-ci ne retourne rien :

Java.perform(() => {
  Process.enumerateModules({
    onMatch: (mod) => {
      if (mod.name.includes('libpp')) {
        console.log('Trouvé :', mod);
      }
    },
    onComplete: () => {}
  });
});

Solutions envisageables

Option 1 : Utiliser un périphérique physique ARM
La solution officielle recommandée par l’équipe Frida. Simple et fiable, mais nécessite un appareil réel.

Option 2 : Émulateur AVD avec image ARM
L’approche retenue ici consiste à utiliser l’Android Virtual Device Manager (AVD) fourni avec Android Studio :

  1. Ouvrir AVD Manager dans Android Studio.
  2. Télécharger une image système ARM (disponible principalement pour Android 7.0 Nougat).
  3. Créer un nouvel émulateur basé sur cette image.

Avec cet émulateur ARM pur, /proc/<pid>/maps montre :

e9684000-e9688000 r-xp ... /data/app/.../lib/arm/libpp.so
e9688000-e9689000 r--p ... /data/app/.../lib/arm/libpp.so
e9689000-e968a000 rw-p ... /data/app/.../lib/arm/libpp.so

Et Frida parveint désormais à détecter le module :

frida -U -f com.geekerchina.pingpongmachine -l ./NHook.js
...
[send] libpp.so|0xe9684000|24576|/data/app/.../lib/arm/libpp.so
[send] findExportByName ping():0xe9685309
[send] findExportByName pong():0xe9685565

Pourquoi cela fonctionne ?

Dans un émulateur ARM natif (via QEMU dans AVD), le code ARM s’exécute directement sans traduction. Le chargeur ELF standard gère le chargement de libpp.so, ce qui rend le module visible à Frida via les API habituelles.

Conclusion

Pour analyser des bibliothèques natives ARM sur émulateur, privilégiez un AVD avec image ARM plutôt que des émulateurs tiers x86 avec traduction binaire. Cela garantit la compatibilité avec Frida et d’autres outils d’instrumentation dynamique.

Étiquettes: Frida Android reverse-engineering ARM x86

Publié le 7 octobre à 00h59