Android APP リバース - JNI 開発

JNI の紹介

JNI は、ネイティブ言語のプログラミング インターフェイス (Java Native Interface) です。JVM で実行される Java コードは、C、C++、またはアセンブリで記述されたネイティブ コードと相互運用できます。

JNIの存在意義:

  • [開発] システムの基本機能] ava は直接呼び出すことができず、C および C++ プログラミングの助けを借りてのみ実現できます。

  • [開発] 比較的高いパフォーマンスが要求される一部の関数については、C および C++ を使用する方が効率的です。

  • [クローラー] コア アルゴリズムに C および C++ を使用して、リバース クラックの難易度を高めます。


JNI のインストール

NDK をインストールすると、Android Studio ベースの JNI を開発できます。

  • 新しい Android プロジェクトを作成する場合、C を使用してコア コードを開発します。【ネイティブC++テンプレート】

  • ネイティブ C++ テンプレート (空のテンプレート + C 基本設定)


静的登録

JNI と組み合わせて Java で C コードを呼び出したい場合。

  • Java クラスを作成するには、特定のロジックを実装する必要はなく、クラスとメソッドを定義するだけです。

package com.nb.fucker;

// com.nb.fucker.encryptUtils
public class encryptUtils {
    // 加载C文件
    static {
        System.loadLibrary("encrypt");
    }
    public static native int add(int  v1, int v2);

    public static native String sign(String origin);
}
  • C/C++ ファイルを作成し、コードを記述して特定の機能を実装します。

  • ヘッダー ファイル (クラスへのパス) を自動的に生成するコマンド

javac -h ./ encryptUtils.java
  • C言語関数名、命名規則 → Java_パッケージ名_クラス名_メソッド名

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_nb_fucker_encryptUtils */

#ifndef _Included_com_nb_fucker_encryptUtils
#define _Included_com_nb_fucker_encryptUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_nb_fucker_encryptUtils
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint

JNICALL Java_com_nb_fucker_encryptUtils_add(JNIEnv *env, jclass obj, jint v1, jint v2) {
    // 写 C 语言代码 + env是JNI对象 + obj当前类 encryptUtils + v1、v2 是参数
    return v1 + v2;
}

/*
 * Class:     com_nb_fucker_encryptUtils
 * Method:    sign
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring

JNICALL Java_com_nb_fucker_encryptUtils_sign(JNIEnv *env, jclass obj, jstring origin) {
    char data[] = "wupeiqi";

    return (*env)->NewStringUTF(env, data); // 将 c中的字符串 转换成 java中的String

}

#ifdef __cplusplus
}
#endif
#endif
  • CMakeLists.txt を構成する

add_library( # Sets the name of the library.
        encrypt

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        encrypt.c)

target_link_libraries( # Specifies the target library.
        fucker encrypt
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

移行

int v1 = encryptUtils.add(1, 2);
String v2 = encryptUtils.sign("xxxxx");

価値

他人のサイトのsoファイルを逆にする場合は、ファイル名の対応を知っておきましょう。


動的登録

動的登録の手順:

  • Java クラス:


public class DynamicUtils {
    static {
        System.loadLibrary("dynamic");
    }
    public static native int add(int v1, int v2);
}
  • C の関数:

JNI_OnLoad
    -- 动态找到add
jint plus(JNIEnv *env, jclass obj, jint v1, jint v2) {
    return v1 + v2;
}

static JNINativeMethod gMethod[] = {
       //Java函数  ---->  C语言中的函数
        {"add", "(II)I", (void *) plus},
};

/*
 * System.loadLibrary("包")时会自动调用
 */

JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;

    // 在Java虚拟机中获取 env
    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

    // 找到 Java 中的类,env=JNI
    jclass clazz = (*env)->FindClass(env, "com/nb/fucker/DynamicUtils");

    // 将类中的方法注册到JNI中
    int res = (*env)->RegisterNatives(env, clazz, gMethod, 1);
    if(res < 0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}
  • CMakeLists.txt を構成する

