Frida Handleiding

Reading time: 11 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Installasie

Installeer frida tools:

bash
pip install frida-tools
pip install frida

Laai af en installeer op die Android-toestel die frida server (Download the latest release).
Eenreël-opdrag om adb te herbegin in root-modus, daarmee te koppel, frida-server op te laai, exec permissions te gee en dit in die agtergrond te laat loop:

bash
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 &"

Kontroleer of dit werk:

bash
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)

Twee algemene maniere om Android-apps met Frida te instrumenteer:

  • Frida server (rooted devices): Stuur en voer 'n native daemon uit wat jou toelaat om aan enige proses te koppel.
  • Frida Gadget (no root): Bundel Frida as 'n gedeelde biblioteek binne die APK en laai dit outomaties in die teikenproses.

Frida server (rooted)

bash
# 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. Pak die APK uit, voeg die gadget .so en konfigurasie by:
  • Plaas libfrida-gadget.so in lib/<abi>/ (bv. lib/arm64-v8a/)
  • Skep assets/frida-gadget.config met jou instellings vir die laai van skripte

Voorbeeld frida-gadget.config

json
{
"interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" },
"runtime": { "logFile": "/sdcard/frida-gadget.log" }
}
  1. Verwys/laai die gadget sodat dit vroeg geïnitialiseer word:
  • Eenvoudigste: Voeg 'n klein Java-stub by System.loadLibrary("frida-gadget") in Application.onCreate(), of gebruik reeds bestaande native lib loading.
  1. Herpak en teken die APK, en installeer:
bash
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. Koppel vanaf die gasheer aan die gadget-proses:
bash
frida-ps -Uai
frida -U -n com.example.app

Aantekeninge

  • Gadget word deur sommige beskermingsmaatreëls opgespoor; hou name/paaie heimlik en laai laat/voorwaardelik indien nodig.
  • By geharde apps, verkies rooted testing met server + late attach, of kombineer dit met Magisk/Zygisk hiding.

Self-contained agent + Gadget inbedding (Frida 17+; automated with Objection)

Frida 17 het die ingeboude Java/ObjC bridges uit GumJS verwyder. As jou agent Java hooks, moet jy die Java bridge binne jou bundel insluit.

  1. Skep 'n Frida agent (TypeScript) en sluit die Java bridge in
bash
# 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

Minimale Java hook (dwing dobbelrolle na 1):

ts
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);
};
});

Skep 'n enkele bundel vir inbedding:

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

Vinnige USB-toets (opsioneel):

bash
frida -U -f org.secuso.privacyfriendlydicer -l _agent.js
  1. Konfigureer Gadget om jou script outomaties te laai Objection se patcher verwag 'n Gadget config; wanneer jy script mode gebruik, spesifiseer die on-disk path binne die APK lib dir:
json
{
"interaction": {
"type": "script",
"path": "libfrida-gadget.script.so"
}
}
  1. Outomatiseer APK patching met Objection
bash
# 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

Wat patchapk doen (op hoë vlak):

  • Detecteer die toestel se ABI (e.g., arm64-v8a) en haal die ooreenstemmende Gadget
  • Voeg opsioneel android.permission.INTERNET by wanneer dit nodig is
  • Injekteer 'n statiese klass-initialiseerder wat System.loadLibrary("frida-gadget") aanroep in die launch activity
  • Plaas die volgende onder lib/<abi>/:
  • libfrida-gadget.so
  • libfrida-gadget.config.so (geserialiseerde konfigurasie)
  • libfrida-gadget.script.so (jou _agent.js)

Voorbeeld ingespuite smali (statiese initialiseerder):

smali
.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. Verifieer die repack
bash
apktool d org.secuso.privacyfriendlydicer.apk
apktool d org.secuso.privacyfriendlydicer.objection.apk
# Inspect differences
diff -r org.secuso.privacyfriendlydicer org.secuso.privacyfriendlydicer.objection

Verwagte veranderinge:

  • AndroidManifest.xml kan insluit <uses-permission android:name="android.permission.INTERNET"/>
  • Nuwe native libs onder lib// soos hierbo
  • Launchable activity smali bevat 'n statiese <clinit> wat System.loadLibrary("frida-gadget") aanroep
  1. Split APKs
  • Patch die base APK (die een wat MAIN/LAUNCHER activity verklaar)
  • Heronderteken die oorblywende splits met dieselfde sleutel:
bash
objection signapk split1.apk split2.apk ...
  • Installeer splits saam:
bash
adb install-multiple split1.apk split2.apk ...
  • Vir verspreiding kan jy splits saamvoeg in 'n enkele APK met APKEditor, en dan align/sign

Verdedigingsnotas (waarop om te let tydens hardening)

  • Implementeer signature/repackage-kontroles en runtime-integriteit/attestering
  • Detecteer onverwagte System.loadLibrary("frida-gadget") of verdagte native libs by opstart
  • Vermy die verklaring van ongebruikte INTERNET-permissie; verminder gadget-detekteringsoppervlak

Handleidings

Handleiding 1

Vanaf: https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1
APK: https://github.com/t0thkr1s/frida-demo/releases
Bronkode: https://github.com/t0thkr1s/frida-demo

Volg die skakel om dit te lees.

Handleiding 2

Vanaf: https://11x256.github.io/Frida-hooking-android-part-2/ (Parts 2, 3 & 4)
APKs en Bronkode: https://github.com/11x256/frida-android-examples

Volg die skakel om dit te lees.

Handleiding 3

Vanaf: https://joshspicer.com/android-frida-1
APK: https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk

Volg die skakel om dit te lees.

Jy kan meer Awesome Frida-skripte hier vind: https://codeshare.frida.re/

Vinnige Voorbeelde

Frida vanaf die opdragreël aanroep

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.

Basiese Python-skrip

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 funksies sonder parameters

Hook die funksie a() van die klas sg.vantagepoint.a.c

javascript
Java.perform(function () {
;  rootcheck1.a.overload().implementation = function() {
rootcheck1.a.overload().implementation = function() {
send("sg.vantagepoint.a.c.a()Z   Root check 1 HIT!  su.exists()");
return false;
};
});

Hook java exit()

javascript
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()

javascript
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()

javascript
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 functions met parameters en die waarde terugkry

Hooking a decryption function. Druk die invoer, roep die oorspronklike funksie aan om die invoer te decrypt en druk uiteindelik die platte data:

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
}

Hooking functions and calling them with our input

Hook 'n function wat 'n string ontvang en call dit met 'n ander string (van here)

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
}

Verkryding van 'n reeds geskepte objek van 'n klas

As jy 'n attribuut van 'n geskepte objek wil uittrek, kan jy dit gebruik.

In hierdie voorbeeld gaan jy sien hoe om die objek van die klas my_activity te kry en hoe om die funksie .secret() aan te roep wat 'n privaat attribuut van die objek sal afdruk:

javascript
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 () {},
})

Ander Frida handleidings

Verwysings

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks