Contournement de l’Anti-Instrumentation Android et du SSL Pinning (Frida/Objection)

Tip

Apprenez et pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).

Support HackTricks

Cette page propose un workflow pratique pour reprendre l’analyse dynamique d’apps Android qui détectent/bloquent l’instrumentation sur appareils rootés ou qui appliquent le TLS pinning. Elle se concentre sur le triage rapide, les détections courantes, et des hooks/tactiques prêts à copier‑coller pour les contourner sans repackager quand c’est possible.

Surface de détection (ce que les apps vérifient)

  • Root checks : binaire su, chemins Magisk, valeurs getprop, paquets root courants
  • Frida/debugger checks (Java) : Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), balayage de /proc, classpath, libs chargées
  • Anti‑debug natif : ptrace(), appels système, anti‑attach, breakpoints, hooks inline
  • Vérifications d’init précoce : Application.onCreate() ou hooks de démarrage de processus qui plantent si l’instrumentation est présente
  • TLS pinning : TrustManager/HostnameVerifier personnalisés, OkHttp CertificatePinner, Conscrypt pinning, pins natifs

Contourner la détection Anti‑Frida / Stealth Frida Servers

phantom-frida reconstruit Frida depuis les sources et applique ~90 patches pour faire disparaître les empreintes Frida courantes tout en conservant la compatibilité du protocole Frida stock (frida-tools peut toujours se connecter). Cible : apps qui grepent /proc (cmdline, maps, task comm, fd readlink), noms de services D-Bus, ports par défaut, ou symboles exportés.

Phases:

  • Source patches : renommage global des identifiants frida (server/agent/helper) et reconstruction du helper DEX avec un package Java renommé.
  • Targeted build/runtime patches : ajustements meson, label memfd changé en jit-cache, labels SELinux (p.ex. frida_file) renommés, hooks libc sur exit/signal désactivés pour éviter les hook-detectors.
  • Post-build rename : le symbole exporté frida_agent_main est renommé après la première compilation (Vala l’émet), nécessitant une seconde compilation incrémentale.
  • Binary hex patches : noms de threads (gmain, gdbus, pool-spawner) remplacés ; un sweep optionnel supprime les chaînes résiduelles frida/Frida.

Vecteurs de détection couverts:

  • Base (1–8) : le nom de processus frida-server, la bibliothèque mappée libfrida-agent.so, les noms de threads, le label memfd, le symbole exporté frida_agent_main, les labels SELinux, les effets secondaires des hooks libc, et le service D-Bus re.frida.server sont renommés/neutralisés.
  • Extended (9–16) : changement du port d’écoute (--port), renommage des interfaces D-Bus/symboles C internes/noms GType, chemins temporaires comme .frida/frida-, sweep des chaînes binaires, renommage des defines au moment de la build et des chemins d’assets (libdir/frida). Les noms d’interface D-Bus qui font partie du protocole wire restent inchangés en mode base pour éviter de casser les clients stock.

Build/usage (exemple Android arm64) :

python3 build.py --version 17.7.2 --name myserver --port 27142 --extended --verify
adb push output/myserver-server-17.7.2-android-arm64 /data/local/tmp/myserver-server
adb shell chmod 755 /data/local/tmp/myserver-server
adb shell /data/local/tmp/myserver-server -D &
adb forward tcp:27142 tcp:27142
frida -H 127.0.0.1:27142 -f com.example.app

Options : --skip-build (patch uniquement), --skip-clone, --arch, --ndk-path, --temp-fixes; Assistant WSL : wsl -d Ubuntu bash build-wsl.sh.

Step 1 — Quick win: hide root with Magisk DenyList

  • Activer Zygisk dans Magisk
  • Activer DenyList, ajouter le package cible
  • Redémarrer et retester

De nombreuses applis ne recherchent que des indicateurs évidents (su / chemins Magisk / getprop). DenyList neutralise souvent les vérifications naïves.

Références:

  • Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk

Play Integrity / Zygisk detections (post‑SafetyNet)

