Frida Anleitung
Tip
Lernen & ĂŒben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & ĂŒben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
UnterstĂŒtzen Sie HackTricks
- ĂberprĂŒfen Sie die AbonnementplĂ€ne!
- Treten Sie der đŹ Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter đŠ @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Installation
Installiere frida tools:
pip install frida-tools
pip install frida
Herunterladen und installieren des frida server auf dem Android-GerÀt (Download the latest release).
Einzeiler, um adb im Root-Modus neu zu starten, sich damit zu verbinden, frida-server hochzuladen, AusfĂŒhrungsrechte zu vergeben und ihn im Hintergrund auszufĂŒhren:
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 &"
ĂberprĂŒfe ob es funktioniert:
frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
frida-ui (browserbasierter Frida-Controller)
frida-ui stellt eine Web-UI unter http://127.0.0.1:8000 bereit, um GerÀte/Apps aufzulisten und Targets mit Skripten anzuhÀngen oder zu starten (kein CLI nötig).
- Installieren (frida an die device-server-Version anpassen):
uv tool install frida-ui --with frida==16.7.19
# pipx install frida-ui
# pip install frida-ui
- AusfĂŒhren:
frida-ui
frida-ui --host 127.0.0.1 --port 8000 --reload
- Funktionen: entdeckt USB-/lokale GerĂ€te, fĂŒgt Remote-Server (
192.168.1.x:27042) hinzu und unterstĂŒtzt Attach, Spawn, und Spawn & Run (um vor der frĂŒhenonCreate()-Logik zu hooken). - Scripting: Editor, Drag & Drop von
.js, CodeShare importieren, Skripte und Session-Logs herunterladen. - Remote servers:
./frida-server -l 0.0.0.0:27042 -Dmacht ihn im Netzwerk erreichbar, sodass frida-ui sich ohne ADB verbinden kann.
Frida server vs. Gadget (root vs. no-root)
Two common ways to instrument Android apps with Frida:
- Frida server (rooted devices): Einen nativen Daemon aufspielen und starten, der das AnhÀngen an jeden Prozess ermöglicht.
- Frida Gadget (no root): Frida als Shared Library in die APK einbinden und automatisch im Zielprozess laden.
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 (kein Root)
- Entpacke die APK, fĂŒge die .so des Gadgets und die Konfiguration hinzu:
- Platziere libfrida-gadget.so in
lib/<abi>/(z. B. lib/arm64-v8a/) - Erstelle assets/frida-gadget.config mit deinen Einstellungen zum Laden von Skripten
Beispiel frida-gadget.config
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
- Referenziere/lade das gadget, damit es frĂŒhzeitig initialisiert wird:
- Am einfachsten: FĂŒge einen kleinen Java-Stub mit System.loadLibrary(âfrida-gadgetâ) in Application.onCreate() hinzu, oder verwende bereits vorhandenes native lib loading.
- Repacke und signiere die APK, dann installiere:
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
- Vom Host an den Gadget-Prozess anhÀngen:
frida-ps -Uai
frida -U -n com.example.app
Hinweise
- Gadget wird von einigen Schutzmechanismen erkannt; halte Namen/Pfade unauffÀllig und lade es bei Bedarf spÀt oder selektiv.
- Bei gehÀrteten Apps: Tests vorzugsweise auf einem gerooteten GerÀt mit Server + spÀtem Attach, oder in Kombination mit Magisk/Zygisk-Hiding.
JDWP-basierte Frida-Injektion ohne Root/Repackaging (frida-jdwp-loader)
Wenn das APK debuggable ist (android:debuggable=âtrueâ), kannst du ĂŒber JDWP anhĂ€ngen und an einem Java-Breakpoint eine native Library injizieren. Kein Root und kein Repackaging des APKs.
- Repo: https://github.com/frankheat/frida-jdwp-loader
- Voraussetzungen: ADB, Python 3, USB/Wireless debugging. Die App muss debuggable sein (emulator mit
ro.debuggable=1, gerootetes GerÀt mitresetprop, oder Manifest neu bauen).
Schnellstart
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
Hinweise
- Modi: spawn (break at Application.onCreate) oder attach (break at Activity.onStart). Verwende
-b, um eine bestimmte Java-Methode festzulegen,-g, um die Gadget-Version/Pfad auszuwÀhlen,-p, um den JDWP-Port zu wÀhlen. - Listen-Modus: Gadget weiterleiten (Standard 127.0.0.1:27042) falls erforderlich:
adb forward tcp:27042 tcp:27042; dannfrida-ps -H 127.0.0.1:27042. - Dies nutzt JDWP-Debugging. Risiko: Ausliefern von debuggable Builds oder Offenlegen von JDWP.
EigenstÀndiger Agent + Gadget-Einbettung (Frida 17+; automatisiert mit Objection)
Frida 17 hat die eingebauten Java/ObjC-Bridges aus GumJS entfernt. Wenn dein Agent Java hookt, musst du die Java-Bridge in dein Bundle einbinden.
- Erstelle einen Frida-Agenten (TypeScript) und binde die Java-Bridge in dein Bundle ein
# 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 (erzwingt WĂŒrfelwĂŒrfe auf 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);
};
});
Ein einzelnes Bundle zum Einbetten erstellen:
npm run build # produces _agent.js via frida-compile
Schneller USB-Test (optional):
frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
- Konfiguriere Gadget, damit es dein script automatisch lĂ€dt Objectionâs patcher erwartet eine Gadget config; wenn du den script mode verwendest, gib den on-disk path innerhalb des APK lib dir an:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
- APK-Patching mit Objection automatisieren
# 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
Was patchapk macht (auf hoher Ebene):
- Erkennt die ABI des GerÀts (z. B. arm64-v8a) und lÀdt das passende Gadget
- FĂŒgt optional android.permission.INTERNET hinzu, wenn nötig
- Injiziert einen statischen Klasseninitialisierer, der System.loadLibrary(âfrida-gadgetâ) in die Launch-Activity aufruft
- Platziert Folgendes unter
lib/<abi>/: - libfrida-gadget.so
- libfrida-gadget.config.so (serialisierte Konfiguration)
- libfrida-gadget.script.so (dein _agent.js)
Beispiel injizierter smali (statischer Initialisierer):
.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
- ĂberprĂŒfe das 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
Erwartete Ănderungen:
- AndroidManifest.xml kann
<uses-permission android:name="android.permission.INTERNET"/>enthalten - Neue native libs unter
lib/<abi>/wie oben - Launchable activity smali enthÀlt eine statische
<clinit>, die System.loadLibrary(âfrida-gadgetâ) aufruft
- Split APKs
- Patch das base APK (dasjenige, das die MAIN/LAUNCHER Activity deklariert)
- Signiere die verbleibenden Splits mit demselben SchlĂŒssel neu:
objection signapk split1.apk split2.apk ...
- Installiere splits zusammen:
adb install-multiple split1.apk split2.apk ...
- FĂŒr die Distribution kannst du Splits mit APKEditor zu einer einzigen APK zusammenfĂŒhren und dann align/sign
FLAG_SECURE wÀhrend der dynamischen Analyse entfernen
Apps, die getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE) aufrufen, verhindern Screenshots, Remote-Displays und sogar Androidâs recent-task snapshots. Als Freedom Chat dieses Flag erzwang, war der einzige Weg, die leaks zu dokumentieren, das Fenster zur Laufzeit zu manipulieren. Ein zuverlĂ€ssiges Muster ist:
- Hook jede
Window-Ăberladung, die das Flag erneut anwenden kann (setFlags,addFlags,setAttributes) und maskiere das Bit0x00002000(WindowManager.LayoutParams.FLAG_SECURE). - Nach jedem Resume einer Activity plane einen UI-Thread-Aufruf zu
clearFlags(FLAG_SECURE), sodass Dialogs/Fragments, die spÀter erstellt werden, den entsperrten Zustand erben. - Apps, die mit React Native / Flutter gebaut wurden, erzeugen oft verschachtelte Windows; hook
android.app.Dialog/android.view.View-Hilfen oder durchlaufegetWindow().peekDecorView(), wenn du weiterhin schwarze Frames siehst.
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>
FĂŒhre das Script mit `frida -U -f <package> -l disable-flag-secure.js --no-pause` aus, interagiere mit der UI, und Screenshots/Aufnahmen funktionieren wieder. Da alles im UI-Thread passiert, gibt es kein Flackern, und du kannst den Hook weiterhin mit HTTP Toolkit/Burp kombinieren, um den Traffic zu erfassen, der den `/channel` PIN leak offenlegte.
## Tutorials
### [Tutorial 1](frida-tutorial-1.md)
**Von**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
**Quellcode**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
**Folge dem [Link, um es zu lesen](frida-tutorial-1.md).**
### [Tutorial 2](frida-tutorial-2.md)
**Von**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
**APKs und Quellcode**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**Folge dem [Link, um es zu lesen.](frida-tutorial-2.md)**
### [Tutorial 3](owaspuncrackable-1.md)
**Von**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
**APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk)
**Folge dem [Link, um es zu lesen](owaspuncrackable-1.md).**
**Weitere groĂartige Frida-Skripte findest du hier:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## Schnellbeispiele
### Frida ĂŒber die Kommandozeile aufrufen
```bash
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.
Grundlegendes Python-Skript
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 von Funktionen ohne Parameter
Hook die Funktion a() der Klasse 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() & .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 von Funktionen mit Parametern und Wertauslesung
Hooking einer decryption function. Gib die Eingabe aus, rufe die Originalfunktion auf, decrypt die Eingabe und gib schlieĂlich die plain data aus:
Hooking a decryption function (Java) â Eingaben/Ausgaben ausgeben
```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 von Funktionen und deren Aufruf mit unseren Eingaben
Hook eine Funktion, die einen string erhÀlt, und rufe sie mit einem anderen string auf (aus [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
}
Ein bereits erstelltes Objekt einer Klasse erhalten
Wenn du ein Attribut eines erstellten Objekts extrahieren möchtest, kannst du Folgendes verwenden.
In diesem Beispiel siehst du, wie du das Objekt der Klasse my_activity erhÀltst und die Funktion .secret() aufrufst, die ein privates Attribut des Objekts ausgibt:
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 () {},
})
Weitere Frida-Tutorials
- https://github.com/DERE-ad2001/Frida-Labs
- Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries
Quellen
- Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa
- Frida Gadget documentation
- Frida releases (server binaries)
- Objection (SensePost)
- Modding And Distributing Mobile Apps with Frida
- frida-jdwp-loader
- Library injection for debuggable Android apps (blog)
- jdwp-lib-injector (original idea/tool)
- jdwp-shellifier
- âSuper secureâ MAGA-themed messaging app leaks everyoneâs phone number
- Android Frida Hooking: Disabling FLAG_SECURE
- frida-ui
Tip
Lernen & ĂŒben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & ĂŒben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & ĂŒben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
UnterstĂŒtzen Sie HackTricks
- ĂberprĂŒfen Sie die AbonnementplĂ€ne!
- Treten Sie der đŹ Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter đŠ @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


