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
Descargar e instalar en el android el frida server (Download the latest release).
Comando de una 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 &"
Comprobar 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 de Frida basado en navegador)
frida-ui proporciona una interfaz web en http://127.0.0.1:8000 para listar dispositivos/apps y attach o spawn targets con scripts (no se necesita CLI).
- Instalar (fijar
fridaa la versión del device server):
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: descubre dispositivos USB/locales, añade servidores remotos (
192.168.1.x:27042), y soporta Attach, Spawn, y Spawn & Run (para hookear antes de la lógica temprana deonCreate()). - Scripting: editor, arrastrar y soltar
.js, importar CodeShare, descargar scripts y logs de sesión. - 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): Sube y ejecuta un daemon nativo que te permite hacer attach a cualquier proceso.
- Frida Gadget (no root): Empaqueta Frida como una librería compartida dentro del APK y la carga automáticamente 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 .so del gadget y la configuración:
- Coloca libfrida-gadget.so en
lib/<abi>/(p. ej., lib/arm64-v8a/) - Crea assets/frida-gadget.config con la configuración para cargar tus scripts
Ejemplo frida-gadget.config
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
- Referencia/carga el gadget para que se inicialice temprano:
- Lo más sencillo: Añade un pequeño stub Java que llame a System.loadLibrary(“frida-gadget”) en Application.onCreate(), o utiliza 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
- Conectarse desde el host al proceso gadget:
frida-ps -Uai
frida -U -n com.example.app
Notas
- Gadget is detected by some protections; keep names/paths stealthy and load late/conditionally if needed.
- On hardened apps, prefer rooted testing with server + late attach, or combine with Magisk/Zygisk hiding.
Inyección Frida basada en JDWP sin root/reempaquetado (frida-jdwp-loader)
Si el APK es debuggable (android:debuggable=“true”), puedes attach over JDWP e inyectar una librería nativa en un breakpoint de Java. No root y no reempaquetado del APK.
- Repo: https://github.com/frankheat/frida-jdwp-loader
- Requisitos: ADB, Python 3, USB/Wireless debugging. La app debe ser debuggable (emulator with
ro.debuggable=1, rooted device withresetprop, or rebuild 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
Notes
- Modos: spawn (break at Application.onCreate) o attach (break at Activity.onStart). Usa
-bpara establecer un método Java específico,-gpara seleccionar la versión/ruta de Gadget,-ppara elegir el puerto JDWP. - Listen mode: forward Gadget (default 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 debuggable builds o exponer JDWP.
Self-contained agent + Gadget embedding (Frida 17+; automated with Objection)
Frida 17 removed the built-in Java/ObjC bridges from GumJS. Si tu agente hooks Java, debes incluir el Java bridge dentro de tu bundle.
- Create a Frida agent (TypeScript) and include the 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 mínimo de Java (obliga a que las tiradas de dados sean 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 bundle único 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
- Configurar Gadget para cargar automáticamente tu script El patcher de Objection espera una configuración de Gadget; al usar script mode, especifica la ruta en disco dentro del lib dir del APK:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
- Automatizar el parcheo de APK 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
Lo que 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 inicializador de clase estático 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 serializado)
- libfrida-gadget.script.so (tu _agent.js)
Ejemplo de smali inyectado (inicializador estático):
.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
- AndroidManifest.xml puede incluir
<uses-permission android:name="android.permission.INTERNET"/> - Nuevas librerías nativas bajo
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 los splits juntos:
adb install-multiple split1.apk split2.apk ...
- Para distribución, puedes combinar los splits en un único APK con APKEditor, luego alinear/firmar
Borrando FLAG_SECURE durante el análisis dinámico
Las apps que llaman a getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE) impiden capturas de pantalla, displays remotos y hasta las instantáneas de tareas recientes de Android. Cuando Freedom Chat forzó esta bandera la única forma de documentar the leaks fue manipular la ventana en tiempo de ejecución. Un patrón fiable es:
- Hook every
Windowoverload that can re-apply the flag (setFlags,addFlags,setAttributes) and mask out bit0x00002000(WindowManager.LayoutParams.FLAG_SECURE). - Después de que cada activity se reanude, programa una llamada en el hilo de UI a
clearFlags(FLAG_SECURE)para que los Dialogs/Fragments creados después hereden el estado desbloqueado. - Las apps construidas con React Native / Flutter suelen crear ventanas anidadas; hook
android.app.Dialog/android.view.Viewhelpers o recorrergetWindow().peekDecorView()si aún ves black frames.
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>
Ejecuta el script con `frida -U -f <package> -l disable-flag-secure.js --no-pause`, interactúa con la interfaz de usuario, y las capturas de pantalla/las grabaciones volverán a funcionar. Como todo ocurre en el hilo de la interfaz de usuario 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.
## Dynamic DEX dumping / unpacking with clsdumper (Frida)
`clsdumper` es un **DEX/class dumper** dinámico basado en Frida que sobrevive a aplicaciones hardened combinando una etapa previa anti-Frida con estrategias de descubrimiento nativas y en Java (funciona incluso si `Java.perform()` deja de funcionar). Requisitos: Python 3.10+, dispositivo rooteado con `frida-server` en ejecución, conexión USB o TCP con `--host`.
**Instalación y uso rápido**
```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
Opciones CLI (más útiles)
target: nombre del paquete o PID.--spawn: spawn en lugar de attach.--host <ip>: conectar con frida-server remoto.--strategies <comma>: limitar/seleccionar extractors; por defecto todos exceptommap_hook(costoso).--no-scan/--deep-scan: deshabilitar o ralentizar el deep memory scan (añade CDEX scanning).--extract-classes: postprocesar dumps a.smalivía androguard.--no-anti-frida: omitir la etapa de bypass pre-hook.--list/--list-apps: enumerar procesos en ejecución o paquetes instalados.
Bypass anti-instrumentación (fase 0)
- Intercepta
sigaction/signalpara bloquear el registro de manejadores de crash/anti-debug. - Sirve un
/proc/self/mapsfiltrado víamemfd_createpara ocultar regiones de Frida. - Monitorea
pthread_createpara detectar/neutralizar hilos watchdog que buscan Frida.
Descubrimiento DEX (fases 1–2) — múltiples estrategias complementarias con metadata por resultado + deduplicación (lado agente djb2, lado host SHA-256):
- Nativo (no se necesita puente Java):
art_walk(recorre ART Runtime→ClassLinker→DexFile),open_common_hook(hookeaDexFile::OpenCommon),memory_scan(DEX magic en mapas legibles),oat_extract(parsea .vdex/.oat mapeados),fart_dump(hookeaDefineClass+ recorreclass_table_),dexfile_constructor(hookea constructores deOatDexFile),mmap_hook(vigilammap/mmap64, desactivado por defecto por rendimiento). - Java (cuando esté disponible):
cookie(leermCookiede ClassLoaders),classloader_hook(monitorearloadClass,DexClassLoader,InMemoryDexClassLoader).
Formato de salida
dump_<target>/
dex/classes_001.dex ...
classes/ # only when --extract-classes
metadata.json # strategy per hit + hashes
Tip: las apps protegidas a menudo cargan código desde varias fuentes (in-memory payload, vdex/oat, cargadores personalizados). Ejecutar con el conjunto multi-estrategia por defecto más --spawn maximiza la cobertura; habilita --deep-scan solo cuando sea necesario para evitar impactos en el rendimiento.
Tutoriales
Tutorial 1
De: https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1
APK: https://github.com/t0thkr1s/frida-demo/releases
Código fuente: https://github.com/t0thkr1s/frida-demo
Sigue el enlace para leerlo.
Tutorial 2
De: https://11x256.github.io/Frida-hooking-android-part-2/ (Parts 2, 3 & 4)
APKs y código fuente: https://github.com/11x256/frida-android-examples
Sigue el enlace para leerlo.
Tutorial 3
De: https://joshspicer.com/android-frida-1
APK: https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk
Sigue el enlace para leerlo.
Puedes encontrar más scripts de Frida increíbles aquí: https://codeshare.frida.re/
Ejemplos rápidos
Llamar a Frida desde la línea de comandos
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 de 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 obtención del valor
Hooking a decryption function. Imprime la entrada, llama a la función original para decrypt the input y, finalmente, imprime los datos en claro:
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 llamándolas con nuestra entrada
Hook a function que recibe un string y llámala con otro string (from [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 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
- clsdumper — Android Dynamic Class Dumper
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.


