Tutorial de Frida
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Instalación
Instalar frida tools:
pip install frida-tools
pip install frida
Descarga e instala en el dispositivo Android el frida server (Download the latest release).
Comando de una sola línea para reiniciar adb en modo root, conectarse a él, subir frida-server, darle permisos de ejecución y ejecutarlo en segundo plano:
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 &"
Comprueba si está funcionando:
frida-ps -U #List packages and processes
frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
frida-ui (controlador Frida basado en navegador)
frida-ui proporciona una interfaz web en http://127.0.0.1:8000 para listar devices/apps y attach o spawn targets con scripts (no se necesita CLI).
- Instalar (pin
fridato the device server version):
uv tool install frida-ui --with frida==16.7.19
# pipx install frida-ui
# pip install frida-ui
- Ejecutar:
frida-ui
frida-ui --host 127.0.0.1 --port 8000 --reload
- Características: detecta dispositivos USB/locales, añade servidores remotos (
192.168.1.x:27042), y soporta Attach, Spawn, y Spawn & Run (para interceptar antes de la lógica temprana deonCreate()). - Scripting: editor, arrastrar y soltar
.js, importar CodeShare, descargar scripts y session logs. - Servidores remotos:
./frida-server -l 0.0.0.0:27042 -Dlo expone en la red para que frida-ui pueda conectarse sin ADB.
Frida server vs. Gadget (root vs. no-root)
Dos formas comunes de instrumentar aplicaciones Android con Frida:
- Frida server (rooted devices): Push y ejecuta un daemon nativo que te permite attach a cualquier proceso.
- Frida Gadget (no root): Empaqueta Frida como una shared library dentro del APK y la auto-load dentro del proceso objetivo.
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)
- Desempaqueta el APK, añade el gadget .so y la config:
- Coloca libfrida-gadget.so en
lib/<abi>/(p. ej., lib/arm64-v8a/) - Crea assets/frida-gadget.config con la configuración de carga de tus scripts
Ejemplo frida-gadget.config
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
- Referenciar/cargar el gadget para que se inicialice temprano:
- Lo más sencillo: Añade un pequeño stub Java con System.loadLibrary(“frida-gadget”) en Application.onCreate(), o usa la carga de librería nativa ya presente.
- Reempaqueta y firma el APK, luego instala:
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
- Adjuntar desde el host al proceso gadget:
frida-ps -Uai
frida -U -n com.example.app
Notas
- Gadget es detectado por algunas protecciones; mantén nombres/rutas discretos y carga tarde/condicionalmente si es necesario.
- En aplicaciones hardened, prefiere pruebas en dispositivos rooted con servidor + late attach, o combínalo con ocultamiento Magisk/Zygisk.
JDWP-based Frida injection without root/repackaging (frida-jdwp-loader)
Si el APK es debuggable (android:debuggable=“true”), puedes adjuntar mediante JDWP e inyectar una biblioteca nativa en un breakpoint Java. No se necesita root ni reempaquetado del APK.
- Repo: https://github.com/frankheat/frida-jdwp-loader
- Requisitos: ADB, Python 3, depuración USB/ Wireless. La app debe ser debuggable (emulador con
ro.debuggable=1, dispositivo rooted conresetprop, o reconstruir el manifest).
Inicio rápido
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
Notas
- Modos: spawn (detiene en Application.onCreate) o attach (detiene en Activity.onStart). Usa
-bpara establecer un método Java específico,-gpara seleccionar la versión/ruta de Gadget,-ppara elegir el puerto JDWP. - Modo listen: reenvía Gadget (por defecto 127.0.0.1:27042) si es necesario:
adb forward tcp:27042 tcp:27042; luegofrida-ps -H 127.0.0.1:27042. - Esto aprovecha la depuración JDWP. El riesgo es distribuir builds con debuggable habilitado o exponer JDWP.
Agente autocontenido + inclusión de Gadget (Frida 17+; automatizado con Objection)
Frida 17 eliminó los built-in Java/ObjC bridges de GumJS. Si tu agent hooks Java, debes incluir el Java bridge dentro de tu bundle.
- Crea un Frida agent (TypeScript) e incluye el 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 mínimo (obliga las tiradas de dados a 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);
};
});
Crear un único bundle para incrustar:
npm run build # produces _agent.js via frida-compile
Prueba rápida de USB (opcional):
frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
- Configura Gadget para que cargue automáticamente tu script El patcher de Objection espera una Gadget config; cuando uses script mode, especifica la ruta en disco dentro del APK lib dir:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
- Automatizar el parcheo de APKs con 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
Qué hace patchapk (a alto nivel):
- Detecta el ABI del dispositivo (por ejemplo, arm64-v8a) y descarga el Gadget correspondiente
- Opcionalmente añade android.permission.INTERNET cuando es necesario
- Inyecta un static class initializer que llama a System.loadLibrary(“frida-gadget”) en la actividad de lanzamiento
- Coloca lo siguiente bajo
lib/<abi>/: - libfrida-gadget.so
- libfrida-gadget.config.so (config serializada)
- libfrida-gadget.script.so (tu _agent.js)
Ejemplo de smali inyectado (static initializer):
.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
- Verificar el 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
Cambios esperados:
- AndroidManifest.xml puede incluir
<uses-permission android:name="android.permission.INTERNET"/> - Nuevas librerías nativas en
lib/<abi>/como arriba - El smali de la actividad lanzable contiene un
<clinit>estático que llama a System.loadLibrary(“frida-gadget”)
- APKs divididos
- Parchea el APK base (el que declara la actividad MAIN/LAUNCHER)
- Vuelve a firmar los splits restantes con la misma clave:
objection signapk split1.apk split2.apk ...
- Instalar splits juntos:
adb install-multiple split1.apk split2.apk ...
- Para distribución, puedes fusionar los splits en un solo APK con APKEditor, luego alinear/firmar
Eliminando FLAG_SECURE durante el análisis dinámico
Las apps que llaman a getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE) impiden las capturas de pantalla, las pantallas remotas e incluso las instantáneas de tareas recientes de Android. Cuando Freedom Chat impuso este flag la única forma de documentar los leaks fue manipular la ventana en tiempo de ejecución. Un patrón fiable es:
- Hook cada sobrecarga de
Windowque pueda volver a aplicar el flag (setFlags,addFlags,setAttributes) y enmascara el bit0x00002000(WindowManager.LayoutParams.FLAG_SECURE). - Después de que cada activity reanude, programa una llamada en el hilo de la UI a
clearFlags(FLAG_SECURE)para que los Dialogs/Fragments creados después hereden el estado desbloqueado. - Apps construidas con React Native / Flutter a menudo crean ventanas anidadas; hook
android.app.Dialog/android.view.Viewhelpers o recorregetWindow().peekDecorView()si aún ves marcos negros.
Frida hook para limpiar 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>
Ejecute el script con `frida -U -f <package> -l disable-flag-secure.js --no-pause`, interactúe con la UI, y las capturas/grabaciones volverán a funcionar. Como todo ocurre en el UI thread no hay parpadeo, y aún puedes combinar el hook con HTTP Toolkit/Burp para capturar el tráfico que reveló el PIN `/channel` leak.
## Tutoriales
### [Tutorial 1](frida-tutorial-1.md)
**Fuente**: [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)\
**Código fuente**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
**Sigue el [enlace para leerlo](frida-tutorial-1.md).**
### [Tutorial 2](frida-tutorial-2.md)
**Fuente**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\
**APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**Sigue el [enlace para leerlo.](frida-tutorial-2.md)**
### [Tutorial 3](owaspuncrackable-1.md)
**Fuente**: [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)
**Sigue el [enlace para leerlo](owaspuncrackable-1.md).**
**Puedes encontrar más Awesome Frida scripts aquí:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## Ejemplos rápidos
### Llamando a Frida desde la línea de comandos
```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.
Script básico de Python
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 funciones sin parámetros
Hook la función a() de la clase 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 de funciones con parámetros y recuperación del valor
Hooking a decryption function. Imprime el input, llama a la función original para decrypt the input y, finalmente, imprime el plain data:
Hooking a decryption function (Java) — imprimir entradas/salidas
```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 functions y llamarlas con nuestra entrada
Hook a function que recibe un string y llámala con otro string (desde [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
}
Obtener un objeto ya creado de una clase
Si quieres extraer algún atributo de un objeto ya creado, puedes usar esto.
En este ejemplo verás cómo obtener el objeto de la clase my_activity y cómo llamar a la función .secret() que imprimirá un atributo privado del objeto:
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 () {},
})
Otros tutoriales de Frida
- https://github.com/DERE-ad2001/Frida-Labs
- Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries
Referencias
- 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
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