Les applications bancaires/d’identité récentes lient les vérifications runtime à Google Play Integrity (remplaçant de SafetyNet) et peuvent aussi planter si Zygisk est présent. Conseils rapides de triage:

  • Désactiver temporairement Zygisk (toggle off + redémarrer) et réessayer ; certaines applis plantent dès que l’injection Zygote se charge.
  • Si l’attestation bloque la connexion, patcher Google Play Services avec PlayIntegrityFix/Fork + TrickyStore ou utiliser ReZygisk/Zygisk‑Next uniquement pour les tests. Garder la cible dans DenyList et éviter les modules LSPosed qui leak props.
  • Pour des exécutions ponctuelles, utiliser KernelSU/APatch (pas d’injection Zygote) pour rester sous les heuristiques Zygisk, puis attacher Frida.

Step 2 — 30‑second Frida Codeshare tests

Tester les scripts drop‑in courants avant d’approfondir:

  • anti-root-bypass.js
  • anti-frida-detection.js
  • hide_frida_gum.js

Exemple:

frida -U -f com.example.app -l anti-frida-detection.js

Elles remplacent généralement les vérifications Java de root/debug, les analyses de processus/services, et le ptrace() natif. Utile sur des applications faiblement protégées ; les cibles durcies peuvent nécessiter des hooks adaptés.

  • Codeshare: https://codeshare.frida.re/

Automatiser avec Medusa (Frida framework)

Medusa propose plus de 90 modules prêts à l’emploi pour SSL unpinning, root/emulator detection bypass, HTTP comms logging, crypto key interception, et plus encore.

git clone https://github.com/Ch0pin/medusa
cd medusa
pip install -r requirements.txt
python medusa.py

# Example interactive workflow
show categories
use http_communications/multiple_unpinner
use root_detection/universal_root_detection_bypass
run com.target.app

Astuce : Medusa est great pour des quick wins avant d’écrire des hooks personnalisés. Vous pouvez aussi cherry-pick des modules et les combiner avec vos propres scripts.

Automatiser avec Auto-Frida (spawn-mode + consolidated hooks)

Auto-Frida est une boîte à outils d’automatisation Frida qui se concentre sur une configuration reproductible ainsi que sur l’auto-détection des protections et la génération consolidée de scripts de bypass. Il est utile lorsque les apps effectuent des vérifications très tôt ou lorsque plusieurs modules de bypass risquent de double-hooker les mêmes APIs.

Principales idées d’automatisation :

  • Spawn-mode analysis pour installer des hooks avant Application.onCreate() afin de détecter très tôt les SSL pinning, root, emulator ou anti-Frida.
  • Protection detection + auto-bypass : les résultats de détection pilotent la génération d’un seul script consolidé qui hooke chaque méthode Java/symbole natif une seule fois, réduisant les plantages dus à des hooks qui se chevauchent.
  • Frida server lifecycle checks : valider l’état du server (process + port 27042 + frida-ps handshake) avant de télécharger/redémarrer pour maintenir la stabilité des runs.

Démarrage rapide :

git clone https://github.com/ommirkute/Auto-Frida.git
cd Auto-Frida
pip install -r requirements.txt
python auto_frida.py

Remarques

  • Auto-Frida peut installer automatiquement frida/frida-tools s’ils sont manquants et prend en charge la sélection multi-appareils.
  • Les scripts générés peuvent être exécutés immédiatement ou fusionnés avec vos hooks personnalisés après analyse.

Étape 3 — Contourner les détecteurs d’initialisation en s’attachant tardivement

De nombreuses détections ne s’exécutent que lors du process spawn/onCreate(). Les Spawn‑time injection (-f) ou les gadgets se font repérer ; s’attacher après le chargement de l’UI peut les contourner.

# Launch the app normally (launcher/adb), wait for UI, then attach
frida -U -n com.example.app
# Or with Objection to attach to running process
aobjection --gadget com.example.app explore  # if using gadget

Si cela fonctionne, gardez la session stable et procédez à la cartographie et aux vérifications des stubs.

