Tutoriel Frida
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Installation
Installer frida tools :
pip install frida-tools
pip install frida
Téléchargez et installez sur l’appareil Android le frida server (Download the latest release).
Commande en une ligne pour redémarrer adb en mode root, se connecter à l’appareil, téléverser frida-server, donner les permissions d’exécution et l’exécuter en arrière-plan:
adb root; adb connect localhost:6000; sleep 1; adb push frida-server /data/local/tmp/; adb shell "chmod 755 /data/local/tmp/frida-server"; adb shell "/data/local/tmp/frida-server &"
Vérifiez si cela fonctionne :
frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
frida-ui (contrôleur Frida basé sur le navigateur)
frida-ui fournit une interface web sur http://127.0.0.1:8000 pour lister devices/apps et attacher ou spawn des targets avec des scripts (pas besoin de CLI).
- Installer (pin
fridato the device server version):
uv tool install frida-ui --with frida==16.7.19
# pipx install frida-ui
# pip install frida-ui
- Exécuter :
frida-ui
frida-ui --host 127.0.0.1 --port 8000 --reload
- Fonctionnalités : découvre les appareils USB/locaux, ajoute des serveurs distants (
192.168.1.x:27042), et supporte Attach, Spawn, et Spawn & Run (pour hooker avant la logique précoceonCreate()). - Scripting : éditeur, glisser-déposer de fichiers
.js, importer CodeShare, télécharger des scripts et les logs de session. - Remote servers :
./frida-server -l 0.0.0.0:27042 -Dl’expose sur le réseau afin que frida-ui puisse se connecter sans ADB.
Frida server vs. Gadget (root vs. no-root)
Two common ways to instrument Android apps with Frida:
- Frida server (rooted devices): Push and run a native daemon that lets you
Attachto any process. - Frida Gadget (no root): Bundle Frida as a shared library inside the APK and auto-load it within the target process.
Frida server (rooted)
# Download the matching frida-server binary for your device's arch
# https://github.com/frida/frida/releases
adb root
adb push frida-server-<ver>-android-<arch> /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server & # run at boot via init/magisk if desired
# From host, list processes and attach
frida-ps -Uai
frida -U -n com.example.app
Frida Gadget (no-root)
- Décompressez l’APK, ajoutez le gadget .so et le fichier de config :
- Placez libfrida-gadget.so dans
lib/<abi>/(p.ex., lib/arm64-v8a/) - Créez assets/frida-gadget.config avec vos paramètres de chargement des scripts
Exemple frida-gadget.config
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
- Référencez/chargez le gadget pour qu’il soit initialisé tôt :
- Le plus simple : Ajoutez un petit stub Java contenant System.loadLibrary(“frida-gadget”) dans Application.onCreate(), ou utilisez le chargement natif de bibliothèques déjà présent.
- Repackez et signez l’APK, puis installez :
apktool d app.apk -o app_m
# ... add gadget .so and config ...
apktool b app_m -o app_gadget.apk
uber-apk-signer -a app_gadget.apk -o out_signed
adb install -r out_signed/app_gadget-aligned-debugSigned.apk
- Attacher depuis l’hôte au processus gadget :
frida-ps -Uai
frida -U -n com.example.app
Remarques
- Gadget est détecté par certaines protections ; maintenez les noms/chemins furtifs et chargez tardivement/conditionnellement si nécessaire.
- Sur les applications durcies, privilégiez les tests rooted avec server + late attach, ou combinez avec le masquage Magisk/Zygisk.
Injection Frida basée sur JDWP sans root/repackaging (frida-jdwp-loader)
Si l’APK est debuggable (android:debuggable=“true”), vous pouvez vous attacher via JDWP et injecter une bibliothèque native à un breakpoint Java. Pas de root et pas de APK repackaging.
- Repo: https://github.com/frankheat/frida-jdwp-loader
- Prérequis: ADB, Python 3, USB/Wireless debugging. L’app doit être debuggable (emulator with
ro.debuggable=1, rooted device withresetprop, or rebuild manifest).
Démarrage rapide:
git clone https://github.com/frankheat/frida-jdwp-loader.git
cd frida-jdwp-loader
# Inject frida-gadget.so into a debuggable target
python frida-jdwp-loader.py frida -n com.example.myapplication
# Keep the breakpoint thread suspended for early hooks
python frida-jdwp-loader.py frida -n com.example.myapplication -s
# Networkless: run a local agent script via Gadget "script" mode
python frida-jdwp-loader.py frida -n com.example.myapplication -i script -l script.js
Remarques
- Modes : spawn (break at Application.onCreate) or attach (break at Activity.onStart). Utilisez
-bpour définir une méthode Java spécifique,-gpour sélectionner Gadget version/chemin,-ppour choisir le port JDWP. - Mode écoute : redirigez Gadget (par défaut 127.0.0.1:27042) si nécessaire :
adb forward tcp:27042 tcp:27042; puisfrida-ps -H 127.0.0.1:27042. - Cela exploite le débogage JDWP. Risque : livrer des versions débogables ou exposer JDWP.
Self-contained agent + Gadget embedding (Frida 17+; automated with Objection)
Frida 17 a retiré les Java/ObjC bridges intégrés de GumJS. Si votre agent hooks Java, vous devez inclure le Java bridge dans votre bundle.
- Créez un agent Frida (TypeScript) et incluez le Java bridge
# Scaffolding
frida-create -t agent -o mod
cd mod && npm install
# Install the Java bridge for Frida 17+
npm install frida-java-bridge
# Dev loop (optional live-reload via REPL)
npm run watch
Minimal Java hook (force les lancers de dés à 1):
import Java from "frida-java-bridge";
Java.perform(function () {
var dicer = Java.use("org.secuso.privacyfriendlydicer.dicer.Dicer");
dicer.rollDice.implementation = function (numDice: number, numFaces: number) {
return Array(numDice).fill(1);
};
});
Générer un seul bundle pour l’intégration :
npm run build # produces _agent.js via frida-compile
Test USB rapide (optionnel) :
frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
- Configurer Gadget pour charger automatiquement votre script Le patcher d’Objection attend une Gadget config ; lorsque vous utilisez le script mode, spécifiez le chemin sur le disque à l’intérieur du APK lib dir :
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
- Automatiser APK patching avec Objection
# Embed Gadget, config, and your compiled agent into the APK; rebuild and sign
objection patchapk -s org.secuso.privacyfriendlydicer.apk \
-c gadget-config.json \
-l mod/_agent.js \
--use-aapt2
Ce que fait patchapk (haut niveau) :
- Détecte l’ABI de l’appareil (ex. arm64-v8a) et récupère le Gadget correspondant
- Ajoute éventuellement android.permission.INTERNET si nécessaire
- Injecte un initialiseur statique de classe appelant System.loadLibrary(“frida-gadget”) dans l’activité de lancement
- Place les éléments suivants sous
lib/<abi>/: - libfrida-gadget.so
- libfrida-gadget.config.so (serialized config)
- libfrida-gadget.script.so (your _agent.js)
Exemple de smali injecté (initialiseur statique) :
.method static constructor <clinit>()V
.locals 1
const-string v0, "frida-gadget"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
- Vérifier le repack
apktool d org.secuso.privacyfriendlydicer.apk
apktool d org.secuso.privacyfriendlydicer.objection.apk
# Inspect differences
diff -r org.secuso.privacyfriendlydicer org.secuso.privacyfriendlydicer.objection
Modifications attendues :
- AndroidManifest.xml peut inclure
<uses-permission android:name="android.permission.INTERNET"/> - Nouvelles bibliothèques natives sous
lib/<abi>/comme ci‑dessus - Le smali de l’activité lançable contient un
<clinit>static qui appelle System.loadLibrary(“frida-gadget”)
- Split APKs
- Patchez l’APK de base (celui qui déclare l’activité MAIN/LAUNCHER)
- Re-signez les splits restants avec la même clé:
objection signapk split1.apk split2.apk ...
- Installer les splits ensemble:
adb install-multiple split1.apk split2.apk ...
- Pour la distribution, vous pouvez fusionner les splits en un seul APK avec APKEditor, puis aligner/signer
Suppression de FLAG_SECURE pendant l’analyse dynamique
Les apps qui appellent getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE) empêchent les screenshots, les affichages à distance et même les snapshots des tâches récentes d’Android. Lorsque Freedom Chat appliquait ce flag, la seule façon de documenter les leaks était de modifier la fenêtre à l’exécution. Un procédé fiable est :
- Hook chaque surcharge de
Windowqui peut ré-appliquer le flag (setFlags,addFlags,setAttributes) et mask out le bit0x00002000(WindowManager.LayoutParams.FLAG_SECURE). - Après la reprise de chaque activity, planifiez un appel sur le thread UI vers
clearFlags(FLAG_SECURE)afin que les Dialogs/Fragments créés ensuite héritent de l’état déverrouillé. - Les apps construites avec React Native / Flutter créent souvent des fenêtres imbriquées ; hook
android.app.Dialog/android.view.Viewhelpers ou parcourezgetWindow().peekDecorView()si vous voyez encore des frames noires.
Frida hook clearing Window.FLAG_SECURE
```javascript Java.perform(function () { var LayoutParams = Java.use("android.view.WindowManager$LayoutParams"); var FLAG_SECURE = LayoutParams.FLAG_SECURE.value; var Window = Java.use("android.view.Window"); var Activity = Java.use("android.app.Activity");function strip(value) { var masked = value & (~FLAG_SECURE); if (masked !== value) { console.log(“[-] Stripped FLAG_SECURE from 0x” + value.toString(16)); } return masked; }
Window.setFlags.overload(‘int’, ‘int’).implementation = function (flags, mask) { return this.setFlags.call(this, strip(flags), strip(mask)); };
Window.addFlags.implementation = function (flags) { return this.addFlags.call(this, strip(flags)); };
Window.setAttributes.implementation = function (attrs) { attrs.flags.value = strip(attrs.flags.value); return this.setAttributes.call(this, attrs); };
Activity.onResume.implementation = function () { this.onResume(); var self = this; Java.scheduleOnMainThread(function () { try { self.getWindow().clearFlags(FLAG_SECURE); console.log(“[+] Cleared FLAG_SECURE on “ + self.getClass().getName()); } catch (err) { console.log(”[!] clearFlags failed: “ + err); } }); }; });
</details>
Exécutez le script avec `frida -U -f <package> -l disable-flag-secure.js --no-pause`, interagissez avec l'UI, et les captures d'écran/enregistrements fonctionneront à nouveau. Comme tout se passe sur le UI thread il n'y a pas de clignotement, et vous pouvez toujours combiner le hook avec HTTP Toolkit/Burp pour capturer le trafic qui a révélé le leak du PIN `/channel`.
## Dynamic DEX dumping / unpacking avec clsdumper (Frida)
`clsdumper` est un Frida-based dynamic **DEX/class dumper** qui survit aux apps renforcées en combinant une pré-étape anti-Frida avec des stratégies de découverte native et Java (fonctionne même si `Java.perform()` plante). Requirements: Python 3.10+, appareil rooté avec `frida-server` en cours d'exécution, connexion USB ou TCP `--host`.
**Installation & utilisation rapide**
```bash
pip install clsdumper
# Attach to a running app
clsdumper com.example.app
# Spawn first (hooks before early loaders)
clsdumper com.example.app --spawn
# Select strategies
clsdumper com.example.app --strategies fart_dump,oat_extract
Options CLI (les plus utiles)
target: nom du package ou PID.--spawn: lancer au lieu d’attacher.--host <ip>: se connecter au frida-server distant.--strategies <comma>: limiter/choisir les extracteurs ; par défaut tous saufmmap_hook(coûteux).--no-scan/--deep-scan: désactiver ou ralentir l’analyse mémoire approfondie (ajoute CDEX scanning).--extract-classes: post-traiter les dumps en.smalivia androguard.--no-anti-frida: ignorer l’étape de bypass pré-hook.--list/--list-apps: énumérer les processus en cours ou les packages installés.
Bypass anti-instrumentation (phase 0)
- Installe des hooks sur
sigaction/signalpour bloquer l’enregistrement des gestionnaires de crash/anti-debug. - Fournit un
/proc/self/mapsfiltré viamemfd_createpour cacher les régions Frida. - Surveille
pthread_createpour attraper/neutraliser les threads de surveillance qui chassent Frida.
Découverte DEX (phases 1–2) — plusieurs stratégies complémentaires avec métadonnées par détection + déduplication (agent-side djb2, host-side SHA-256):
- Natif (aucun bridge Java requis) :
art_walk(parcours ART Runtime→ClassLinker→DexFile),open_common_hook(hookDexFile::OpenCommon),memory_scan(séquence magique DEX dans les maps lisibles),oat_extract(analyser les .vdex/.oat mappés),fart_dump(hookDefineClass+ parcourirclass_table_),dexfile_constructor(hook des constructeursOatDexFile),mmap_hook(surveillemmap/mmap64, désactivé par défaut pour les performances). - Java (lorsque disponible) :
cookie(liremCookiedepuis les ClassLoaders),classloader_hook(surveillerloadClass,DexClassLoader,InMemoryDexClassLoader).
Structure de sortie
dump_<target>/
dex/classes_001.dex ...
classes/ # only when --extract-classes
metadata.json # strategy per hit + hashes
Astuce : les applications protégées chargent souvent du code depuis plusieurs sources (in-memory payload, vdex/oat, custom loaders). Exécuter avec l’ensemble multi-strategy par défaut plus --spawn maximise la couverture ; activez --deep-scan uniquement lorsque nécessaire pour éviter des impacts sur les performances.
Tutoriels
Tutoriel 1
Source: https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1
APK: https://github.com/t0thkr1s/frida-demo/releases
Code source: https://github.com/t0thkr1s/frida-demo
Suivez le lien pour le lire.
Tutoriel 2
Source: https://11x256.github.io/Frida-hooking-android-part-2/ (Parts 2, 3 & 4)
APKs et code source: https://github.com/11x256/frida-android-examples
Suivez le lien pour le lire.
Tutoriel 3
Source: https://joshspicer.com/android-frida-1
APK: https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk
Suivez le lien pour le lire.
Vous pouvez trouver plus d’Awesome Frida scripts ici: https://codeshare.frida.re/
Exemples rapides
Appeler Frida depuis la ligne de commande
frida-ps -U
#Basic frida hooking
frida -l disableRoot.js -f owasp.mstg.uncrackable1
#Hooking before starting the app
frida -U --no-pause -l disableRoot.js -f owasp.mstg.uncrackable1
#The --no-pause and -f options allow the app to be spawned automatically,
#frozen so that the instrumentation can occur, and the automatically
#continue execution with our modified code.
Script Python de base
import frida, sys
jscode = open(sys.argv[0]).read()
process = frida.get_usb_device().attach('infosecadventures.fridademo')
script = process.create_script(jscode)
print('[ * ] Running Frida Demo application')
script.load()
sys.stdin.read()
Hooking des fonctions sans paramètres
Hook la fonction a() de la classe sg.vantagepoint.a.c
Java.perform(function () {
rootcheck1.a.overload().implementation = function () {
return false;
};
});
Hook java exit()
var sysexit = Java.use("java.lang.System")
sysexit.exit.overload("int").implementation = function (var_0) {
send("java.lang.System.exit(I)V // We avoid exiting the application :)")
}
Hook MainActivity .onStart() et .onCreate()
var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity")
mainactivity.onStart.overload().implementation = function () {
send("MainActivity.onStart() HIT!!!")
var ret = this.onStart.overload().call(this)
}
mainactivity.onCreate.overload("android.os.Bundle").implementation = function (
var_0
) {
send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
Hook android .onCreate()
var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function (
var_0
) {
send("Activity HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
Hooking de fonctions avec paramètres et récupération de la valeur
Hooking d’une decryption function. Affichez l’input, appelez la fonction originale pour decrypt l’input et enfin affichez les données en clair :
Hooking d'une decryption function (Java) — afficher les entrées/sorties
```javascript function getString(data) { var ret = "" for (var i = 0; i < data.length; i++) { ret += data[i].toString() } return ret } var aes_decrypt = Java.use("sg.vantagepoint.a.a") aes_decrypt.a.overload("[B", "[B").implementation = function (var_0, var_1) { send("sg.vantagepoint.a.a.a([B[B)[B doFinal(enc) // AES/ECB/PKCS7Padding") send("Key : " + getString(var_0)) send("Encrypted : " + getString(var_1)) var ret = this.a.overload("[B", "[B").call(this, var_0, var_1) send("Decrypted : " + ret)var flag = “” for (var i = 0; i < ret.length; i++) { flag += String.fromCharCode(ret[i]) } send(“Decrypted flag: “ + flag) return ret //[B }
</details>
### Hooking de fonctions et les appeler avec notre input
Hook une fonction qui reçoit une string et l'appeler avec une autre string (depuis [here](https://11x256.github.io/Frida-hooking-android-part-2/))
```javascript
var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class
my_class.fun.overload("java.lang.String").implementation = function (x) {
//hooking the new function
var my_string = string_class.$new("My TeSt String#####") //creating a new String by using `new` operator
console.log("Original arg: " + x)
var ret = this.fun(my_string) // calling the original function with the new String, and putting its return value in ret variable
console.log("Return value: " + ret)
return ret
}
Récupérer un objet déjà créé d’une classe
Si vous voulez extraire un attribut d’un objet déjà créé, vous pouvez utiliser ceci.
Dans cet exemple, vous allez voir comment obtenir l’objet de la classe my_activity et comment appeler la fonction .secret() qui affichera un attribut privé de l’objet :
Java.choose("com.example.a11x256.frida_test.my_activity", {
onMatch: function (instance) {
//This function will be called for every instance found by frida
console.log("Found instance: " + instance)
console.log("Result of secret func: " + instance.secret())
},
onComplete: function () {},
})
Autres tutoriels Frida
- https://github.com/DERE-ad2001/Frida-Labs
- Partie 1 de la série de blogs “Advanced Frida Usage” : Bibliothèques de chiffrement IOS
Références
- Créer un laboratoire Android Bug Bounty reproductible : émulateur vs Magisk, Burp, Frida et Medusa
- Documentation Frida Gadget
- Frida releases (binaires serveur)
- Objection (SensePost)
- Modder et distribuer des applications mobiles avec Frida
- frida-jdwp-loader
- Injection de bibliothèques pour applications Android débogables (blog)
- jdwp-lib-injector (idée/outil original)
- jdwp-shellifier
- “Super secure” MAGA-themed messaging app leaks le numéro de téléphone de tout le monde
- Android Frida Hooking : Désactivation de FLAG_SECURE
- frida-ui
- clsdumper — Dump dynamique de classes Android
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


