overview.md (21717B)
1 --- 2 title: "Frida Tutorial" 3 section: "Mobile" 4 sectionSlug: "mobile-pentesting" 5 sourcePath: "src/mobile-pentesting/android-app-pentesting/frida-tutorial/README.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/android-app-pentesting/frida-tutorial/README.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: true 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Frida Tutorial 14 15 ## Installation 16 17 Install **frida tools**: 18 19 ```bash 20 pip install frida-tools 21 pip install frida 22 ``` 23 24 **Download and install** in the android the **frida server** ([Download the latest release](https://github.com/frida/frida/releases)).<sup>[[3]](#references)</sup>\ 25 One-liner to restart adb in root mode, connect to it, upload frida-server, give exec permissions and run it in backgroud: 26 27 ```bash 28 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 &" 29 ``` 30 31 **Check** if it is **working**: 32 33 ```bash 34 frida-ps -U #List packages and processes 35 frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name 36 ``` 37 38 ## frida-ui (browser-based Frida controller) 39 40 **frida-ui** provides a web UI on `http://127.0.0.1:8000` to list devices/apps and attach or spawn targets with scripts (no CLI needed).<sup>[[12]](#references)</sup> 41 42 - Install (pin `frida` to the device server version): 43 44 ```bash 45 uv tool install frida-ui --with frida==16.7.19 46 # pipx install frida-ui 47 # pip install frida-ui 48 ``` 49 50 - Run: 51 52 ```bash 53 frida-ui 54 frida-ui --host 127.0.0.1 --port 8000 --reload 55 ``` 56 57 - Features: discovers USB/local devices, add remote servers (`192.168.1.x:27042`), and supports **Attach**, **Spawn**, and **Spawn & Run** (to hook before early `onCreate()` logic). 58 - Scripting: editor, drag & drop `.js`, import CodeShare, download scripts and session logs. 59 - Remote servers: `./frida-server -l 0.0.0.0:27042 -D` exposes it on the network so frida-ui can connect without ADB. 60 61 ## Frida server vs. Gadget (root vs. no-root) 62 63 Two common ways to instrument Android apps with Frida:<sup>[[1]](#references)</sup> 64 65 - Frida server (rooted devices): Push and run a native daemon that lets you attach to any process. 66 - Frida Gadget (no root): Bundle Frida as a shared library inside the APK and auto-load it within the target process. 67 68 Frida server (rooted)<sup>[[3]](#references)</sup> 69 70 ```bash 71 # Download the matching frida-server binary for your device's arch 72 # https://github.com/frida/frida/releases 73 adb root 74 adb push frida-server-<ver>-android-<arch> /data/local/tmp/frida-server 75 adb shell chmod 755 /data/local/tmp/frida-server 76 adb shell /data/local/tmp/frida-server & # run at boot via init/magisk if desired 77 78 # From host, list processes and attach 79 frida-ps -Uai 80 frida -U -n com.example.app 81 ``` 82 83 Frida Gadget (no-root) 84 85 1) Unpack the APK, add the gadget .so and config: 86 - Place libfrida-gadget.so into `lib/<abi>/` (e.g., lib/arm64-v8a/) 87 - Create assets/frida-gadget.config with your script loading settings<sup>[[2]](#references)</sup> 88 89 Example frida-gadget.config 90 ```json 91 { 92 "interaction": { "type": "script", "path": "/sdcard/ssl-bypass.js" }, 93 "runtime": { "logFile": "/sdcard/frida-gadget.log" } 94 } 95 ``` 96 97 2) Reference/load the gadget so it’s initialized early: 98 - Easiest: Add a small Java stub to System.loadLibrary("frida-gadget") in Application.onCreate(), or use native lib loading already present. 99 100 3) Repack and sign the APK, then install: 101 ```bash 102 apktool d app.apk -o app_m 103 # ... add gadget .so and config ... 104 apktool b app_m -o app_gadget.apk 105 uber-apk-signer -a app_gadget.apk -o out_signed 106 adb install -r out_signed/app_gadget-aligned-debugSigned.apk 107 ``` 108 109 4) Attach from host to the gadget process: 110 ```bash 111 frida-ps -Uai 112 frida -U -n com.example.app 113 ``` 114 115 Notes 116 - Gadget is detected by some protections; keep names/paths stealthy and load late/conditionally if needed. 117 - On hardened apps, prefer rooted testing with server + late attach, or combine with Magisk/Zygisk hiding. 118 119 ## JDWP-based Frida injection without root/repackaging (frida-jdwp-loader) 120 121 If the APK is debuggable (android:debuggable="true"), you can attach over JDWP and inject a native library at a Java breakpoint. No root and no APK repackaging.<sup>[[6]](#references)[[7]](#references)[[8]](#references)[[9]](#references)</sup> 122 123 - Repo: https://github.com/frankheat/frida-jdwp-loader<sup>[[6]](#references)</sup> 124 - Requirements: ADB, Python 3, USB/Wireless debugging. App must be debuggable (emulator with `ro.debuggable=1`, rooted device with `resetprop`, or rebuild manifest). 125 126 Quick start: 127 ```bash 128 git clone https://github.com/frankheat/frida-jdwp-loader.git 129 cd frida-jdwp-loader 130 # Inject frida-gadget.so into a debuggable target 131 python frida-jdwp-loader.py frida -n com.example.myapplication 132 # Keep the breakpoint thread suspended for early hooks 133 python frida-jdwp-loader.py frida -n com.example.myapplication -s 134 # Networkless: run a local agent script via Gadget "script" mode 135 python frida-jdwp-loader.py frida -n com.example.myapplication -i script -l script.js 136 ``` 137 138 Notes 139 - Modes: spawn (break at Application.onCreate) or attach (break at Activity.onStart). Use `-b` to set a specific Java method, `-g` to select Gadget version/path, `-p` to choose JDWP port. 140 - Listen mode: forward Gadget (default 127.0.0.1:27042) if needed: `adb forward tcp:27042 tcp:27042`; then `frida-ps -H 127.0.0.1:27042`. 141 - This leverages JDWP debugging. Risk is shipping debuggable builds or exposing JDWP. 142 143 ## Self-contained agent + Gadget embedding (Frida 17+; automated with Objection) 144 145 Frida 17 removed the built-in Java/ObjC bridges from GumJS. If your agent hooks Java, you must include the Java bridge inside your bundle. 146 147 1) Create a Frida agent (TypeScript) and include the Java bridge 148 ```bash 149 # Scaffolding 150 frida-create -t agent -o mod 151 cd mod && npm install 152 # Install the Java bridge for Frida 17+ 153 npm install frida-java-bridge 154 # Dev loop (optional live-reload via REPL) 155 npm run watch 156 ``` 157 Minimal Java hook (forces dice rolls to 1): 158 ```text 159 import Java from "frida-java-bridge"; 160 161 Java.perform(function () { 162 var dicer = Java.use("org.secuso.privacyfriendlydicer.dicer.Dicer"); 163 dicer.rollDice.implementation = function (numDice: number, numFaces: number) { 164 return Array(numDice).fill(1); 165 }; 166 }); 167 ``` 168 Build a single bundle for embedding: 169 ```bash 170 npm run build # produces _agent.js via frida-compile 171 ``` 172 Quick USB test (optional): 173 ```bash 174 frida -U -f org.secuso.privacyfriendlydicer -l _agent.js 175 ``` 176 177 2) Configure Gadget to auto-load your script 178 Objection’s patcher expects a Gadget config; when using script mode, specify the on-disk path inside the APK lib dir:<sup>[[4]](#references)</sup> 179 ```json 180 { 181 "interaction": { 182 "type": "script", 183 "path": "libfrida-gadget.script.so" 184 } 185 } 186 ``` 187 188 3) Automate APK patching with Objection 189 ```bash 190 # Embed Gadget, config, and your compiled agent into the APK; rebuild and sign 191 objection patchapk -s org.secuso.privacyfriendlydicer.apk \ 192 -c gadget-config.json \ 193 -l mod/_agent.js \ 194 --use-aapt2 195 ``` 196 What patchapk does (high level):<sup>[[4]](#references)[[5]](#references)</sup> 197 - Detects device ABI (e.g., arm64-v8a) and fetches matching Gadget 198 - Optionally adds android.permission.INTERNET when needed 199 - Injects a static class initializer calling System.loadLibrary("frida-gadget") into the launch activity 200 - Places the following under `lib/<abi>/`: 201 - libfrida-gadget.so 202 - libfrida-gadget.config.so (serialized config) 203 - libfrida-gadget.script.so (your _agent.js) 204 205 Example injected smali (static initializer): 206 ```text 207 .method static constructor <clinit>()V 208 .locals 1 209 const-string v0, "frida-gadget" 210 invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V 211 return-void 212 .end method 213 ``` 214 215 4) Verify the repack<sup>[[5]](#references)</sup> 216 ```bash 217 apktool d org.secuso.privacyfriendlydicer.apk 218 apktool d org.secuso.privacyfriendlydicer.objection.apk 219 # Inspect differences 220 diff -r org.secuso.privacyfriendlydicer org.secuso.privacyfriendlydicer.objection 221 ``` 222 Expected changes: 223 - AndroidManifest.xml may include `<uses-permission android:name="android.permission.INTERNET"/>` 224 - New native libs under `lib/<abi>/` as above 225 - Launchable activity smali contains a static `<clinit>` that calls System.loadLibrary("frida-gadget") 226 227 5) Split APKs 228 - Patch the base APK (the one that declares MAIN/LAUNCHER activity) 229 - Re-sign remaining splits with the same key: 230 ```bash 231 objection signapk split1.apk split2.apk ... 232 ``` 233 - Install splits together: 234 ```bash 235 adb install-multiple split1.apk split2.apk ... 236 ``` 237 - For distribution, you can merge splits into a single APK with APKEditor, then align/sign 238 239 ## Clearing FLAG_SECURE during dynamic analysis 240 241 Apps that call `getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE)` prevent screenshots, remote displays and even Android's recent-task snapshots. When Freedom Chat enforced this flag the only way to document the leaks was to tamper with the window at runtime.<sup>[[10]](#references)</sup> A reliable pattern is:<sup>[[11]](#references)</sup> 242 243 - Hook every `Window` overload that can re-apply the flag (`setFlags`, `addFlags`, `setAttributes`) and mask out bit `0x00002000` (`WindowManager.LayoutParams.FLAG_SECURE`). 244 - After each activity resumes, schedule a UI-thread call to `clearFlags(FLAG_SECURE)` so Dialogs/Fragments created later inherit the unlocked state. 245 - Apps built with React Native / Flutter often create nested windows; hook `android.app.Dialog`/`android.view.View` helpers or walk `getWindow().peekDecorView()` if you still see black frames. 246 247 <details> 248 <summary>Frida hook clearing Window.FLAG_SECURE</summary> 249 250 ```javascript 251 Java.perform(function () { 252 var LayoutParams = Java.use("android.view.WindowManager$LayoutParams"); 253 var FLAG_SECURE = LayoutParams.FLAG_SECURE.value; 254 var Window = Java.use("android.view.Window"); 255 var Activity = Java.use("android.app.Activity"); 256 257 function strip(value) { 258 var masked = value & (~FLAG_SECURE); 259 if (masked !== value) { 260 console.log("[-] Stripped FLAG_SECURE from 0x" + value.toString(16)); 261 } 262 return masked; 263 } 264 265 Window.setFlags.overload('int', 'int').implementation = function (flags, mask) { 266 return this.setFlags.call(this, strip(flags), strip(mask)); 267 }; 268 269 Window.addFlags.implementation = function (flags) { 270 return this.addFlags.call(this, strip(flags)); 271 }; 272 273 Window.setAttributes.implementation = function (attrs) { 274 attrs.flags.value = strip(attrs.flags.value); 275 return this.setAttributes.call(this, attrs); 276 }; 277 278 Activity.onResume.implementation = function () { 279 this.onResume(); 280 var self = this; 281 Java.scheduleOnMainThread(function () { 282 try { 283 self.getWindow().clearFlags(FLAG_SECURE); 284 console.log("[+] Cleared FLAG_SECURE on " + self.getClass().getName()); 285 } catch (err) { 286 console.log("[!] clearFlags failed: " + err); 287 } 288 }); 289 }; 290 }); 291 ``` 292 293 </details> 294 295 Run the script with `frida -U -f <package> -l disable-flag-secure.js --no-pause`, interact with the UI, and screenshots/recordings will work again. Because everything happens on the UI thread there is no flicker, and you can still combine the hook with HTTP Toolkit/Burp to capture the traffic that revealed the `/channel` PIN leak.<sup>[[10]](#references)</sup> 296 297 ## Dynamic DEX dumping / unpacking with clsdumper (Frida) 298 299 `clsdumper` is a Frida-based dynamic **DEX/class dumper** that survives hardened apps by combining an anti-Frida pre-stage with native and Java discovery strategies (works even if `Java.perform()` dies). Requirements: Python 3.10+, rooted device with `frida-server` running, USB or `--host` TCP connection.<sup>[[13]](#references)</sup> 300 301 **Install & quick use** 302 ```bash 303 pip install clsdumper 304 # Attach to a running app 305 clsdumper com.example.app 306 # Spawn first (hooks before early loaders) 307 clsdumper com.example.app --spawn 308 # Select strategies 309 clsdumper com.example.app --strategies fart_dump,oat_extract 310 ``` 311 312 **CLI options (most useful)** 313 - `target`: package name or PID. 314 - `--spawn`: spawn instead of attach. 315 - `--host <ip>`: connect to remote frida-server. 316 - `--strategies <comma>`: limit/choose extractors; default is all except `mmap_hook` (expensive). 317 - `--no-scan` / `--deep-scan`: disable or slow deep memory scan (adds CDEX scanning). 318 - `--extract-classes`: post-process dumps into `.smali` via androguard. 319 - `--no-anti-frida`: skip the pre-hook bypass stage. 320 - `--list` / `--list-apps`: enumerate running processes or installed packages. 321 322 **Anti-instrumentation bypass (phase 0)** 323 - Hooks `sigaction`/`signal` to block registration of crash/anti-debug handlers. 324 - Serves a filtered `/proc/self/maps` via `memfd_create` to hide Frida regions. 325 - Monitors `pthread_create` to catch/neutralize watchdog threads hunting Frida. 326 327 **DEX discovery (phases 1–2)** — multiple complementary strategies with per-hit metadata + deduplication (agent-side djb2, host-side SHA-256): 328 - Native (no Java bridge needed): `art_walk` (walk ART Runtime→ClassLinker→DexFile), `open_common_hook` (hook `DexFile::OpenCommon`), `memory_scan` (DEX magic in readable maps), `oat_extract` (parse mapped .vdex/.oat), `fart_dump` (hook `DefineClass` + walk `class_table_`), `dexfile_constructor` (hook `OatDexFile` constructors), `mmap_hook` (watch `mmap/mmap64`, off by default for perf). 329 - Java (when available): `cookie` (read `mCookie` from ClassLoaders), `classloader_hook` (monitor `loadClass`, `DexClassLoader`, `InMemoryDexClassLoader`). 330 331 **Output layout** 332 ```text 333 dump_<target>/ 334 dex/classes_001.dex ... 335 classes/ # only when --extract-classes 336 metadata.json # strategy per hit + hashes 337 ``` 338 339 Tip: protected apps often load code from several sources (in-memory payload, vdex/oat, custom loaders). Running with the default multi-strategy set plus `--spawn` maximizes coverage; enable `--deep-scan` only when needed to avoid performance hits. 340 341 ## Tutorials 342 343 ### [Tutorial 1](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1) 344 345 **From**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\ 346 **APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\ 347 **Source Code**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo) 348 349 **Follow the [link to read it](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1).** 350 351 ### [Tutorial 2](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2) 352 353 **From**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (Parts 2, 3 & 4)\ 354 **APKs and Source code**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples) 355 356 **Follow the [link to read it.](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2)** 357 358 ### [Tutorial 3](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1) 359 360 **From**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\ 361 **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) 362 363 **Follow the [link to read it](/hacktricks/mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1).** 364 365 **You can find more Awesome Frida scripts here:** [**https://codeshare.frida.re/**](https://codeshare.frida.re) 366 367 ## Quick Examples 368 369 ### Calling Frida from command line 370 371 ```bash 372 frida-ps -U 373 374 #Basic frida hooking 375 frida -l disableRoot.js -f owasp.mstg.uncrackable1 376 377 #Hooking before starting the app 378 frida -U --no-pause -l disableRoot.js -f owasp.mstg.uncrackable1 379 #The --no-pause and -f options allow the app to be spawned automatically, 380 #frozen so that the instrumentation can occur, and the automatically 381 #continue execution with our modified code. 382 ``` 383 384 ### Basic Python Script 385 386 ```python 387 import frida, sys 388 389 jscode = open(sys.argv[0]).read() 390 process = frida.get_usb_device().attach('infosecadventures.fridademo') 391 script = process.create_script(jscode) 392 print('[ * ] Running Frida Demo application') 393 script.load() 394 sys.stdin.read() 395 ``` 396 397 ### Hooking functions without parameters 398 399 Hook the function `a()` of the class `sg.vantagepoint.a.c` 400 401 ```javascript 402 Java.perform(function () { 403 rootcheck1.a.overload().implementation = function () { 404 return false; 405 }; 406 }); 407 ``` 408 409 Hook java `exit()` 410 411 ```javascript 412 var sysexit = Java.use("java.lang.System") 413 sysexit.exit.overload("int").implementation = function (var_0) { 414 send("java.lang.System.exit(I)V // We avoid exiting the application :)") 415 } 416 ``` 417 418 Hook MainActivity `.onStart()` & `.onCreate()` 419 420 ```javascript 421 var mainactivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity") 422 mainactivity.onStart.overload().implementation = function () { 423 send("MainActivity.onStart() HIT!!!") 424 var ret = this.onStart.overload().call(this) 425 } 426 mainactivity.onCreate.overload("android.os.Bundle").implementation = function ( 427 var_0 428 ) { 429 send("MainActivity.onCreate() HIT!!!") 430 var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0) 431 } 432 ``` 433 434 Hook android `.onCreate()` 435 436 ```javascript 437 var activity = Java.use("android.app.Activity") 438 activity.onCreate.overload("android.os.Bundle").implementation = function ( 439 var_0 440 ) { 441 send("Activity HIT!!!") 442 var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0) 443 } 444 ``` 445 446 ### Hooking functions with parameters and retrieving the value 447 448 Hooking a decryption function. Print the input, call the original function decrypt the input and finally, print the plain data: 449 450 <details> 451 <summary>Hooking a decryption function (Java) — print inputs/outputs</summary> 452 453 ```javascript 454 function getString(data) { 455 var ret = "" 456 for (var i = 0; i < data.length; i++) { 457 ret += data[i].toString() 458 } 459 return ret 460 } 461 var aes_decrypt = Java.use("sg.vantagepoint.a.a") 462 aes_decrypt.a.overload("[B", "[B").implementation = function (var_0, var_1) { 463 send("sg.vantagepoint.a.a.a([B[B)[B doFinal(enc) // AES/ECB/PKCS7Padding") 464 send("Key : " + getString(var_0)) 465 send("Encrypted : " + getString(var_1)) 466 var ret = this.a.overload("[B", "[B").call(this, var_0, var_1) 467 send("Decrypted : " + ret) 468 469 var flag = "" 470 for (var i = 0; i < ret.length; i++) { 471 flag += String.fromCharCode(ret[i]) 472 } 473 send("Decrypted flag: " + flag) 474 return ret //[B 475 } 476 ``` 477 478 </details> 479 480 ### Hooking functions and calling them with our input 481 482 Hook a function that receives a string and call it with other string (from [here](https://11x256.github.io/Frida-hooking-android-part-2/)) 483 484 ```javascript 485 var string_class = Java.use("java.lang.String") // get a JS wrapper for java's String class 486 487 my_class.fun.overload("java.lang.String").implementation = function (x) { 488 //hooking the new function 489 var my_string = string_class.$new("My TeSt String#####") //creating a new String by using `new` operator 490 console.log("Original arg: " + x) 491 var ret = this.fun(my_string) // calling the original function with the new String, and putting its return value in ret variable 492 console.log("Return value: " + ret) 493 return ret 494 } 495 ``` 496 497 ### Getting an already created object of a class 498 499 If you want to extract some attribute of a created object you can use this. 500 501 In this example you are going to see how to get the object of the class my_activity and how to call the function .secret() that will print a private attribute of the object: 502 503 ```javascript 504 Java.choose("com.example.a11x256.frida_test.my_activity", { 505 onMatch: function (instance) { 506 //This function will be called for every instance found by frida 507 console.log("Found instance: " + instance) 508 console.log("Result of secret func: " + instance.secret()) 509 }, 510 onComplete: function () {}, 511 }) 512 ``` 513 514 ## Other Frida tutorials 515 516 - [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs) 517 - [Part 1 of Advanced Frida Usage blog series: IOS Encryption Libraries](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/) 518 519 520 ## References 521 522 - [1] [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools) 523 - [2] [Frida Gadget documentation](https://frida.re/docs/gadget/) 524 - [3] [Frida releases (server binaries)](https://github.com/frida/frida/releases) 525 - [4] [Objection (SensePost)](https://github.com/sensepost/objection) 526 - [5] [Modding And Distributing Mobile Apps with Frida](https://pit.bearblog.dev/modding-and-distributing-mobile-apps-with-frida/) 527 - [6] [frida-jdwp-loader](https://github.com/frankheat/frida-jdwp-loader) 528 - [7] [Library injection for debuggable Android apps (blog)](https://koz.io/library-injection-for-debuggable-android-apps/) 529 - [8] [jdwp-lib-injector (original idea/tool)](https://github.com/ikoz/jdwp-lib-injector) 530 - [9] [jdwp-shellifier](https://github.com/hugsy/jdwp-shellifier) 531 - [10] ["Super secure" MAGA-themed messaging app leaks everyone’s phone number](https://ericdaigle.ca/posts/super-secure-maga-messaging-app-leaks-everyones-phone-number/) 532 - [11] [Android Frida Hooking: Disabling FLAG_SECURE](https://www.securify.nl/en/blog/android-frida-hooking-disabling-flagsecure/) 533 - [12] [frida-ui](https://github.com/adityatelange/frida-ui) 534 - [13] [clsdumper — Android Dynamic Class Dumper](https://github.com/TheQmaks/clsdumper)