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 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 server vs. Gadget (root vs. no-root)
Dos formas comunes de instrumentar aplicaciones Android con Frida:
- Frida server (rooted devices): Copiar y ejecutar un demonio nativo que te permite adjuntarte a cualquier proceso.
- Frida Gadget (no root): Empaqueta Frida como una biblioteca compartida dentro del APK y cárgala 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 gadget .so y el archivo de configuración:
- Coloca libfrida-gadget.so en
lib/<abi>/(por ejemplo, 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 nativa de librerías 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 del gadget:
frida-ps -Uai
frida -U -n com.example.app
Notas
- Gadget es detectado por algunas protecciones; mantén nombres/rutas discretos y cárgalo tarde/condicionalmente si es necesario.
- En apps hardened, prefiere pruebas con root con server + late attach, o combínalo con ocultación Magisk/Zygisk.
Inyección de Frida basada en JDWP sin root/repackaging (frida-jdwp-loader)
Si el APK es debuggable (android:debuggable=“true”), puedes adjuntar vía JDWP e inyectar una biblioteca nativa en un breakpoint de Java. No root y no APK repackaging.
- 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
Notas
- 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. - Modo escucha: 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 depurables o exponer JDWP.
Agente autocontenido + Gadget embedding (Frida 17+; automated with Objection)
Frida 17 eliminó los built-in Java/ObjC bridges de GumJS. Si tu agente hooks Java, debes incluir el Java bridge dentro de tu bundle.
- Crea un agente Frida (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 (fuerza 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 paquete para embedding:
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 directorio lib del APK:
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
- Automatizar el patching 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 la ABI del dispositivo (p. ej., arm64-v8a) y obtiene el Gadget correspondiente
- Opcionalmente añade android.permission.INTERNET cuando sea necesario
- Inyecta un inicializador estático de clase 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
Cambios esperados:
- 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”)
- Split APKs
- 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 splits en un único APK con APKEditor, luego alinear/firmar
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/ (Partes 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 Awesome Frida scripts aquí: https://codeshare.frida.re/
Ejemplos rápidos
Llamando 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 functions sin parámetros
Hook la función a() de la clase 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() y .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)
}
Hookear 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 de una función de descifrado. Imprime la entrada, llama a la función original para descifrar la entrada y, finalmente, imprime los datos en claro:
Hooking de una función de descifrado (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 nuestro input
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
- Parte 1 de la serie de blogs Advanced Frida Usage: Bibliotecas de cifrado iOS
Referencias
- Crear un laboratorio reproducible de Bug Bounty para Android: Emulator vs Magisk, Burp, Frida, y Medusa
- Documentación de Frida Gadget
- Frida releases (server binaries)
- Objection (SensePost)
- Modificación y distribución de aplicaciones móviles con Frida
- frida-jdwp-loader
- Inyección de librerías para aplicaciones Android depurables (blog)
- jdwp-lib-injector (idea/herramienta original)
- jdwp-shellifier
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.
HackTricks

