Skip to main content

JNITrace EX: trace JNI in Android apps (Frida 16+/17+)

Project description

JNITrace EX

An updated JNITrace that works with the latest Frida (16.x and 17.x).

JNITrace EX is a maintained fork of chame1eon/jnitrace, modernized to run on current Frida and Python versions. It traces use of the JNI API in Android apps—similar to frida-trace or strace, but for the JNI.


Why JNITrace EX?

The original jnitrace targeted older Frida (e.g. 14.x) and Python 2/3.4–3.7. This version was created so you can use JNI tracing with:

  • Frida 16 and 17 – Updated Python API usage and a patch for jnitrace-engine so Module.findExportByName(null, …) is replaced with Module.findGlobalExportByName(…) (Frida 17 breaking change).
  • Python 3.7+ – Version and script loading use importlib_metadata / importlib_resources (with fallbacks) instead of deprecated pkg_resources.
  • Stable terminal output – Unbuffered stdout and flushes so trace output appears in the terminal without needing adb logcat.
  • Easy run-from-source./scripts/jnitrace.sh runs jnitrace from the repo using the project’s venv and PYTHONPATH, so you don’t depend on a global pip install jnitrace.

Repository: https://github.com/L0WK3Y-IAAN/jnitrace-ex


Installation

From PyPI:

pip install jnitrace-ex

After install, run the CLI with jnitrace (same as before).

From source:

Use a Python that has Frida installed (e.g. 3.12). Create a venv with a stable Python path, then install:

cd /path/to/jnitrace-ex
/path/to/python3 -m venv .venv   # e.g. /Library/Frameworks/Python.framework/Versions/3.12/bin/python3
.venv/bin/pip install -e .
.venv/bin/pip install -r requirements.txt

Run without installing the CLI (script uses repo + venv):

./scripts/jnitrace.sh -l libnative-lib.so -b none com.example.myapplication

Troubleshooting:

  • bad interpreter: ... python3.14: no such file or directory – Recreate the venv with a Python that stays in the same place, or run: .venv/bin/python3 -m jnitrace.jnitrace ...
  • ModuleNotFoundError: No module named 'frida' – Install Frida for that interpreter: pip install frida, or use the same Python as frida-tools.
  • ModuleNotFoundError: No module named 'jnitrace' – From repo root run .venv/bin/pip install -e ., or use ./scripts/jnitrace.sh (no install needed).
  • TypeError: not a function in jnitrace-engine – Try running from source so the Frida script is built with your environment: clone the repo, then ./scripts/jnitrace.sh -l lib.so -b none com.example.app. If that works, reinstall from PyPI (pip install --force-reinstall jnitrace-ex) to get a fresh build, or use the run-from-source method.

Dependencies:

  • Android device (arm, arm64, x86, or x64) with frida-server (16.x or 17.x)
  • Host: Python 3.7+, Frida 16+, colorama, hexdump, importlib_resources

Running

Start frida-server on the device, then:

# Spawn app and trace (recommended)
./scripts/jnitrace.sh -l libnative-lib.so -b none com.example.myapplication

# Or after pip install
jnitrace -l libnative-lib.so com.example.myapplication

Required:

  • -l libnative-lib.so – Library to trace. Use multiple -l for several libs, or -l * for all.
  • com.example.myapplication – Package name (must be installed on the device).

Useful options:

  • -b none – Disable backtrace (reduces overhead; often needed so the app doesn’t crash under tracing).
  • -m attach – Attach to an already running process by name (e.g. -m attach "AppName").
  • -R [host:port] – Remote Frida server (default 127.0.0.1:27042).
  • -i <regex> – Include only JNI methods matching the regex (e.g. -i "NewStringUTF|CallIntMethod").
  • -e <regex> – Exclude JNI methods matching the regex.
  • -o path/output.json – Save trace to JSON.
  • -p path/to/script.js – Load a Frida script before jnitrace (e.g. anti-Frida bypass).
  • -a path/to/script.js – Load a Frida script after jnitrace.
  • --hide-data – Hide hexdumps and extra data.
  • --ignore-env / --ignore-vm – Skip JNIEnv or JavaVM calls.