Étape 4 — Cartographier la logique de détection via Jadx et recherche de chaînes

Mots-clés de triage statique dans Jadx :

  • “frida”, “gum”, “root”, “magisk”, “ptrace”, “su”, “getprop”, “debugger”

Modèles Java typiques :

public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}

API courantes à examiner/hook:

  • android.os.Debug.isDebuggerConnected
  • android.app.ActivityManager.getRunningAppProcesses / getRunningServices
  • java.lang.System.loadLibrary / System.load (native bridge)
  • java.lang.Runtime.exec / ProcessBuilder (probing commands)
  • android.os.SystemProperties.get (root/emulator heuristics)

Étape 5 — Stubbing à l’exécution avec Frida (Java)

Surcharger les vérifications personnalisées pour renvoyer des valeurs sûres sans repacking:

Java.perform(() => {
const Checks = Java.use('com.example.security.Checks');
Checks.isFridaDetected.implementation = function () { return false; };

// Neutralize debugger checks
const Debug = Java.use('android.os.Debug');
Debug.isDebuggerConnected.implementation = function () { return false; };

// Example: kill ActivityManager scans
const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
});

Triage des plantages précoces ? Dumper les classes juste avant qu’il ne plante pour repérer les espaces de noms de détection probables :

Java.perform(() => {
Java.enumerateLoadedClasses({
onMatch: n => console.log(n),
onComplete: () => console.log('Done')
});
});

Exemple rapide de stub de détection de root (adapter aux noms de package/classe cibles) :

Java.perform(() => {
try {
const RootChecker = Java.use('com.target.security.RootCheck');
RootChecker.isDeviceRooted.implementation = function () { return false; };
} catch (e) {}
});

Enregistrer et neutraliser les méthodes suspectes pour confirmer le flux d’exécution :

Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
Det.checkFrida.implementation = function () {
console.log('checkFrida() called');
return false;
};
});

Bypass emulator/VM detection (Java stubs)

Heuristiques courantes : Build.FINGERPRINT/MODEL/MANUFACTURER/HARDWARE contenant generic/goldfish/ranchu/sdk ; artefacts QEMU comme /dev/qemu_pipe, /dev/socket/qemud ; MAC par défaut 02:00:00:00:00:00 ; NAT 10.0.2.x ; telephony/sensors manquants.

Falsification rapide des champs Build :

Java.perform(function(){
var Build = Java.use('android.os.Build');
Build.MODEL.value = 'Pixel 7 Pro';
Build.MANUFACTURER.value = 'Google';
Build.BRAND.value = 'google';
Build.FINGERPRINT.value = 'google/panther/panther:14/UP1A.231105.003/1234567:user/release-keys';
});

Compléter avec des stubs pour les vérifications d’existence de fichiers et les identifiants (TelephonyManager.getDeviceId/SubscriberId, WifiInfo.getMacAddress, SensorManager.getSensorList) afin de renvoyer des valeurs réalistes.

SSL pinning bypass quick hook (Java)

Neutraliser les TrustManagers personnalisés et forcer des SSL contexts permissifs :

Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');

// No-op validations
X509TrustManager.checkClientTrusted.implementation = function(){ };
X509TrustManager.checkServerTrusted.implementation = function(){ };

// Force permissive TrustManagers
var TrustManagers = [ X509TrustManager.$new() ];
var SSLContextInit = SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;','[Ljavax.net.ssl.TrustManager;','java.security.SecureRandom');
SSLContextInit.implementation = function(km, tm, sr){
return SSLContextInit.call(this, km, TrustManagers, sr);
};
});

Remarques

  • Étendre pour OkHttp : hook okhttp3.CertificatePinner et HostnameVerifier selon les besoins, ou utilisez un script unpinning universel depuis CodeShare.
  • Exemple d’exécution : frida -U -f com.target.app -l ssl-bypass.js --no-pause

OkHttp4 / gRPC / Cronet pinning (2024+)

Les stacks modernes appliquent le pin dans des APIs plus récentes (OkHttp4+, gRPC over Cronet/BoringSSL). Ajoutez ces hooks lorsque le hook SSLContext basique bloque :

