INIT与init array
1.so执行JNI_OnLoad之前,还会执行俩个构造函数init 和init array
在so加载时候有这个过程:
.init -> .init array -> JNI_Onload -> java_com_xxx
在脱壳的过程中会在一些系统级的.so中下断点比如:fopen,fget,dvmdexfileopen等等
而 .init 以及 .init_array 一般会作为壳的入口地方,那我们索性叫它外壳级的.so文件
这里归纳为三类:
应用级别的:java_com_XXX;
外壳级别的:JNI_Onload,.init,.init_array;
系统级别的:fopen,fget,dvmdexfileopen;
对于在应用级别的和系统级别的就不说了比较简单容易理解,这里也是在实现篇中会重点说的,看到上面的.so的加载执行过程我们知道如果说反调试放在外壳级别的.so文件的话我们就会遇程序在应用级核心函数一下断点就退出的尴尬,事实上多数的反调试会放在这,那么过反调试就必须要在这些地方下断点,下面会重点的说如何在.init_array和JNI_Onload处理下断点。
2.so加固 so字符串加密等等,一般会把相关代码放到这里
3.init的使用
exter “C” void _init(){
//函数名必须是_init
……
}
在 JNI 中,INIT
通常指的是调用 Java 类的构造函数以创建 Java 对象。以下是关于 INIT
的详细说明及其使用示例。
使用 INIT
的步骤
- 查找 Java 类:
- 使用
FindClass
查找要实例化的 Java 类。
- 使用
- 获取构造函数 ID:
- 使用
GetMethodID
获取构造函数的 ID。
- 使用
- 创建构造函数参数:
- 创建构造函数所需的参数(如字符串、整数等)。
- 调用构造函数:
- 使用
NewObject
调用构造函数,创建 Java 对象。
- 使用
- 释放局部引用:
- 释放局部引用以避免内存泄漏。
示例代码
以下是一个完整的示例,展示了如何在 JNI 中使用 INIT
创建和初始化一个 Java 对象。
Java 类示例
假设我们有一个 Java 类 Person
,它有一个构造函数和一个方法:
package com.example;
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
JNI 代码示例
接下来,我们编写 JNI 代码来创建 Person
对象并调用其方法:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_createPerson(JNIEnv *env, jobject obj) {
// 1. 查找 Java 类
jclass personClass = env->FindClass("com/example/Person");
if (personClass == nullptr) {
return; // 类未找到,返回
}
// 2. 获取构造函数 ID
jmethodID constructor = env->GetMethodID(personClass, "<init>", "(Ljava/lang/String;)V");
if (constructor == nullptr) {
return; // 构造函数未找到,返回
}
// 3. 创建构造函数参数
jstring na