add_library( # Sets the name of the library.
        dynamic

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        dynamic.c)

target_link_libraries( # Specifies the target library.
        fucker dynamic

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})
  • 移行

int v3 = DynamicUtils.add(3, 4);
Log.e("DynamicUtils.add===>", String.valueOf(v3));

JNI は Java でメンバーを呼び出します

JNI で Java のメンバーを呼び出す場合は、次を使用します。

  • 例 1: (静的メソッド: int+int->int)

// Java
package com.nb.dk;

class Query{
    public static int getData(int v1, int v2) {
        return v1 + v2;
    }
}
// JNI
jclass cls = (*env) -> FindClass(env, "com/nb/dk/Query");
jmethodID mid = (*env) -> GetStaticMethodID(env, cls, "getData", "(II)I");
// "(II)I": 
//        JNI中 I 对应 Java中的 int 数据类型;
//        (II)-->代表参数是2个 int;
//        括号外的 I ---> 代表返回值是 int;
int res = (*env) -> CallStaticIntMethod(env, cls, mid, 1, 2);
  • 例 2: (静的メソッド: int+int->String)

// Java
package com.nb.dk;

class Query{
    public static String getData(int v1, int v2) {
        return v1 + v2;
    }
}
// JNI
jclass cls = (*env) -> FindClass(env, "com/nb/dk/Query");
jmethodID mid = (*env) -> GetStaticMethodID(env, cls, "getData", "(II)Ljava/lang/String;");
// "(II)Ljava/lang/String;": 
//        JNI中 I 对应 Java中的 int 数据类型;
//        (II)-->代表参数是2个 int;
//        括号外的 Ljava/lang/String; ---> 代表返回值是 String;
int res = (*env) -> CallStaticIntMethod(env, cls, mid, 1, 2);
  • 例 3: (静的メソッド: int+String->String)

// Java
package com.nb.dk;

class Query{
    public static String getData(String v1, int v2) {
        return String.valueOf(v1 + v2);
    }
}
// JNI, C语言
jclass cls = (*env) -> FindClass(env, "com/nb/dk/Query");
jmethodID mid = (*env) -> GetStaticMethodID(env, cls, "getData", "(Ljava/lang/String;I)Ljava/lang/String;");
// (Ljava/lang/String;I)Ljava/lang/String;": 
//        JNI中 I 对应 Java中的 int 数据类型;
//        (Ljava/lang/String;I)-->代表参数是第一个数据类型是String; 第二个数据类型是int;
//        括号外的 Ljava/lang/String; ---> 代表返回值是 String;
jstring arg1 = (*env)->NewStringUTF(env, "哈哈哈");    // 将C语言的字符串转化成 java的字符串
int res = (*env) -> CallStaticIntMethod(env, cls, mid, arg1, 2);
  • 例 4: (動的メソッド: int+String->String)

// Java
package com.nb.dk;

class Query{
    // 构造方法
    public Query(int arg1, int arg2, String arg3) {
    
    }
    // getData
    public static String getData(String v1, int v2) {
        return String.valueOf(v1 + v2);
    }
}
// JNI
jclass cls = (*env) -> FindClass(env, "com/nb/dk/Query");
// "<init>" 找类中的构造方法
// v --> void
jmethodID init = (*env) -> GetStaticMethodID(env, cls, "<init>", "(IILjava/lang/String;)v");

// 创建对象
jobject cls_object = (*env)->NewObject(env, cls, init, 1, 2, (*env)->NewStringUTF(env, "哈哈哈"));

jmethodID mid = (*env) -> GetMethodID(env, cls, "getData", "(II)Ljava/lang/String;");
jstring arg1 = (*env)->NewStringUTF(env, "字符串啊");
int res = (*env) -> CallStaticIntMethod(env, cls_object, mid, arg1, 2);

おすすめ

転載: blog.csdn.net/m0_57126939/article/details/128853276