安卓逆向5.Android Studio JNI静态注册(C++和Java互操作)

 1)JNI普通字段,静态字段互操作,获取普通字段的值,设置普通字段的值,获取静态字段的值,设置静态字段的值。

1.根据上一篇帖子使用Android Studio新建一个名字叫TestStaticReflection的项目,并在UI界面上添加一个TextView控件,ID为txtOutputDebug,用于输出调试信息。
上一篇帖子:安卓逆向4.Android Studio JNI静态注册(一个简单的JNI静态注册流程)
https://www.cnblogs.com/fuhua/p/12695436.html

 

 

2.在MainActivity创建一个普通字段,一个静态字段和四个方法。分别用来获取普通字段的值,设置普通字段的值,获取静态字段的值,设置静态字段的值。如图

 

3.使用命令:javah -jni com.crackme.teststaticreflection.MainActivity生成MainActivity所对应的jni头文件,如图

 

4.创建TestStaticReflection.cpp文件,并实现头文件中的四个导出函数。cpp文件代码如下
#include "com_crackme_teststaticreflection_MainActivity.h"

//获取普通字段的值
JNIEXPORT jstring JNICALL Java_com_crackme_teststaticreflection_MainActivity_GetTestField(JNIEnv * env, jobject obj)
{
     //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类
     jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity");
     //在MainActivity下寻找字段名为TestField,且字段类型为Ljava/lang/String的字段ID
     jfieldID _jfieldID=env->GetFieldID(_jClass,"TestField","Ljava/lang/String;");
     //通过字段ID获取字段的值
     jobject jstr=env->GetObjectField(obj,_jfieldID);
     //返回字段的值
     return (jstring)jstr;
}

//获取静态字段的值
JNIEXPORT jstring JNICALL Java_com_crackme_teststaticreflection_MainActivity_GetTestStaticField(JNIEnv * env, jobject obj)
{
     //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类
     jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity");
     //在MainActivity下寻找字段名为TestStaticField,且字段类型为Ljava/lang/String的字段ID
     jfieldID _jfieldID=env->GetStaticFieldID(_jClass,"TestStaticField","Ljava/lang/String;");
     //通过字段ID获取字段的值
     jobject jstr=env->GetStaticObjectField(_jClass,_jfieldID);
     //返回字段的值
     return (jstring)jstr;
}

//设置普通字段的值
JNIEXPORT void JNICALL Java_com_crackme_teststaticreflection_MainActivity_SetTestField(JNIEnv * env, jobject obj)
{
     //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类
     jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity");
      //在MainActivity下寻找字段名为TestField,且字段类型为Ljava/lang/String的字段ID
     jfieldID _jfieldID=env->GetFieldID(_jClass,"TestField","Ljava/lang/String;");
     //调用SetObjectField方法重新给字段赋值
     env->SetObjectField(obj,_jfieldID,env->NewStringUTF("我是重新设置的普通字段的值"));
}

//设置静态字段的值
JNIEXPORT void JNICALL Java_com_crackme_teststaticreflection_MainActivity_SetTestStaticField(JNIEnv * env, jobject obj)
{
//通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类
     jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity");
     //在MainActivity下寻找字段名为TestStaticField,且字段类型为Ljava/lang/String的字段ID
     jfieldID _jfieldID=env->GetStaticFieldID(_jClass,"TestStaticField","Ljava/lang/String;");
     //通过字段ID获取字段的值
     env->SetStaticObjectField(_jClass,_jfieldID,env->NewStringUTF("我是重新设置的静态字段的值"));
}

 

5.使用ndk-build命令生成libTestStaticReflection.so

 

 

6.修改MainActivity类中的OnCreate方法代码如下:
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView txtOutputDebug=(TextView) findViewById(R.id.txtOutputDebug);
        String strOutPut="------------------获取字段-----------------\r\n";
        strOutPut+="TestField:"+GetTestField()+"\r\n";
        strOutPut+="TestStaticField:"+GetTestStaticField()+"\r\n";
        strOutPut+="------------------设置字段-----------------\r\n";
        SetTestField();
        SetTestStaticField();
        strOutPut+="TestField:"+TestField+"\r\n";
        strOutPut+="TestStaticField:"+TestStaticField+"\r\n";
        txtOutputDebug.setText(strOutPut);

    }

 

7.模拟器测试运行

 

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

 

8.在MainActivity中新增如下代码并在onCreate方法中进行调用

 