Java.perform(() => {
try {
const Pinner = Java.use('okhttp3.CertificatePinner');
Pinner.check.overload('java.lang.String', 'java.util.List').implementation = function(){};
Pinner.check$okhttp.implementation = function(){};
} catch (e) {}

try {
const CronetB = Java.use('org.chromium.net.CronetEngine$Builder');
CronetB.enablePublicKeyPinningBypassForLocalTrustAnchors.overload('boolean').implementation = function(){ return this; };
CronetB.setPublicKeyPins.overload('java.lang.String', 'java.util.Set', 'boolean').implementation = function(){ return this; };
} catch (e) {}
});

Si TLS échoue toujours, passez au natif et appliquez un patch aux points d’entrée de vérification de BoringSSL utilisés par Cronet/gRPC :

const customVerify = Module.findExportByName(null, 'SSL_CTX_set_custom_verify');
if (customVerify) {
Interceptor.attach(customVerify, {
onEnter(args){
// arg0 = SSL_CTX*, arg1 = mode, arg2 = callback
args[1] = ptr(0); // SSL_VERIFY_NONE
args[2] = NULL;  // disable callback
}
});
}

Étape 6 — Suivre la piste JNI/native lorsque les Java hooks échouent

Tracez les points d’entrée JNI pour localiser les native loaders et l’initialisation de détection :

frida-trace -n com.example.app -i "JNI_OnLoad"

Triage natif rapide des fichiers .so inclus :

# List exported symbols & JNI
nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'

Rétro-ingénierie interactive/native:

  • Ghidra: https://ghidra-sre.org/
  • r2frida: https://github.com/nowsecure/r2frida

Exemple : neutraliser ptrace pour contourner un anti‑debug simple dans libc:

const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
Interceptor.replace(ptrace, new NativeCallback(function () {
return -1; // pretend failure
}, 'int', ['int', 'int', 'pointer', 'pointer']));
}

Voir aussi : Reversing Native Libraries

Étape 7 — Objection patching (embed gadget / strip basics)

Si vous préférez le repacking aux runtime hooks, essayez :

objection patchapk --source app.apk

Notes:

  • Nécessite apktool ; assurez-vous d’avoir une version récente depuis le guide officiel pour éviter des problèmes de build : https://apktool.org/docs/install
  • Gadget injection permet l’instrumentation sans root mais peut quand même être détectée par des init‑time checks plus stricts.

Optionnellement, ajoutez des modules LSPosed et Shamiko pour un masquage de root plus robuste dans les environnements Zygisk, et affinez la DenyList pour couvrir les processus enfants.

Pour un workflow complet incluant la configuration en mode script de Gadget et l’intégration de votre Frida 17+ agent dans l’APK, voir:

Frida Tutorial — Self-contained agent + Gadget embedding

Références:

  • Objection: https://github.com/sensepost/objection

Étape 8 — Solution de secours : patcher le TLS pinning pour la visibilité réseau

Si l’instrumentation est bloquée, vous pouvez toujours inspecter le trafic en supprimant le TLS pinning statiquement :

apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
  • Outil: https://github.com/shroudedcode/apk-mitm
  • Pour les astuces CA‑trust de config réseau (et la confiance des CA utilisateur sur Android 7+), voir :

Make APK Accept CA Certificate

Install Burp Certificate

LSPosed/Xposed Hooking Abuse (Téléphonie/SMS)

Sur les appareils rootés, les modules LSPosed/Xposed peuvent hooker les API Java de téléphonie/SMS à l’exécution, laissant l’APK non modifié sur le disque tout en contrôlant entièrement ce que l’application voit. Ceci est couramment abusé pour contourner les flux liés à la SIM qui font confiance aux API de téléphonie locales ou à l’état local du fournisseur SMS.

