You've got a third-party APK (Android application package), and you want to debug/trace/explore/reverse-engineer it, and you have your personal Android phone which you don't want to root. You have 2 options with Frida's Gadget then:

  1. Option 1: If targeted APK contains any native library (<apk>/lib/arm64-v8a/, then you can inject as a dependency into the native library.
  2. Option 2: If the APK doesn't contain a native library, then you can inject System.loadLibrary into the bytecode.

How it basically works

Frida Gadget injection

How to check whether injection succeeded

In both cases you need to know whether frida-gadget has been injected successfully.


  1. adb logcat | grep -i frida
    03-24 13:01:24.561 21645 22797 I Frida   : Listening on TCP port 27042
  2. adb shell netstat -ln | grep 27042
    tcp        0      0*               LISTEN
  3. frida-ps -U
      PID  Name
    -----  ------
    21645  Gadget

Note: where to get an APK

Yeah, about this tiny nuance. Google Play doesn't allow you to download APK directly. If you decided to analyze some APK, but you haven't got one yet, you have a bunch of options instead:

Option 1: Inject a as a dependency to a native library (JNI) inside of APK

Basically, you need this article: The reason I put my own steps below: here is a lot of caveats aiming to save my time in future because of buggy versions of different tools, and because I want to escape all unnecessary steps I usually tend to follow.

For this option an APK should contain some native library (most probably JNI), and injection is carried out by adding dependency to the native library.

If an APK doesn't contain native library then jump to the option #2.


Let's say we want to inject in <target.apk>/lib/arm64-v8a/

  1. Download and unpack frida-gadget >= 12.8.8 for Android for arm64 (or arm32) from here
    unxz -d
    WARNING: Frida Gadget from 12.7.0 to 12.8.7 doesn't bring up the server, and the bug had been solved here:
  2. Download and unpack your target APK.
    # Destination would be a directory "target"
    apktool d -rs target.apk
    1. Use apktool >= 2.4.1.
    2. -rs is to not decode resources and sources, it will save you time and keep your nerves while compiling the APK back.
    3. unzip/zip doesn't always work - application may not bring up.
  3. Copy frida-gadget to the unpacked APK directory.
    cp target/lib/arm64-v8a/
  4. Write a Python script (say to inject the frida-gadget using lief (see installation instructions here:
    #!/usr/bin/env python3
    import lief
    libnative = lief.parse("target/lib/arm64-v8a/")
    libnative.add_library("") # Injection!
  5. Run the script - patch JNI.
  6. Check the injection succeeded.
    readelf -d target/lib/arm64-v8a/
    Dynamic section at offset 0xb4000 contains 29 entries:
    Tag        Type                         Name/Value
    0x0000000000000001 (NEEDED)             Shared library: []
  7. Re-pack APK.
    # "target" is a directory with unpacked APK of the step 3.
    apktool b target
  8. Sign APK.
    I used "Uber APK signer":
    java -jar uber-apk-signer-1.1.0.jar -a ./target/dist/target.apk
    WARNING: Archive should have *.apk extension to make Uber Signer work!
  9. Install APK.
    adb install -r target/dist/target-aligned-debugSigned.apk
    1. Allow untrusted third-party APK on your phone.
    2. Use -r flag to "reinstall" APK.

Pay attention that the Frida gadget will start when you trigger the use case in your targeted Android application which leads to a native library loading (something inside the code invokes System.loadLibrary to load and it leads to loading). It may happen at any time and not at the application start.

Check the frida-gadget presence as described in the previous chapter, e.g.

frida-ps -U

Trace the application (attach to a gadget):

frida-trace -U Gadget

Option 2: Injecting into the bytecode

The method is basically described here:

Inject a System.loadLibrary("frida-gadget") call into  the bytecode of the app, ideally before any other bytecode executes or  any native code is loaded. A suitable place is typically the static  initializer of the entry point classes of the app, e.g. the main  application Activity, found via the manifest. An easy way to do this is to add the following smali code in a suitable function:
const-string v0, "frida-gadget"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

"Suitable" place can be a constructor of a main activity which you can find in the AndroidManifest.xml (look for an <application>... <activity>... tag).

# direct methods
.method constructor <init>(Lcom/some/packet/activity/MainActivity;)V
    .locals 0
    const-string v0, "frida-gadget"
    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V

.end method
Load from the <init> function of the MainActivity

Pay attention that in this case Frida gadget will be loaded at the application start, so you have to connect to the one quickly from the computer:

frida-trace -U Gadget


  1. apktool d -r target.apk
    Use apktool >= 2.4.1. Use -r to keep your nerves at the re-packing stage which is a buggy thing usually (let me drop details here).
  2. wget; unxz -d
    Use frida-gadget >= 12.8.8, see
  3. cp target/lib/arm64-v8a/
  4. Edit target/smali/.../A.smali (smali file with a main activity). Add a loadLibrary there as shown in the code snipped above.
  5. apktool b target
  6. java -jar uber-apk-signer-1.1.0.jar -a ./target/dist/target.apk
  7. adb install -r ./target/dist/target-aligned-debugSigned.apk

For more details about each step see description of the option #1 above.

What's next

Go to and take there anything you need to trace with frida.

For example, I started with a script to trace any request to filesystem which is the basic step to start from.

frida --codeshare FrenchYeti/android-file-system-access-hook -f --no-pause

I had to modify the initial script, so I downloaded it from codeshare to tracefs.js, modified it and used like the following:

frida.exe -f tracefs.js -U Gadget

And that's it.