Android逆向 JNI静态注册(c++和java交互)

使用Android Studio新建JNi项目

请看NCK大佬的文章:

https://www.cnblogs.com/fuhua/p/12695436.html

先加个textview方便输出调试信息

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/TextViewDebug"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="TextView" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

file

1. JNI普通字段,静态字段互操作.

目标: 获取普通字段的值,设置普通字段的值,获取静态字段的值,设置静态字段的值。

编辑java文件加入静态字段和四个将要写到jni中的方法:
如下:

package com.example.jnidemo2;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("hello");
    }

    private String ReflectionField = "Reflection Field";
    private static String StaticReflectionField = "Static Reflection Field";

    private native String get_reflection_field();

    private native String get_static_reflection_field();

    private native void set_reflection_field(String value);

    private native void set_static_reflection_field(String value);

    @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //首先获取字段
        String debug_string = "获取字段\r\n";
        debug_string += "1:普通字段=>" + get_reflection_field() + "\r\n";
        debug_string += "2:静态字段=>" + get_static_reflection_field() + "\r\n";

//        Toast.makeText(MainActivity.this, "1:普通字段=>" + get_reflection_field(), Toast.LENGTH_LONG).show();
//        Toast.makeText(MainActivity.this, "2:静态字段=>" + get_static_reflection_field(), Toast.LENGTH_LONG).show();

        //设置字段
        String set_field = "Setting Reflection Field";
        set_reflection_field(set_field);
        String set_static_field = "Setting Static Reflection Field";
        set_reflection_field(set_static_field);

        debug_string += "设置字段\r\n";
        debug_string +="3:普通字段=>" + ReflectionField+"\r\n";
        debug_string +="4:静态字段=>" + StaticReflectionField+ "\r\n";

        TextView txtOutputDebug=(TextView) findViewById(R.id.TextViewDebug);
        txtOutputDebug.setText(debug_string );

//        Toast.makeText(this, "3:普通字段=>" + ReflectionField, Toast.LENGTH_LONG).show();
//        Toast.makeText(this, "4:静态字段=>" + StaticReflectionField, Toast.LENGTH_LONG).show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

接下来生成jni

# 因为我这里用的utf-8的字符来保存源文件 所以这里要加上 -encoding UTF-8
# 否则会出现:   错误: 编码GBK的不可映射字符
javah  -encoding UTF-8 -jni -d ../jni com.example.jnidemo2.MainActivity

这是看到已经生成好了头文件
file

头文件内容如下

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

#ifndef _Included_com_example_jnidemo2_MainActivity
#define _Included_com_example_jnidemo2_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    get_reflection_field
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnidemo2_MainActivity_get_1reflection_1field
  (JNIEnv *, jobject);

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    get_static_reflection_field
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnidemo2_MainActivity_get_1static_1reflection_1field
  (JNIEnv *, jobject);

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    set_reflection_field
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_example_jnidemo2_MainActivity_set_1reflection_1field
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    set_static_reflection_field
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_example_jnidemo2_MainActivity_set_1static_1reflection_1field
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

接下来编写cpp文件 实现头文件中的方法

源码如下

//
// Created by asura on 2020/4/24.
//

#include "com_example_jnidemo2_MainActivity.h"

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    get_reflection_field
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnidemo2_MainActivity_get_1reflection_1field(JNIEnv *env, jobject obj) {
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto fieldId = env->GetFieldID(clazz, "ReflectionField", "Ljava/lang/String;");
    auto pJstring = (jstring) env->GetObjectField(obj, fieldId);
    return pJstring;
}

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    get_static_reflection_field
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jnidemo2_MainActivity_get_1static_1reflection_1field(JNIEnv *env, jobject obj) {
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto fieldId = env->GetStaticFieldID(clazz, "StaticReflectionField", "Ljava/lang/String;");
    auto pJstring = (jstring) env->GetStaticObjectField(clazz, fieldId);
    return pJstring;
}

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    set_reflection_field
 * Signature: (Ljava/lang/String;)V
 */