9.此时MainActivity完整代码如下
package com.crackme.teststaticreflection;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import java.util.concurrent.Executor;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("TestStaticReflection");
    }
    //普通字段
    public String TestField="我是普通字段";
    //静态字段
    public static String TestStaticField="我是静态字段";
    //获取普通字段的值
    public native String GetTestField();
    //获取静态字段的值
    public native String GetTestStaticField();
    //设置普通字段的值
    public native void SetTestField();
    //设置静态字段的值
    public native void SetTestStaticField();

    //将strOutPut设置为全局变量
    static String strOutPut=null;
    //将会从native层调用的普通方法
    public void TestMethod()
    {
        strOutPut+="\n------------------方法调用测试-----------------\n";
        strOutPut+="普通方法被调用\n";
    }
    //将会从native层调用的静态方法
    public static  void TestStaticMethod(String arg)
    {
        strOutPut+="\n------------------方法调用测试-----------------\n";
        strOutPut+="静态方法被调用"+" 参数:"+arg+"\n";
    }
    //调用普通方法
    public native String CallTestMethod();
    //调用静态方法
    public native void CallTestStaticMethod(String arg);


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView txtOutputDebug=(TextView) findViewById(R.id.txtOutputDebug);
        strOutPut="------------------获取字段-----------------\n";
        strOutPut+="TestField:"+GetTestField()+"\n";
        strOutPut+="TestStaticField:"+GetTestStaticField()+"\n";
        strOutPut+="\n------------------设置字段-----------------\n";
        SetTestField();
        SetTestStaticField();
        strOutPut+="TestField:"+TestField+"\n";
        strOutPut+="TestStaticField:"+TestStaticField+"\n";

        CallTestMethod();
        CallTestStaticMethod("我是参数");

        txtOutputDebug.setText(strOutPut);
    }
}

 

10.在cpp文件中实现新增的两个native方法

11.此时cpp文件完整代码如下
#include "com_crackme_teststaticreflection_MainActivity.h"
//获取普通字段的值 JNIEXPORT jstring JNICALL Java_com_crackme_teststaticreflection_MainActivity_GetTestField(JNIEnv * env, jobject obj) { //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类 jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity"); //在MainActivity下寻找字段名为TestField,且字段类型为Ljava/lang/String的字段ID jfieldID _jfieldID=env->GetFieldID(_jClass,"TestField","Ljava/lang/String;"); //通过字段ID获取字段的值 jobject jstr=env->GetObjectField(obj,_jfieldID); //返回字段的值 return (jstring)jstr; } //获取静态字段的值 JNIEXPORT jstring JNICALL Java_com_crackme_teststaticreflection_MainActivity_GetTestStaticField(JNIEnv * env, jobject obj) { //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类 jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity"); //在MainActivity下寻找字段名为TestStaticField,且字段类型为Ljava/lang/String的字段ID jfieldID _jfieldID=env->GetStaticFieldID(_jClass,"TestStaticField","Ljava/lang/String;"); //通过字段ID获取字段的值 jobject jstr=env->GetStaticObjectField(_jClass,_jfieldID); //返回字段的值 return (jstring)jstr; } //设置普通字段的值 JNIEXPORT void JNICALL Java_com_crackme_teststaticreflection_MainActivity_SetTestField(JNIEnv * env, jobject obj) { //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类 jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity"); //在MainActivity下寻找字段名为TestField,且字段类型为Ljava/lang/String的字段ID jfieldID _jfieldID=env->GetFieldID(_jClass,"TestField","Ljava/lang/String;"); //调用SetObjectField方法重新给字段赋值 env->SetObjectField(obj,_jfieldID,env->NewStringUTF("我是重新设置的普通字段的值")); } //设置静态字段的值 JNIEXPORT void JNICALL Java_com_crackme_teststaticreflection_MainActivity_SetTestStaticField(JNIEnv * env, jobject obj) { //通过完全限定的名称com/crackme/teststaticreflection/MainActivity寻找到MainActivity这个类 jclass _jClass=env->FindClass("com/crackme/teststaticreflection/MainActivity"); //在MainActivity下寻找字段名为TestStaticField,且字段类型为Ljava/lang/String的字段ID jfieldID _jfieldID=env->GetStaticFieldID(_jClass,"TestStaticField","Ljava/lang/String;"); //通过字段ID获取字段的值 env->SetStaticObjectField(_jClass,_jfieldID,env->NewStringUTF("我是重新设置的静态字段的值")); } //调用java层普通方法 JNIEXPORT jstring JNICALL Java_com_crackme_teststaticreflection_MainActivity_CallTestMethod(JNIEnv * env, jobject obj) { jclass _jClass= env->FindClass("com/crackme/teststaticreflection/MainActivity"); jmethodID _jmethodID= env->GetMethodID(_jClass,"TestMethod","()V"); env->CallVoidMethod(obj,_jmethodID); return env->NewStringUTF("hahah"); } //调用java层静态方法 JNIEXPORT void JNICALL Java_com_crackme_teststaticreflection_MainActivity_CallTestStaticMethod(JNIEnv * env, jobject obj, jstring jstr) { jclass _jClass= env->FindClass("com/crackme/teststaticreflection/MainActivity"); jmethodID _jmethodID= env->GetStaticMethodID(_jClass,"TestStaticMethod","(Ljava/lang/String;)V"); env->CallStaticVoidMethod(_jClass,_jmethodID,jstr); }

 

12.运行测试是否调用成功

 

项目源文件下载:

链接:https://pan.baidu.com/s/1g_ct5DyDOi_6qY0E7c-aZA
提取码:zx2u

posted @ 2020-04-15 22:42  凉游浅笔深画眉  阅读(582)  评论(0编辑  收藏  举报