zoukankan      html  css  js  c++  java
  • 安卓逆向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

  • 相关阅读:
    常用的学生、课程、成绩、教师表的查询
    flutter 自定义TabBar
    Flutter 设置input边框
    Flutter ReorderableListView 可拖拽的列表
    Flutter NotificationListener 监听列表的滚动
    Flutter 使用Tabbar不要Title
    Nestjs 验证对象数组
    postman 发送数组
    JS面向切面编程AOP
    什么是匿名函数、什么是闭包函数?
  • 原文地址:https://www.cnblogs.com/fuhua/p/12709199.html
Copyright © 2011-2022 走看看