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

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).
One-liner pour redémarrer adb en mode root, s’y connecter, uploader frida-server, donner les permissions d’exécution et le lancer 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 server vs. Gadget (root vs. no-root)

Deux façons courantes d’instrumenter les apps Android avec Frida :

  • Frida server (rooted devices): Pousser et exécuter un daemon natif qui vous permet de vous attacher à n’importe quel processus.
  • Frida Gadget (no root): Embarquer Frida comme bibliothèque partagée dans l’APK et la charger automatiquement dans le processus cible.

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)

  1. Décompressez l’APK, ajoutez le gadget .so et la config :
  • Placez libfrida-gadget.so dans lib/<abi>/ (par 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" }
}
  1. Référencer/charger le gadget afin qu’il soit initialisé tôt :
  • Le plus simple : Ajoutez un petit stub Java appelant System.loadLibrary(“frida-gadget”) dans Application.onCreate(), ou utilisez le chargement natif des librairies déjà présentes.
  1. Repaqueter et signer l’APK, puis l’installer :
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
  1. 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 ; gardez les noms/paths discrets et chargez tard/conditionnellement si nécessaire.
  • Sur les apps durcies, privilégiez les tests sur appareil rooted avec server + late attach, ou combinez avec Magisk/Zygisk hiding.

JDWP-based Frida injection without 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 Java breakpoint. Pas de root et pas de repackage de l’APK.

  • 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 with resetprop, 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) ou attach (break at Activity.onStart). Utilisez -b pour définir une méthode Java spécifique, -g pour sélectionner la version/chemin de Gadget, -p pour choisir le port JDWP.
  • Mode écoute : forward Gadget (par défaut 127.0.0.1:27042) si nécessaire : adb forward tcp:27042 tcp:27042; puis frida-ps -H 127.0.0.1:27042.
  • Ceci exploite le débogage JDWP. Le risque est de livrer des builds débogables ou d’exposer JDWP.

Agent autonome + intégration de Gadget (Frida 17+; automatisé avec Objection)

Frida 17 a supprimé les bridges Java/ObjC intégrés de GumJS. Si votre agent hooks Java, vous devez inclure le Java bridge dans votre bundle.

  1. 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

Hook Java minimal (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 embedding :

npm run build    # produces _agent.js via frida-compile

Test USB rapide (optionnel) :

frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
  1. Configurez Gadget pour charger automatiquement votre script Objection’s patcher attend une Gadget config ; lorsque vous utilisez script mode, spécifiez le chemin sur le disque à l’intérieur du APK lib dir :
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
  1. 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 (niveau élevé) :

  • Détecte l’ABI de l’appareil (par ex., arm64-v8a) et récupère le Gadget correspondant
  • Ajoute éventuellement android.permission.INTERNET si nécessaire
  • Injecte un initialiseur de classe statique appelant System.loadLibrary(“frida-gadget”) dans l’activité de lancement
  • Place les fichiers suivants sous lib/<abi>/ :
  • libfrida-gadget.so
  • libfrida-gadget.config.so (config sérialisée)
  • libfrida-gadget.script.so (votre _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
  1. 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é exécutable contient un <clinit> statique qui appelle System.loadLibrary(“frida-gadget”)
  1. Split APKs
  • Patcher l’APK de base (celui qui déclare l’activité MAIN/LAUNCHER)
  • Signer à nouveau 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 align/sign

Tutoriels

Tutoriel 1

De: 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

De: https://11x256.github.io/Frida-hooking-android-part-2/ (Parties 2, 3 et 4)
APKs et code source: https://github.com/11x256/frida-android-examples

Suivez le lien pour le lire.

Tutoriel 3

De: 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 de scripts Frida 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() {
send("sg.vantagepoint.a.c.a()Z   Root check 1 HIT!  su.exists()")
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() & .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 des fonctions avec paramètres et récupération de la valeur

Hooking d’une fonction de déchiffrement. Afficher l’entrée, appeler la fonction originale pour déchiffrer l’entrée et enfin afficher les données en clair :

Hooking d'une fonction de déchiffrement (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 des fonctions et les appeler avec notre entrée

Hook une fonction qui reçoit une chaîne et l'appeler avec une autre chaîne (d'après [ici](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

Références

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