extern "C" JNIEXPORT void JNICALL
Java_com_example_jnidemo2_MainActivity_set_1reflection_1field(JNIEnv *env, jobject obj,jstring str)
{
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto fieldId = env->GetFieldID(clazz, "ReflectionField", "Ljava/lang/String;");
    env->SetObjectField(obj,fieldId,str);
}

/*
 * Class:     com_example_jnidemo2_MainActivity
 * Method:    set_static_reflection_field
 * Signature: (Ljava/lang/String;)V
 */
extern "C" JNIEXPORT void JNICALL
Java_com_example_jnidemo2_MainActivity_set_1static_1reflection_1field(JNIEnv *env, jobject obj, jstring str)
{
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto fieldId = env->GetStaticFieldID(clazz, "StaticReflectionField", "Ljava/lang/String;");
    env->SetStaticObjectField(clazz,fieldId,str);
}

编译后使用模拟器打开

file
成功!!

2. JNI普通方法,静态方法调用。

java代码中增加静态方法和普通方法:

package com.example.jnidemo2;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("hello");
    }

    private String ReflectionField = "Reflection Field";
    private static String StaticReflectionField = "Static Reflection Field";

    private native String get_reflection_field();

    private native String get_static_reflection_field();

    private native void set_reflection_field(String value);

    private native void set_static_reflection_field(String value);

    private native String CallMethod(String watermark);

    private native String CallStaticMethod(String watermark);

    private static String StaticDemoMethod(String str) {
        return "Static Call End" + str + "\r\n";
    }

    private String DemoMethod(String str) {
        return "Call End" + str + "\r\n";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //首先获取字段
        String debug_string = "----------获取字段\r\n";
        debug_string += "1:普通字段=>" + get_reflection_field() + "\r\n";
        debug_string += "2:静态字段=>" + get_static_reflection_field() + "\r\n";

//        Toast.makeText(MainActivity.this, "1:普通字段=>" + get_reflection_field(), Toast.LENGTH_LONG).show();
//        Toast.makeText(MainActivity.this, "2:静态字段=>" + get_static_reflection_field(), Toast.LENGTH_LONG).show();

        //设置字段
        set_reflection_field("Setting Reflection Field");
        set_static_reflection_field("Setting Static Reflection Field");

        debug_string += "---------------设置字段\r\n";
        debug_string += "3:普通字段=>" + ReflectionField + "\r\n";
        debug_string += "4:静态字段=>" + StaticReflectionField + "\r\n";

//        Toast.makeText(this, "3:普通字段=>" + ReflectionField, Toast.LENGTH_LONG).show();
//        Toast.makeText(this, "4:静态字段=>" + StaticReflectionField, Toast.LENGTH_LONG).show();

        debug_string += "----------------jni调用 \r\n";
        debug_string += CallMethod("JNI_MARK ");
        debug_string += CallStaticMethod("JNI_STATIC_MARK");
        TextView txtOutputDebug = (TextView) findViewById(R.id.TextViewDebug);
        txtOutputDebug.setText(debug_string);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

继续生成头文件 并且书写对应的 代码
这里就不放全图了 放个写好的c++ 方法


extern "C" JNIEXPORT jstring JNICALL Java_com_example_jnidemo2_MainActivity_CallMethod
        (JNIEnv *env, jobject jobj, jstring watermark) {
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto method_id = env->GetMethodID(clazz, "DemoMethod",
                                      "(Ljava/lang/String;)Ljava/lang/String;");
    auto method_return = (jstring) env->CallObjectMethod(jobj, method_id, watermark);

    return method_return;
}

extern "C" jstring JNICALL Java_com_example_jnidemo2_MainActivity_CallStaticMethod
        (JNIEnv *env, jobject jobj, jstring watermark) {
    auto clazz = env->FindClass("com/example/jnidemo2/MainActivity");
    auto static_method_id = env->GetStaticMethodID(clazz, "StaticDemoMethod",
                                                   "(Ljava/lang/String;)Ljava/lang/String;");
    auto static_method_return = (jstring) env->CallStaticObjectMethod(clazz, static_method_id,
                                                                      watermark);
    return static_method_return;
}

编译输出:

file

代码详见:

https://github.com/luodaoyi/Android_JNI/tree/master/03_JNI_register2