A Frida based tool that traces usage of the JNI API in Android apps.

Overview

jnitrace

A Frida based tool to trace use of the JNI API in Android apps.

Native libraries contained within Android Apps often make use of the JNI API to utilize the Android Runtime. Tracking those calls through manual reverse engineering can be a slow and painful process. jnitrace works as a dynamic analysis tracing tool similar to frida-trace or strace but for the JNI.

JNITrace Output

Installation:

The easiest way to get running with jnitrace is to install using pip:

pip install jnitrace

Dependencies:
  • arm, arm64, x86, or x64 Android device
  • Frida installed on the Android device
  • Frida support > 12
  • Linux, Mac, or Windows Host with Python 3 and pip

Running:

After a pip install it is easy to run jnitrace:

jnitrace -l libnative-lib.so com.example.myapplication

jnitrace requires a minimum of two parameters to run a trace:

  • -l libnative-lib.so - is used to specify the libraries to trace. This argument can be used multiple times or * can be used to track all libraries. For example, -l libnative-lib.so -l libanother-lib.so or -l *.
  • com.example.myapplication - is the Android package to trace. This package must already be installed on the device.

Optional arguments are listed below:

  • -R : - is used to specify the network location of the remote Frida server. If a : is unspecified, localhost:27042 is used by deafult.
  • -m - is used to specify the Frida attach mechanism to use. It can either be spawn or attach. Spawn is the default and recommended option.
  • -b - is used to control backtrace output. By default jnitrace will run the backtracer in accurate mode. This option can be changed to fuzzy mode or used to stop the backtrace by using the none option. See the Frida docs for an explanation on the differences.
  • -i - is used to specify the method names that should be traced. This can be helpful for reducing the noise in particularly large JNI apps. The option can be supplied multiple times. For example, -i Get -i RegisterNatives would include only JNI methods that contain Get or RegisterNatives in their name.
  • -e - is used to specify the method names that should be ignored in the trace. This can be helpful for reducing the noise in particularly large JNI apps. The option can be supplied multiple times. For example, -e ^Find -e GetEnv would exclude from the results all JNI method names that begin Find or contain GetEnv.
  • -I - is used to specify the exports from a library that should be traced. This is useful for libraries where you only want to trace a small number of methods. The functions jnitrace considers exported are any functions that are directly callable from the Java side, as such, that includes methods bound using RegisterNatives. The option can be supplied multiple times. For example, -I stringFromJNI -I nativeMethod([B)V could be used to include an export from the library called Java_com_nativetest_MainActivity_stringFromJNI and a method bound using RegisterNames with the signature of nativeMethod([B)V.
  • -E is used to specify the exports from a library that should not be traced. This is useful for libraries where you have a group of busy native calls that you want to ignore. The functions jnitrace considers exported are any functions that are directly callable from the Java side, as such, that includes methods bound using RegisterNatives. The option can be supplied multiple times. For example, -E JNI_OnLoad -E nativeMethod would exclude from the trace the JNI_OnLoad function call and any methods with the name nativeMethod.
  • -o path/output.json - is used to specify an output path where jnitrace will store all traced data. The information is stored in JSON format to allow later post-processing of the trace data.
  • -p path/to/script.js - the path provided is used to load a Frida script into the target process before the jnitrace script has loaded. This can be used for defeating anti-frida or anti-debugging code before jnitrace starts.
  • -a path/to/script.js - the path provided is used to load Frida script into the target process after jnitrace has been loaded.
  • --hide-data - used to reduce the quantity of output displayed in the console. This option will hide additional data that is displayed as hexdumps or as string de-references.
  • --ignore-env - using this option will hide all calls the app is making using the JNIEnv struct.
  • --ignore-vm - using this option will hide all calls the app is making using the JavaVM struct.
  • --aux - used to pass custom parameters when spawning an application. For example --aux='uid=(int)10' will spawn the application for user 10 instead of default user 0.

Note

Remember frida-server must be running before running jnitrace. If the default instructions for installing frida have been followed, the following command will start the server ready for jnitrace:

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

API:

The engine that powers jnitrace is available as a separate project. That project allows you to import jnitrace to track individual JNI API calls, in a method familiar to using the Frida Interceptor to attach to functions and addresses.

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 information: https://github.com/chame1eon/jnitrace-engine

Building:

Building jnitrace from source requires that node first be installed. After installing node, the following commands need to be run:

  • npm install
  • npm run watch

npm run watch will run frida-compile in the background compiling the source to the output file, build/jnitrace.js. jnitrace.py loads from build/jnitrace.js by default, so no other changes are required to run the updates.

Output:

JNITrace Output

Like frida-trace, output is colored based on the API call thread.

Immediately below the thread ID in the display is the JNI API method name. Method names match exactly with those seen in the jni.h header file.

Subsequent lines contain a list of arguments indicated by a |-. After the |- characters are the argument type followed by the argument value. For jmethods, jfields and jclasses the Java type will be displayed in curly braces. This is dependent on jnitrace having seen the original method, field, or class lookup. For any methods passing buffers, jnitrace will extract the buffers from the arguments and display it as a hexdump below the argument value.

Return values are displayed at the bottom of the list as |= and will not be present for void methods.

If the backtrace is enabled, a Frida backtrace will be displayed below the method call. Please be aware, as per the Frida docs, the fuzzy backtrace is not always accurate and the accurate backtrace may provide limited results.

Details:

The goal of this project was to create a tool that could trace JNI API calls efficiently for most Android applications.

Unfortunately, the simplest approach of attaching to all function pointers in the JNIEnv structure overloads the application. It causes a crash based on the sheer number of function calls made by other unrelated libraries also using the same functions in libart.so.

To deal with that performance barrier, jnitrace creates a shadow JNIEnv that it can supply to libraries it wants to track. That JNIEnv contains a series of function trampolines that bounce the JNI API calls through some custom Frida NativeCallbacks to track the input and output of those functions.

The generic Frida API does a great job of providing a platform to build those function trampolines with minimal effort. However, that simple approach does not work for all of the JNIEnv API. The key problem with tracing all of the methods is the use of variadic arguments in the API. It is not possible to create the NativeCallback for these functions ahead of time, as it is not known beforehand all the different combinations of Java methods that will be called.

The solution is to monitor the process for calls to GetMethodID or GetStaticMethodID, used to look up method identifiers from the runtime. Once jnitrace sees a jmethodID lookup it has a known mapping of ID to method signature. Later, when a JNI Java method call is made, an initial NativeCallback is used to extract the method ID in the call. That method signature is then parsed to extract the method arguments. Once jnitrace has extracted the arguments in the method, it can dynamically create a NativeCallback for that method. That new NativeCallback is returned and a little bit of architecture specific shellcode deals with setting up the stack and registers to allow that call to run successfully. Those NativeCallbacks for specific methods are cached to allow the callback to run more efficiently if a method if called multiple times.

The other place where a simple NativeCallback is not sufficient for extracting the arguments from a method call, is for calls using a va_args pointer as the final argument. In this case jnitrace uses some code to extract the arguments from the pointer provided. Again this is architecture specific.

All data traced in these function calls is sent to the python console application that formats and displays it to the user.

Recommendations:

Most testing of this tool has been done on an Android x86_64 emulator running Marshmallow. Any issues experienced running on another device, please file an issue, but also, if possible, it is recommended to try running on a similar emulator.

Issues:

For any issues experienced running jnitrace please create an issue on GitHub. Please include the following information in the filed issue:

  • Device you were running on
  • Version of Frida you were using
  • Application you were running against
  • Any displayed error messages
Comments
  • Error includes of null

    Error includes of null

    i got this error

    ERROR: {'type': 'error', 'description': "TypeError: Cannot read property 'includes' of null", 'stack': "TypeError: Cannot read property 'includes' of null
       at jnitrace/src/main.ts:39:22
        at Array.forEach (<anonymous>)
        at Object.onLoaded (jnitrace/src/main.ts:38:26)
        at Object.doCallback (node_modules/jnitrace-engine/dist/index.js:127:13)
        at checkLibrary (node_modules/jnitrace-engine/dist/engine.js:44:9)
        at InvocationContext.<anonymous> (node_modules/jnitrace-engine/dist/engine.js:102:17)", 'fileName': 'jnitrace/src/main.ts', 'lineNumber': 39, 'columnNumber': 22}
    
    opened by smaznet 7
  • argument of type 'NoneType' is not iterable

    argument of type 'NoneType' is not iterable

    Traceback (most recent call last): File "/Users/anaconda3/env/lib/python3.6/site-packages/frida-12.6.11-py3.6-macosx-10.6-intel.egg/frida/core.py", line 298, in _on_message callback(message, data) File "/Users/anaconda3/envs//lib/python3.6/site-packages/jnitrace/jnitrace.py", line 438, in on_message self._print_backtrace(payload["backtrace"]) File "/Users/anaconda3/envs/lib/python3.6/site-packages/jnitrace/jnitrace.py", line 288, in _print_backtrace max_len, max_name, size = self._calculate_backtrace_lengths(backtrace) File "/Users/anaconda3/envs/lib/python3.6/site-packages/jnitrace/jnitrace.py", line 270, in _calculate_backtrace_lengths b_t["module"]["name"], b_t["symbol"]["name"] File "/Users/anaconda3/envs/lib/python3.6/site-packages/jnitrace/jnitrace.py", line 242, in _create_backtrace_symbol if "+" not in symbol_name: TypeError: argument of type 'NoneType' is not iterable

    opened by onegithuber 7
  • output not saved to file when remote?

    output not saved to file when remote?

    $jnitrace -l libEncryptor.so -l libsscronet.so -l libttcrypto.so -l libttmain.so com.zhiliaoapp.musically -R 192.168.86.65:6666 --output jnitrace.log -b accurate --ignore-vm

    $cat jnitrace.log []%

    However, the trace data is printing to stdout. Am I doing something wrong?

    device: arm64-v8a, android 8.1.0 frida: 14.2.13 jnitrace: 3.2.0

    opened by maceip 6
  • filters not working?

    filters not working?

    host: macosx big sur 11.0.1 remote device: arm64-v8a, android 8.1.0 frida: 14.2.13 jnitrace: 3.2.1

    i'm looking to trace one method, yet it looks like it's tracing all of them. Perhaps this native code has inserted it's own hooks you are following?

    output:

    $jnitrace -l '*' -R 192.168.86.65:6666 -i http_verify_sign com.zhiliaoapp.musically
    Tracing. Press any key to quit...
               /* TID 18776 */
        568 ms [+] JavaVM->GetEnv
        568 ms |- JavaVM*          : 0x78258a8200
        568 ms |- void**           : 0x7fee618be0
        568 ms |:     0x78258cb1c0
        568 ms |- jint             : 65542
        568 ms |= jint             : 0
    
        568 ms ----------------------------Backtrace----------------------------
        568 ms |->       0x78075d8d18: JNI_OnLoad+0x44 (libkeva.so:0x78075cb000)
        568 ms |->       0x78075d8d18: JNI_OnLoad+0x44 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        696 ms [+] JNIEnv->FindClass
        696 ms |- JNIEnv*          : 0x78258cb1c0
        696 ms |- char*            : 0x78075e9e24
        696 ms |:     com/bytedance/keva/KevaImpl
        696 ms |= jclass           : 0x89    { com/bytedance/keva/KevaImpl }
    
        696 ms ----------------------------Backtrace----------------------------
        696 ms |->       0x78075d8d3c: JNI_OnLoad+0x68 (libkeva.so:0x78075cb000)
        696 ms |->       0x78075d8d3c: JNI_OnLoad+0x68 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        699 ms [+] JNIEnv->GetMethodID
        699 ms |- JNIEnv*          : 0x78258cb1c0
        699 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        699 ms |- char*            : 0x78075e9e40
        699 ms |:     addMapIntWhenLoading
        699 ms |- char*            : 0x78075e9e55
        699 ms |:     (Ljava/lang/String;IJ)V
        699 ms |= jmethodID        : 0x9bbc2778    { addMapIntWhenLoading(Ljava/lang/String;IJ)V }
    
        699 ms ----------------------------Backtrace----------------------------
        699 ms |->       0x78075d8d68: JNI_OnLoad+0x94 (libkeva.so:0x78075cb000)
        699 ms |->       0x78075d8d68: JNI_OnLoad+0x94 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        703 ms [+] JNIEnv->GetMethodID
        703 ms |- JNIEnv*          : 0x78258cb1c0
        703 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        703 ms |- char*            : 0x78075e9e6d
        703 ms |:     addMapBoolWhenLoading
        703 ms |- char*            : 0x78075e9e83
        703 ms |:     (Ljava/lang/String;ZJ)V
        703 ms |= jmethodID        : 0x9bbc26e8    { addMapBoolWhenLoading(Ljava/lang/String;ZJ)V }
    
        703 ms ----------------------------Backtrace----------------------------
        703 ms |->       0x78075d8d9c: JNI_OnLoad+0xc8 (libkeva.so:0x78075cb000)
        703 ms |->       0x78075d8d9c: JNI_OnLoad+0xc8 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        706 ms [+] JNIEnv->GetMethodID
        706 ms |- JNIEnv*          : 0x78258cb1c0
        706 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        706 ms |- char*            : 0x78075e9e9b
        706 ms |:     addMapFloatWhenLoading
        706 ms |- char*            : 0x78075e9eb2
        706 ms |:     (Ljava/lang/String;FJ)V
        706 ms |= jmethodID        : 0x9bbc2748    { addMapFloatWhenLoading(Ljava/lang/String;FJ)V }
    
        706 ms ----------------------------Backtrace----------------------------
        706 ms |->       0x78075d8dc8: JNI_OnLoad+0xf4 (libkeva.so:0x78075cb000)
        706 ms |->       0x78075d8dc8: JNI_OnLoad+0xf4 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        709 ms [+] JNIEnv->GetMethodID
        709 ms |- JNIEnv*          : 0x78258cb1c0
        709 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        709 ms |- char*            : 0x78075e9eca
        709 ms |:     addMapDoubleWhenLoading
        709 ms |- char*            : 0x78075e9ee2
        709 ms |:     (Ljava/lang/String;DJ)V
        709 ms |= jmethodID        : 0x9bbc2718    { addMapDoubleWhenLoading(Ljava/lang/String;DJ)V }
    
        709 ms -----------------------------Backtrace-----------------------------
        709 ms |->       0x78075d8df4: JNI_OnLoad+0x120 (libkeva.so:0x78075cb000)
        709 ms |->       0x78075d8df4: JNI_OnLoad+0x120 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        713 ms [+] JNIEnv->GetMethodID
        713 ms |- JNIEnv*          : 0x78258cb1c0
        713 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        713 ms |- char*            : 0x78075e9efa
        713 ms |:     addMapLongWhenLoading
        713 ms |- char*            : 0x78075e9f10
        713 ms |:     (Ljava/lang/String;JJ)V
        713 ms |= jmethodID        : 0x9bbc27a8    { addMapLongWhenLoading(Ljava/lang/String;JJ)V }
    
        713 ms -----------------------------Backtrace-----------------------------
        713 ms |->       0x78075d8e20: JNI_OnLoad+0x14c (libkeva.so:0x78075cb000)
        713 ms |->       0x78075d8e20: JNI_OnLoad+0x14c (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        716 ms [+] JNIEnv->GetMethodID
        716 ms |- JNIEnv*          : 0x78258cb1c0
        716 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        716 ms |- char*            : 0x78075e9f28
        716 ms |:     addMapOffsetWhenLoading
        716 ms |- char*            : 0x78075e9f40
        716 ms |:     (Ljava/lang/String;JI)V
        716 ms |= jmethodID        : 0x9bbc27d8    { addMapOffsetWhenLoading(Ljava/lang/String;JI)V }
    
        716 ms -----------------------------Backtrace-----------------------------
        716 ms |->       0x78075d8e4c: JNI_OnLoad+0x178 (libkeva.so:0x78075cb000)
        716 ms |->       0x78075d8e4c: JNI_OnLoad+0x178 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        719 ms [+] JNIEnv->FindClass
        719 ms |- JNIEnv*          : 0x78258cb1c0
        719 ms |- char*            : 0x78075e9f58
        719 ms |:     java/lang/RuntimeException
        719 ms |= jclass           : 0x91    { java/lang/RuntimeException }
    
        719 ms -----------------------------Backtrace-----------------------------
        719 ms |->       0x78075d8e6c: JNI_OnLoad+0x198 (libkeva.so:0x78075cb000)
        719 ms |->       0x78075d8e6c: JNI_OnLoad+0x198 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        723 ms [+] JNIEnv->NewGlobalRef
        723 ms |- JNIEnv*          : 0x78258cb1c0
        723 ms |- jobject          : 0x91    { java/lang/RuntimeException }
        723 ms |= jobject          : 0x1e12    { java/lang/RuntimeException }
    
        723 ms -----------------------------Backtrace-----------------------------
        723 ms |->       0x78075d8e80: JNI_OnLoad+0x1ac (libkeva.so:0x78075cb000)
        723 ms |->       0x78075d8e80: JNI_OnLoad+0x1ac (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
        728 ms [+] JNIEnv->RegisterNatives
        728 ms |- JNIEnv*          : 0x78258cb1c0
        728 ms |- jclass           : 0x89    { com/bytedance/keva/KevaImpl }
        728 ms |- JNINativeMethod* : 0x78075f2000
        728 ms |:     0x78075d8ee0 - loadRepo(Ljava/lang/String;IZ)J
        728 ms |:     0x78075d9088 - initialize(Ljava/lang/String;)V
        728 ms |:     0x78075d91a0 - delete(Ljava/lang/String;)Z
        728 ms |:     0x78075d9300 - clear(J)V
        728 ms |:     0x78075d93c4 - dump(J)V
        728 ms |:     0x78075d93d4 - checkReportException(J)V
        728 ms |:     0x78075d9488 - storeInt(JLjava/lang/String;JI)J
        728 ms |:     0x78075d9684 - storeBoolean(JLjava/lang/String;JZ)J
        728 ms |:     0x78075d9884 - storeString(JLjava/lang/String;JLjava/lang/String;)J
        728 ms |:     0x78075d9b78 - storeFloat(JLjava/lang/String;JF)J
        728 ms |:     0x78075d9d7c - storeLong(JLjava/lang/String;JJ)J
        728 ms |:     0x78075d9f78 - storeDouble(JLjava/lang/String;JD)J
        728 ms |:     0x78075da17c - storeBytes(JLjava/lang/String;J[BI)J
        728 ms |:     0x78075da40c - storeStringArray(JLjava/lang/String;J[Ljava/lang/String;I)J
        728 ms |:     0x78075da818 - fetchInt(JLjava/lang/String;JI)I
        728 ms |:     0x78075daa5c - fetchBoolean(JLjava/lang/String;JZ)Z
        728 ms |:     0x78075daca0 - fetchLong(JLjava/lang/String;JJ)J
        728 ms |:     0x78075daee4 - fetchFloat(JLjava/lang/String;JF)F
        728 ms |:     0x78075db128 - fetchDouble(JLjava/lang/String;JD)D
        728 ms |:     0x78075db36c - fetchString(JLjava/lang/String;JLjava/lang/String;)Ljava/lang/String;
        728 ms |:     0x78075db65c - fetchBytes(JLjava/lang/String;J[BI)[B
        728 ms |:     0x78075db90c - fetchStringArray(JLjava/lang/String;J[Ljava/lang/String;I)[Ljava/lang/String;
        728 ms |:     0x78075dbdfc - erase(JLjava/lang/String;J)V
        728 ms |:     0x78075dbfe0 - rebuildValueMap(J)V
        728 ms |:     0x78075dc0c4 - contains(JLjava/lang/String;J)Z
        728 ms |:     0x78075dc2bc - eraseUnusedChunk(JJ)V
        728 ms |:     0x78075dc2d0 - protectPortingInterProcess(Ljava/lang/String;ZI)I
        728 ms |- jint             : 27
        728 ms |= jint             : 0
    
        728 ms -----------------------------Backtrace-----------------------------
        728 ms |->       0x78075d8eac: JNI_OnLoad+0x1d8 (libkeva.so:0x78075cb000)
        728 ms |->       0x78075d8eac: JNI_OnLoad+0x1d8 (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
       1099 ms [+] JNIEnv->GetStringUTFChars
       1099 ms |- JNIEnv*          : 0x78258cb1c0
       1099 ms |- jstring          : 0x7fee619098
       1099 ms |- jboolean*        : 0x0
       1099 ms |= char*            : 0x781a6c5640
    
       1099 ms ------------------------------Backtrace------------------------------
       1099 ms |->       0x78075d90cc: libkeva.so!0xe0cc (libkeva.so:0x78075cb000)
       1099 ms |->       0x78075d90cc: libkeva.so!0xe0cc (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
       1122 ms [+] JNIEnv->ReleaseStringUTFChars
       1122 ms |- JNIEnv*          : 0x78258cb1c0
       1122 ms |- jstring          : 0x781a6c5640
       1122 ms |- char*            : 0x781a6c5640
       1122 ms |:     /data/user/0/com.zhiliaoapp.musically/files/keva
    
       1122 ms ------------------------------Backtrace------------------------------
       1122 ms |->       0x78075d916c: libkeva.so!0xe16c (libkeva.so:0x78075cb000)
       1122 ms |->       0x78075d916c: libkeva.so!0xe16c (libkeva.so:0x78075cb000)
    
    
               /* TID 18776 */
       1144 ms [+] JNIEnv->GetStringUTFChars
       1144 ms |- JNIEnv*          : 0x78258cb1c0
       1144 ms |- jstring          : 0x7fee619b88
       1144 ms |- jboolean*        : 0x0
       1144 ms |= char*            : 0x781a66a520
    
       1144 ms ------------------------------Backtrace------------------------------
       1144 ms |->       0x78075d8f3c: libkeva.so!0xdf3c (libkeva.so:0x78075cb000)
       1144 ms |->       0x78075d8f3c: libkeva.so!0xdf3c (libkeva.so:0x78075cb000)
    ...
    
    opened by maceip 5
  •  'runtime' is an invalid keyword argument

    'runtime' is an invalid keyword argument

    Hi, when I use jnitrace, it told me below errors

    frida version:12.2.6 jnitrace version:3.0.7 android version: 4.4.2(kitkat) arm emulator

    jnitrace -l xx.so com.xxx Traceback (most recent call last): File "/usr/local/bin/jnitrace", line 8, in sys.exit(main()) File "/usr/local/lib/python3.6/site-packages/jnitrace/jnitrace.py", line 552, in main script = session.create_script(jscode, runtime="v8") File "/usr/local/lib/python3.6/site-packages/frida/core.py", line 148, in create_script return Script(self._impl.create_script(*args, **kwargs)) TypeError: 'runtime' is an invalid keyword argument for this function

    opened by jiych 5
  • Export the hooking logic as a library

    Export the hooking logic as a library

    Are there any plans to expose the core hooking logic of this library as a NPM library that other Frida scripts can consume?

    I'd love to reuse the code you have already written and a library would probably be more maintainable than copy-pasting functions. :)

    opened by Ayrx 5
  • Error: abort was called

    Error: abort was called

    Hello. I am new in studying your toolkit. Thank you for developing such interesting tool. Together with frida you can do everything you want:)

    I've got an error. The log and error below. The app doesn't starts. Is it because of unity libs? Tried frida 12.8.20 and last 12.9.3. Thanks. Waiting for reply:)

    Also I'd like to suggest to add an argument :)

    -el <regex> - is used to specify library names that should be ignored in the trace. 
                  This can be helpful for reducing the noise in particularly large JNI apps.
                  The option can be supplied multiple times.
                  For example, -el testLib1.so -el testLib2.so would exclude from the results all JNI method names that contained in this libs.
    

    jnitrace -l * -m spawn com.boundless.jawaker (https://play.google.com/store/apps/details?id=com.boundless.jawaker&hl=en) Tracing. Press any key to quit...

         /* TID 7713 */
    124 ms [+] JavaVM->GetEnv
    124 ms |- JavaVM*          : 0x7df82c8cc0
    124 ms |- void**           : 0x7fceef5190
    124 ms |:     0x7df82e8460
    124 ms |- jint             : 65542
    124 ms |= jint             : 0
    
    124 ms ----------------------------------Backtrace----------------------------------
    124 ms |->       0x7dd6112960: JNI_OnLoad+0x3c (libqti_performance.so:0x7dd6111000)
    
    
           /* TID 7713 */
    199 ms [+] JNIEnv->FindClass
    199 ms |- JNIEnv*          : 0x7df82e8460
    199 ms |- char*            : 0x7dd6113764
    199 ms |:     com/qualcomm/qti/Performance
    199 ms |= jclass           : 0x85    { com/qualcomm/qti/Performance }
    
    199 ms ----------------------------------------Backtrace----------------------------------------
    199 ms |->       0x7e7cba0484: jniRegisterNativeMethods+0x40 (libnativehelper.so:0x7e7cb9e000)
    
    
           /* TID 7713 */
    204 ms [+] JNIEnv->RegisterNatives
    204 ms |- JNIEnv*          : 0x7df82e8460
    204 ms |- jclass           : 0x85    { com/qualcomm/qti/Performance }
    204 ms |- JNINativeMethod* : 0x7dd6131008
    204 ms |:     0x7dd61129f0 - native_perf_lock_acq(II[I)I
    204 ms |:     0x7dd6112abc - native_perf_lock_rel(I)I
    204 ms |:     0x7dd6112ad8 - native_perf_hint(ILjava/lang/String;II)I
    204 ms |:     0x7dd6112b90 - native_perf_get_feedback(ILjava/lang/String;)I
    204 ms |:     0x7dd6112c24 - native_perf_io_prefetch_start(ILjava/lang/String;Ljava/lang/String;)I
    204 ms |:     0x7dd6112e58 - native_perf_io_prefetch_stop()I
    204 ms |:     0x7dd6112f80 - native_perf_uxEngine_events(IILjava/lang/String;I)I
    204 ms |:     0x7dd6113154 - native_perf_uxEngine_trigger(I)Ljava/lang/String;
    204 ms |- jint             : 8
    204 ms |= jint             : 0
    
    204 ms ----------------------------------------Backtrace----------------------------------------
    204 ms |->       0x7e7cba04e0: jniRegisterNativeMethods+0x9c (libnativehelper.so:0x7e7cb9e000)
    
    
           /* TID 7713 */
    213 ms [+] JNIEnv->DeleteLocalRef
    213 ms |- JNIEnv*          : 0x7df82e8460
    213 ms |- jobject          : 0x85
    
    213 ms ----------------------------------------Backtrace----------------------------------------
    213 ms |->       0x7e7cba0534: jniRegisterNativeMethods+0xf0 (libnativehelper.so:0x7e7cb9e000)
    
    
           /* TID 7713 */
    432 ms [+] JavaVM->AttachCurrentThread
    432 ms |- JavaVM*          : 0x7df82c8cc0
    432 ms |- void**           : 0x7fceef4ca8
    432 ms |:     0x7df82e8460
    432 ms |- void*            : 0x0
    432 ms |= jint             : 0
    
    432 ms ----------------------------Backtrace----------------------------
    432 ms |->       0x7dd54e1858: JNI_OnLoad+0x1c (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    437 ms [+] JNIEnv->FindClass
    437 ms |- JNIEnv*          : 0x7df82e8460
    437 ms |- char*            : 0x7dd54e1b28
    437 ms |:     com/unity3d/player/NativeLoader
    437 ms |= jclass           : 0x91    { com/unity3d/player/NativeLoader }
    
    437 ms ----------------------------Backtrace----------------------------
    437 ms |->       0x7dd54e1870: JNI_OnLoad+0x34 (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    443 ms [+] JNIEnv->RegisterNatives
    443 ms |- JNIEnv*          : 0x7df82e8460
    443 ms |- jclass           : 0x91    { com/unity3d/player/NativeLoader }
    443 ms |- JNINativeMethod* : 0x7dd54f1fa0
    443 ms |:     0x7dd54e18cc - load(Ljava/lang/String;)Z
    443 ms |:     0x7dd54e1a9c - unload()Z
    443 ms |- jint             : 2
    443 ms |= jint             : 0
    
    443 ms ----------------------------Backtrace----------------------------
    443 ms |->       0x7dd54e1894: JNI_OnLoad+0x58 (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    453 ms [+] JNIEnv->GetStringUTFLength
    453 ms |- JNIEnv*          : 0x7df82e8460
    453 ms |- jstring          : 0x7fceef5668
    453 ms |= jsize            : 66
    
    453 ms -----------------------------Backtrace-----------------------------
    453 ms |->       0x7dd54e1904: libmain.so!0x904 (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    457 ms [+] JNIEnv->GetStringUTFChars
    457 ms |- JNIEnv*          : 0x7df82e8460
    457 ms |- jstring          : 0x7fceef5668
    457 ms |- jboolean*        : 0x0
    457 ms |= char*            : 0x7df823b750
    
    457 ms -----------------------------Backtrace-----------------------------
    457 ms |->       0x7dd54e1930: libmain.so!0x930 (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    462 ms [+] JNIEnv->ReleaseStringUTFChars
    462 ms |- JNIEnv*          : 0x7df82e8460
    462 ms |- jstring          : 0x7df823b750
    462 ms |- char*            : 0x7df823b750
    462 ms |:     /data/app/com.boundless.jawaker-h3IBeFROAGcy8xvbmPRpuw==/lib/arm64
    
    462 ms -----------------------------Backtrace-----------------------------
    462 ms |->       0x7dd54e195c: libmain.so!0x95c (libmain.so:0x7dd54e1000)
    
    
           /* TID 7713 */
    466 ms [+] JNIEnv->GetJavaVM
    466 ms |- JNIEnv*          : 0x7df82e8460
    466 ms |- JavaVM**         : 0x7fceef4a00
    466 ms |:     0x7df82c8cc0
    466 ms |= jint             : 0
    
    466 ms -----------------------------Backtrace-----------------------------
    466 ms |->       0x7dd54e197c: libmain.so!0x97c (libmain.so:0x7dd54e1000)
    

    ERROR: {'type': 'error', 'description': 'Error: abort was called', 'stack': 'Error: abort was called\n at InvocationContext. (node_modules/jnitrace-engine/dist/jni/jni_env_interceptor.js:260:23)', 'fileName': 'node_modules/jnitrace-engine/dist/jni/jni_env_interceptor.js', 'lineNumber': 260, 'columnNumber': 23}

    opened by PeterParker369 4
  • frida.TimedOutError : ~

    frida.TimedOutError : ~

    Hi, I am using frida 14.2.8 & python 3.6. my devices is galaxy s9+, so 64bits of frida-server is running on devices. but when I have try to use, the error occurred .


    jnitrace -l libDrm2.so com.appName ------Error---------------------------------------- Traceback (most recent call last): File "c:\users\des\appdata\local\programs\python\python36\lib\runpy.py", line 193, in _run_module_as_main "main", mod_spec) File "c:\users\des\appdata\local\programs\python\python36\lib\runpy.py", line 85, in run_code exec(code, run_globals) File "C:\Users\des\AppData\Local\Programs\Python\Python36\Scripts\jnitrace.exe_main.py", line 9, in File "c:\users\des\appdata\local\programs\python\python36\lib\site-packages\jnitrace\jnitrace.py", line 565, in main pid = device.spawn([args.target], **aux_kwargs) File "c:\users\des\appdata\local\programs\python\python36\lib\site-packages\frida\core.py", line 26, in wrapper return f(*args, **kwargs) File "c:\users\des\appdata\local\programs\python\python36\lib\site-packages\frida\core.py", line 140, in spawn return self._impl.spawn(program, argv, envp, env, cwd, stdio, aux_options) frida.TimedOutError: unexpectedly timed out while waiting for app to launch

    opened by kokoory 3
  • filter not work

    filter not work

    -i Get -e * -e .* --ignore-env --ignore-vm

    i had try many option, but none of them work, it would print evething called

    frida-server 14.0.8 android 10, pixel QP1A.191005.007.A3

    opened by RonaldinhoL 3
  • jnitrace execution error

    jnitrace execution error

    Hello

    I am trying to execute jnitrace with python3.8 environment

    it shows below

    Traceback (most recent call last): File "C:\Users\a\AppData\Local\Programs\Python\Python38\Scripts\jnitrace-script.py", line 11, in load_entry_point('jnitrace==3.0.0', 'console_scripts', 'jnitrace')() File "C:\Users\a\AppData\Local\Programs\Python\Python38\lib\site-packages\jnitrace-3.0.0-py3.8.egg\jnitrace\jnitrace.py", line 519, in main File "C:\Users\a\AppData\Local\Programs\Python\Python38\lib\site-packages\pkg_resources_init_.py", line 1156, in resource_string return get_provider(package_or_requirement).get_resource_string( File "C:\Users\a\AppData\Local\Programs\Python\Python38\lib\site-packages\pkg_resources_init_.py", line 361, in get_provider import(moduleOrReq) ModuleNotFoundError: No module named 'jnitrace.build'

    can you take this issue?

    opened by mscgo 3
  • unable to attach the target

    unable to attach the target

    Device: Google Nexus 5 Frida-server:frida-server-12.6.13-android-arm frida:12.6.13 frida-tools:2.0.2 Application: just a helloworld

    Stack Trace:

    C:\Users\YueLuo>jnitrace -l * com.yueluo.bkpttest -m attach
    Traceback (most recent call last):
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\runpy.py", line 193, in _run_module_as_main
        "__main__", mod_spec)
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "C:\Users\YueLuo\AppData\Local\Programs\Python\Python37-32\Scripts\jnitrace.exe\__main__.py", line 9, in <module>
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\site-packages\jnitrace\jnitrace.py", line 491, in main
        session = device.attach(device.attach(args.target))
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\site-packages\frida\core.py", line 110, in attach
        return Session(self._impl.attach(self._pid_of(target)))
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\site-packages\frida\core.py", line 128, in _pid_of
        return self.get_process(target).pid
      File "c:\users\yueluo\appdata\local\programs\python\python37-32\lib\site-packages\frida\core.py", line 68, in get_process
        process_name_lc = process_name.lower()
    AttributeError: 'Session' object has no attribute 'lower'
    

    I have fixed this problem by simply change jni.py #487 to

        device = frida.get_usb_device(3)
        pid = device.spawn([args.target])
        
        if args.inject_method == "spawn":
            session = device.attach(pid)
        else:
            session = device.attach(args.target)
    

    the issuse seems like the lastest frida has changed their api, but I know shit about frida, so I'm not sure how to completely fix this problem on all frida versions.

    opened by qgy123 3
  • Bump terser from 5.3.8 to 5.14.2

    Bump terser from 5.3.8 to 5.14.2

    Bumps terser from 5.3.8 to 5.14.2.

    Changelog

    Sourced from terser's changelog.

    v5.14.2

    • Security fix for RegExps that should not be evaluated (regexp DDOS)
    • Source maps improvements (#1211)
    • Performance improvements in long property access evaluation (#1213)

    v5.14.1

    • keep_numbers option added to TypeScript defs (#1208)
    • Fixed parsing of nested template strings (#1204)

    v5.14.0

    • Switched to @​jridgewell/source-map for sourcemap generation (#1190, #1181)
    • Fixed source maps with non-terminated segments (#1106)
    • Enabled typescript types to be imported from the package (#1194)
    • Extra DOM props have been added (#1191)
    • Delete the AST while generating code, as a means to save RAM

    v5.13.1

    • Removed self-assignments (varname=varname) (closes #1081)
    • Separated inlining code (for inlining things into references, or removing IIFEs)
    • Allow multiple identifiers with the same name in var destructuring (eg var { a, a } = x) (#1176)

    v5.13.0

    • All calls to eval() were removed (#1171, #1184)
    • source-map was updated to 0.8.0-beta.0 (#1164)
    • NavigatorUAData was added to domprops to avoid property mangling (#1166)

    v5.12.1

    • Fixed an issue with function definitions inside blocks (#1155)
    • Fixed parens of new in some situations (closes #1159)

    v5.12.0

    • TERSER_DEBUG_DIR environment variable
    • @​copyright comments are now preserved with the comments="some" option (#1153)

    v5.11.0

    • Unicode code point escapes (\u{abcde}) are not emitted inside RegExp literals anymore (#1147)
    • acorn is now a regular dependency

    v5.10.0

    • Massive optimization to max_line_len (#1109)
    • Basic support for import assertions
    • Marked ES2022 Object.hasOwn as a pure function
    • Fix delete optional?.property
    • New CI/CD pipeline with github actions (#1057)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump shell-quote from 1.7.2 to 1.7.3

    Bump shell-quote from 1.7.2 to 1.7.3

    Bumps shell-quote from 1.7.2 to 1.7.3.

    Changelog

    Sourced from shell-quote's changelog.

    1.7.3

    • Fix a security issue where the regex for windows drive letters allowed some shell meta-characters to escape the quoting rules. (CVE-2021-42740)
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump ansi-regex from 4.1.0 to 4.1.1

    Bump ansi-regex from 4.1.0 to 4.1.1

    Bumps ansi-regex from 4.1.0 to 4.1.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • jnitrace blank response

    jnitrace blank response

    c:\adb>jnitrace -l libsc.so com.exampleapp.android Tracing. Press any key to quit... Traced library "libsc.so" loaded from path "/data/app/com.exampleapp.android-1/lib/arm".

    Why i can't grab any information?

    Thanks.

    opened by fhartavi 0
  • Bump minimist from 1.2.5 to 1.2.6

    Bump minimist from 1.2.5 to 1.2.6

    Bumps minimist from 1.2.5 to 1.2.6.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Releases(v3.3.0)
Owner
null
⌨️ A tool that gives you a massive head start when building Compose based apps. It saves you from time-consuming setup and configuration

⌨️ A tool that gives you a massive head start when building Compose based apps. It saves you from time-consuming setup and configuration

theapache64 467 Dec 23, 2022
Just a simple tool to turn on/off DND(Do Not Disturb) automatically when using specified apps.

AutoDND Just a simple tool to turn on/off DND(Do Not Disturb) automatically when using specified apps. Ever feel disturbed by notifications and maybe

null 6 May 24, 2022
An android application which shows usage of various jetpack libraries built by the android team

JetPacker JetPacker is an android application which implements various jetpack libraries created by the android team. FEATURES - (Will be updated as m

Ibrahim 14 Dec 9, 2022
Android Phishing Application.This Project is for Educational purposes only.The Developer of this application is not responsible of any bad usage

Android Phishing Application.This Project is for Educational purposes only.The Developer of this application is not responsible of any bad usage

Aria Shirazi 93 Oct 23, 2022
A sample Android app which showcases advanced usage of Dagger among other open source libraries.

U+2020 A sample Android app which showcases advanced usage of Dagger among other open source libraries. Watch the corresponding talk or view the slide

Jake Wharton 5.7k Dec 27, 2022
Android app with advanced usage of Epoxy library

Epoxy Advanced Best practices and advanced usages (EditText & Forms) of Epoxy library written in accordance with the Modular and Clean Architectures.

Yusuf Gökmen Arısoy 6 Aug 30, 2022
Allows usage of vCard resources with the Android contacts provider

vcard4android vcard4android is an Android library that brings together VCard and Android. It's a framework for parsing and generating VCard resources

bitfire web engineering 7 Dec 15, 2022
Cosmostation wallet apps are non-custodial tendermint-based wallet that supports Cosmos Network.

Cosmostation wallet apps are non-custodial tendermint-based wallet that supports Cosmos Network.

Cosmostation 44 Dec 21, 2022
FDPClient-EDITED - A free mixin-based injection hacked-client for Minecraft using Minecraft Forge based on LiquidBounce

FDPClient A free mixin-based injection hacked-client for Minecraft using Minecra

SuperSkidder 7 Aug 29, 2022
Android developer tool to draw overlay layout for GUI debug

LayoutOverlay Overview Make a overlay window to show transparent shape to compare size with view, margin. Features Overlay window Drag Drag and drop t

7loro 1 Oct 11, 2021
AdpPad is a GUI application to use adb. adb is a command line tool to control android device.

AdbPad AdpPad is a GUI application to use adb. adb is a command line tool to control android device. Demo.mp4 ✨ Feature Observe a connected android de

katz 31 Dec 30, 2022
Android library for Tesla Authentication based on Tesla JSON API (Unofficial)

TeslaAndroidAuth Lightweight Android library for Tesla SSO Authentication based

Octopus Energy 3 Jan 10, 2022
Android app based on clean architecture and using the github API to show open pull requests

This app is based on clean architecture and using the github API to show open pull requests. The code is made considering all design principles and guidelines.

Himanshu Garg 0 May 2, 2022
MaterialDesignColorPalette 4.2 0.0 L3 Java This is a dev tool to visualize the colours of Material design defined on

MaterialDesignColorPalette This is a dev tool to visualize the colours of Material design defined on http://www.google.com/design/spec/style/color.htm

Guillaume Imbert 256 Oct 2, 2022
APK Explorer & Editor, an open-source tool to explore the contents of an installed APK

APK Explorer & Editor, an open-source tool to explore the contents of an installed APK, is strictly made with an aim to inspect an installed APK file.

APK Explorer & Editor 270 Dec 25, 2022
A search tool for GFE names in Kotlin

GFE Search Generator There are currently tens of thousands of known variants of the Human Leukocyte Antigen (HLA) genes, the genes most responsible fo

Carlos Valencia 1 Jan 21, 2022
Bbl - A command line tool to read Holy Bible

bbl A command line tool to read Holy Bible Usage In the command line, type bbl g

Hokuto Ide 12 Oct 26, 2022
Abysl Asset Manager is an easy to use library management tool to index and search game assets

Abysl Asset Manager is an easy to use library management tool to index and search game assets. Features Itch.IO Library Import Hum

null 22 Oct 6, 2022
ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, create architecure fitness functions, and anaysis system dependencies..

ArchGuard backend ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, database, create ar

ArchGuard 446 Dec 20, 2022