Android逆向 JNI静态注册(c++和java交互)
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>
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
头文件内容如下
/* 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);
}
编译后使用模拟器打开
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;
}
编译输出:
代码详见:
https://github.com/luodaoyi/Android_JNI/tree/master/03_JNI_register2