Primitives clés

  • Supprimer l’envoi des SMS de vérification sortants tout en exfiltrant le token en court‑circuitant SmsManager.sendTextMessage dans beforeHookedMethod.
  • Usurper le MSISDN/numéro de ligne en forçant TelephonyManager.getLine1Number() et SubscriptionInfo.getNumber() à retourner une valeur contrôlée par l’attaquant.
  • Insérer un faux enregistrement “Sent” dans le fournisseur SMS afin que les apps qui vérifient l’historique SMS local voient un envoi réussi même si l’opérateur ne l’a jamais reçu.

Exemple : bloquer l’envoi de SMS et capturer le contenu

XposedHelpers.findAndHookMethod(
"android.telephony.SmsManager",
lpparam.classLoader,
"sendTextMessage",
String.class, String.class, String.class, PendingIntent.class, PendingIntent.class,
new XC_MethodHook() {
protected void beforeHookedMethod(MethodHookParam param) {
String body = (String) param.args[2];
// exfiltrate body to operator channel
param.setResult(null); // suppress real SMS send
}
}
);

Exemple : spoof du numéro de téléphone de l’appareil

XposedHelpers.findAndHookMethod(
"android.telephony.TelephonyManager",
lpparam.classLoader,
"getLine1Number",
new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(spoofedMsisdn);
}
}
);
XposedHelpers.findAndHookMethod(
"android.telephony.SubscriptionInfo",
lpparam.classLoader,
"getNumber",
new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) {
param.setResult(spoofedMsisdn);
}
}
);

Exemple : injecter un faux enregistrement SMS « Sent »

ContentValues v = new ContentValues();
v.put("address", dest);
v.put("body", body);
v.put("type", 2);   // sent
v.put("status", 0); // success
context.getContentResolver().insert(Uri.parse("content://sms/sent"), v);

Aide-mémoire pratique des commandes

# List processes and attach
frida-ps -Uai
frida -U -n com.example.app

# Spawn with a script (may trigger detectors)
frida -U -f com.example.app -l anti-frida-detection.js

# Trace native init
frida-trace -n com.example.app -i "JNI_OnLoad"

# Objection runtime
objection --gadget com.example.app explore

# Static TLS pinning removal
apk-mitm app.apk

Universal proxy forcing + TLS unpinning (HTTP Toolkit Frida hooks)

Les applications modernes ignorent souvent les proxies système et appliquent plusieurs couches de pinning (Java + native), rendant la capture du trafic pénible même avec des CAs utilisateur/système installés. Une approche pratique consiste à combiner universal TLS unpinning avec le forçage du proxy via des hooks Frida prêts à l’emploi, et à rediriger tout le trafic via mitmproxy/Burp.

Workflow

  • Exécutez mitmproxy sur votre hôte (ou Burp). Vérifiez que l’appareil peut atteindre l’IP/port de l’hôte.
  • Chargez les hooks Frida consolidés de HTTP Toolkit pour à la fois unpin TLS et forcer l’utilisation d’un proxy sur les stacks courants (OkHttp/OkHttp3, HttpsURLConnection, Conscrypt, WebView, etc.). Cela contourne les vérifications CertificatePinner/TrustManager et remplace les sélecteurs de proxy, de sorte que le trafic est toujours envoyé via votre proxy même si l’application désactive explicitement les proxies.
  • Démarrez l’application cible avec Frida et le script hook, puis capturez les requêtes dans mitmproxy.

Example

# Device connected via ADB or over network (-U)
# See the repo for the exact script names & options
frida -U -f com.vendor.app \
-l ./android-unpinning-with-proxy.js \
--no-pause

# mitmproxy listening locally
mitmproxy -p 8080

Remarques

  • Combinez avec un proxy système via adb shell settings put global http_proxy <host>:<port> quand c’est possible. Les hooks Frida forceront l’utilisation du proxy même lorsque les apps contournent les paramètres globaux.
  • Cette technique est idéale lorsque vous devez MITM des flux d’onboarding mobile vers IoT, où le pinning et l’évitement du proxy sont courants.
  • Hooks : https://github.com/httptoolkit/frida-interception-and-unpinning

Références

Tip

Apprenez et pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).

Support HackTricks