Start frida-server:

adb shell /data/local/tmp/frida-server

Optional arguments (reference)

Option Description
-b <fuzzy|accurate|none> Backtrace mode. Default accurate; use none to avoid crashes on some apps.
-i <regex> Include only JNI methods whose names match (can be used multiple times).
-e <regex> Exclude JNI methods whose names match.
-I <string> Include only these library exports (e.g. Java_... or RegisterNatives methods).
-E <string> Exclude these library exports.
--aux name=(string|bool|int)value Aux options when spawning (e.g. --aux='uid=(int)10').

Building from source

Build the Frida script (needed for run-from-source or custom changes):

npm install
npm run build

npm run watch compiles on change. The built script is jnitrace/build/jnitrace.js. A patch is applied to jnitrace-engine (via patch-package) for Frida 17 compatibility.


Output

Output is colored by thread. Each JNI call shows:

  • Thread ID
  • Timestamp (ms)
  • Method name (e.g. JNIEnv->NewStringUTF)
  • Arguments (|-) and return value (|=)
  • Optional backtrace when -b is not none

String arguments and return values (e.g. from NewStringUTF) are shown in braces. With -b none, trace is lighter and less likely to destabilize the app.


API (jnitrace-engine)

The engine is available as a separate npm package for custom Frida scripts:

import { JNIInterceptor } from "jnitrace-engine";

JNIInterceptor.attach("FindClass", {
    onEnter(args) {
        console.log("FindClass method called");
        this.className = Memory.readCString(args[1]);
    },
    onLeave(retval) {
        console.log("\tLoading Class:", this.className);
        console.log("\tClass ID:", retval.get());
    }
});

More: jnitrace-engine


How it works (summary)

jnitrace injects a Frida script that hooks library loading (dlopen/dlsym). For libraries you choose with -l, it builds a shadow JNIEnv and replaces the real one so only those libs’ JNI calls go through trampolines. Arguments and return values are captured and sent to the Python host, which formats and prints them. Variadic JNI calls are handled by tracking GetMethodID/GetStaticMethodID and building method signatures so the correct NativeCallbacks can be created per call.


Issues

For bugs or questions about JNITrace EX, open an issue at:

https://github.com/L0WK3Y-IAAN/jnitrace-ex/issues

Please include:

  • Device and Android version
  • Frida version (host and frida-server)
  • Target app (package name)
  • Exact command and any error output

For the original jnitrace or the engine, see chame1eon/jnitrace and chame1eon/jnitrace-engine.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jnitrace_ex-1.0.1.tar.gz (33.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jnitrace_ex-1.0.1-py3-none-any.whl (30.4 kB view details)

Uploaded Python 3

File details

Details for the file jnitrace_ex-1.0.1.tar.gz.

File metadata

  • Download URL: jnitrace_ex-1.0.1.tar.gz
  • Upload date:
  • Size: 33.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jnitrace_ex-1.0.1.tar.gz
Algorithm Hash digest
SHA256 efc5449db1927ea27761bb2f305930ea8d01be1b7b13bba7c34e31d6e2a59601
MD5 1389b93547f1c2ffb88334bd704bfd38
BLAKE2b-256 5e590d85d546207584f0622d626546c8bbd79134fcf76b1cd38b564b06868611

See more details on using hashes here.

Provenance

The following attestation bundles were made for jnitrace_ex-1.0.1.tar.gz:

Publisher: publish.yml on L0WK3Y-IAAN/jnitrace-ex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jnitrace_ex-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: jnitrace_ex-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 30.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for jnitrace_ex-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5fba3ced9e082d0908605187b8f0d44a48e1268c710cd1042bf0aa61c54ea4a3
MD5 8c9b7661d542be5038a4a461e94b8c64
BLAKE2b-256 e60bce7edb4f43ab25b03f79488f1b3a41da8bb5ea98d20c0ea0c00a1759505c

See more details on using hashes here.

Provenance

The following attestation bundles were made for jnitrace_ex-1.0.1-py3-none-any.whl:

Publisher: publish.yml on L0WK3Y-IAAN/jnitrace-ex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page