INIT与init_array

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 的步骤

  1. 查找 Java 类
    • 使用 FindClass 查找要实例化的 Java 类。
  2. 获取构造函数 ID
    • 使用 GetMethodID 获取构造函数的 ID。
  3. 创建构造函数参数
    • 创建构造函数所需的参数(如字符串、整数等)。
  4. 调用构造函数
    • 使用 NewObject 调用构造函数,创建 Java 对象。
  5. 释放局部引用
    • 释放局部引用以避免内存泄漏。

示例代码

以下是一个完整的示例,展示了如何在 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. 获取构造函数 IDjmethodID constructor = env->GetMethodID(personClass, "<init>", "(Ljava/lang/String;)V");if (constructor == nullptr) {return; // 构造函数未找到,返回}// 3. 创建构造函数参数jstring name = env->NewStringUTF("John Doe");// 4. 创建 Java 对象jobject personObject = env->NewObject(personClass, constructor, name);if (personObject == nullptr) {env->DeleteLocalRef(name); // 释放局部引用return; // 对象创建失败,返回}// 5. 获取 getName 方法 IDjmethodID getNameMethod = env->GetMethodID(personClass, "getName", "()Ljava/lang/String;");if (getNameMethod == nullptr) {env->DeleteLocalRef(personObject);env->DeleteLocalRef(name);return; // 方法未找到,返回}// 6. 调用 getName 方法jstring result = (jstring)env->CallObjectMethod(personObject, getNameMethod);if (result != nullptr) {const char *resultStr = env->GetStringUTFChars(result, nullptr);// 这里可以使用 resultStr,例如打印或处理env->ReleaseStringUTFChars(result, resultStr);env->DeleteLocalRef(result); // 释放局部引用}// 7. 释放局部引用env->DeleteLocalRef(personObject);env->DeleteLocalRef(name);
}

代码解释

  1. 查找 Java 类:使用 FindClass 查找 Person 类。
  2. 获取构造函数 ID:使用 GetMethodID 获取构造函数的 ID。
  3. 创建构造函数参数:创建一个字符串参数 name
  4. 调用构造函数:使用 NewObject 创建 Person 对象。
  5. 获取方法 ID:获取 getName 方法的 ID。
  6. 调用方法:使用 CallObjectMethod 调用 getName 方法,获取返回值。
  7. 释放局部引用:在适当的地方释放局部引用,以避免内存泄漏。

总结

  • 使用 INIT 可以在 JNI 中创建 Java 对象。
  • 通过 NewObject 调用构造函数,并使用 GetMethodIDCallObjectMethod 调用对象的方法。
  • 确保在适当的地方释放局部引用,以避免内存泄漏。

4.initarray的使用

在这里插入图片描述

在 JNI 中,INITARRAY 通常指的是初始化 Java 对象数组的过程。使用 NewObjectArray 创建一个 Java 对象数组,并使用 SetObjectArrayElement 方法将对象添加到数组中。以下是关于 INITARRAY 的详细说明及其使用示例。

使用 INITARRAY 的步骤

  1. 查找 Java 类
    • 使用 FindClass 查找要存储在数组中的 Java 类。
  2. 创建对象数组
    • 使用 NewObjectArray 创建一个指定长度的对象数组。
  3. 获取构造函数 ID
    • 获取要创建的 Java 对象的构造函数 ID。
  4. 初始化数组元素
    • 使用循环创建每个元素,并使用 SetObjectArrayElement 将其添加到数组中。
  5. 释放局部引用
    • 释放局部引用以避免内存泄漏。

示例代码

以下是一个完整的示例,展示了如何在 JNI 中使用 INITARRAY 创建和初始化一个 Java 对象数组。

Java 类示例

首先,假设我们有一个 Java 类 MyClass,它有一个构造函数:

package com.example;public class MyClass {private String name;public MyClass(String name) {this.name = name;}public String getName() {return name;}
}

JNI 代码示例

接下来,我们编写 JNI 代码来创建和初始化 MyClass 对象数组:

#include <jni.h>
#include <string>extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_example_yourapp_MainActivity_createMyClassArray(JNIEnv *env, jobject obj) {// 1. 查找 Java 类jclass myClass = env->FindClass("com/example/MyClass");if (myClass == nullptr) {return nullptr; // 类未找到,返回 nullptr}// 2. 获取构造函数 IDjmethodID constructor = env->GetMethodID(myClass, "<init>", "(Ljava/lang/String;)V");if (constructor == nullptr) {return nullptr; // 构造函数未找到,返回 nullptr}// 3. 创建对象数组jobjectArray myArray = env->NewObjectArray(5, myClass, nullptr);if (myArray == nullptr) {return nullptr; // 数组创建失败,返回 nullptr}// 4. 初始化数组元素for (int i = 0; i < 5; i++) {// 创建构造函数参数std::string name = "Object " + std::to_string(i);jstring jName = env->NewStringUTF(name.c_str());// 5. 创建 Java 对象jobject myObject = env->NewObject(myClass, constructor, jName);if (myObject == nullptr) {env->DeleteLocalRef(jName); // 释放局部引用return nullptr; // 对象创建失败,返回 nullptr}// 6. 将对象添加到数组env->SetObjectArrayElement(myArray, i, myObject);// 7. 释放局部引用env->DeleteLocalRef(myObject);env->DeleteLocalRef(jName);}// 8. 返回对象数组return myArray;
}

代码解释

  1. 查找 Java 类:使用 FindClass 查找 MyClass
  2. 获取构造函数 ID:使用 GetMethodID 获取构造函数的 ID。
  3. 创建对象数组:使用 NewObjectArray 创建一个长度为 5 的对象数组。
  4. 初始化数组元素:使用循环创建每个 MyClass 对象,将其添加到数组中。
    • 创建字符串参数并调用构造函数。
    • 使用 SetObjectArrayElement 将创建的对象添加到数组中。
  5. 释放局部引用:在每次循环中释放局部引用,以避免内存泄漏。
  6. 返回对象数组:最后返回创建的对象数组。

总结

  • 使用 INITARRAY 可以在 JNI 中创建和初始化 Java 对象数组。
  • 通过 NewObjectArray 创建数组,并使用 SetObjectArrayElement 方法将元素添加到数组中。
  • 确保在适当的地方释放局部引用,以避免内存泄漏。

这种方式可以有效地在 C++ 和 Java 之间传递对象数组,方便在 Android 应用中实现复杂的数据结构。

5.onCreateNative化

在 Android 应用中,onCreate 方法是 Activity 生命周期中的一个重要部分。将 onCreate 方法的部分逻辑移到 JNI 中,可以通过调用本地方法来实现。以下是如何将 onCreate 方法的逻辑“本地化”的步骤和示例。

步骤

  1. 定义本地方法:在 Java 类中声明一个本地方法。
  2. 实现本地方法:在 C++ 中实现该本地方法。
  3. onCreate 中调用本地方法:在 onCreate 方法中调用本地方法。

示例代码

1. Java 类定义

首先,在你的 Activity 中定义一个本地方法:

package com.example.yourapp;import android.app.Activity;
import android.os.Bundle;public class MainActivity extends Activity {static {System.loadLibrary("native-lib"); // 加载本地库}// 声明本地方法public native void onCreateNative();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 调用本地方法onCreateNative();}
}

2. C++ 实现

接下来,在 C++ 中实现 onCreateNative 方法:

#include <jni.h>
#include <string>
#include <android/log.h>#define LOG_TAG "NativeLib"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)extern "C" JNIEXPORT void JNICALL
Java_com_example_yourapp_MainActivity_onCreateNative(JNIEnv *env, jobject obj) {// 在这里实现本地逻辑LOGI("onCreateNative called");// 你可以在这里执行其他初始化操作// 例如,初始化 C++ 对象、设置 JNI 环境等
}

代码解释

  1. Java 类
    • MainActivity 中声明了一个本地方法 onCreateNative
    • onCreate 方法中调用 onCreateNative,以便在 Activity 创建时执行本地逻辑。
  2. C++ 实现
    • 使用 JNIEXPORTJNICALL 定义本地方法。
    • 使用 __android_log_print 打印日志,确认本地方法被调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147953.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

GUI编程19:贪吃蛇小游戏及GUI总结

视频链接&#xff1a;21、贪吃蛇之界面绘制_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1DJ411B75F?p21&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.游戏中用的的图片素材 1.贪吃蛇游戏的主启动类StartGame&#xff1b; package com.yundait.snake;import j…

缓存的思考与总结

缓存的思考与总结 什么是缓存缓存命中率数据一致性旁路模式 Cache aside双写模式直写模式 write through异步写 Write Behind 旁路和双写 案例 新技术或中间的引入&#xff0c;一定是解决了亟待解决的问题或是显著提升了系统性能&#xff0c;并且这种改变所带来的增幅&#xff…

【开源服务框架】Dubbo

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Java面试中开源服务框架Dubbo会涉及到的知识点 &#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一…

GAMES101(15节)

Irradiance辐射度量学 辐射度量学在渲染领域&#xff0c;可以帮助理解基于物理的光照模型 radiant energy辐射能量Q&#xff0c;累计总能量&#xff08;单位J joule焦耳&#xff09;&#xff0c;就像太阳能板&#xff0c;光照时间越长接收能量越多&#xff0c;收到的能量总和…

jetlinks物联网平台学习2(加盐算法登陆)

加盐算法 加盐算法加密验证密码是否正确 对于传统的MD5加密&#xff0c;比更传统的直接保存账号密码稍微安全一点。 md5加密是一种hash算法 比如对于123456来说&#xff0c;md5算法结果一定是e10adc3949ba59abbe56e057f20f883e 这个结果是固定的。于是有的人准备一张彩虹表 预先…

ECharts基础使用方法 ---vue

1.安装依赖文件 仔细看项目" README.md " 描述&#xff0c;确定用什么安装 npm npm install echarts --save //官网推荐使用 pnpm pnpm install echarts --save 其他也是 在项目根目录&#xff0c;打开当前目录命令控制栏&#xff0c;输入以上命令并运行 安装成功后…

第十三章:使用html和css做一个静态登录网页练习

我们在使用浏览器 浏览某些网站的时候 有可能会遇到登录这种网页,这种网页是怎么制作出来的呢? 下面 我就来分享一个简单的 登录页 实现方案! 登录页面的作用: 身份验证:登录页面的核心作用就是验证用户身份。用户输入用户名(或邮箱、手机号)和密码,系统通过验证来判断…

[数据结构]无头单向非循环链表的实现与应用

文章目录 一、引言二、线性表的基本概念1、线性表是什么2、链表与顺序表的区别3、无头单向非循环链表 三、无头单向非循环链表的实现1、结构体定义2、初始化3、销毁4、显示5、增删查改 四、分析无头单向非循环链表1、存储方式2、优点3、缺点 五、总结1、练习题2、源代码 一、引…

尚品汇-秒杀商品定时任务存入缓存、Redis发布订阅实现状态位(五十一)

目录&#xff1a; &#xff08;1&#xff09;秒杀业务分析 &#xff08;2&#xff09;搭建秒杀模块 &#xff08;3&#xff09;秒杀商品导入缓存 &#xff08;4&#xff09;redis发布与订阅实现 &#xff08;1&#xff09;秒杀业务分析 需求分析 所谓“秒杀”&#xff0…

百度智能云API调用

植物识别API import base64 import urllib import requestsAPI_KEY = "你的图像识别API_KEY" SECRET_KEY = "你的图像识别SECRET_KEY"def main():url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/plant?access_token=" + get_acc…

12、等保安全通用要求

数据来源&#xff1a;12.等保安全通用要求_哔哩哔哩_bilibili 基本要求

docker启动mysql未读取my.cnf配置文件问题

描述 在做mysql主从复制配置两台mysql时&#xff0c;从节点的my.cnf配置为&#xff1a; [mysqld] datadir /usr/local/mysql/slave1/data character-set-server utf8 lower-case-table-names 1 # 主从复制-从机配置# 从服务器唯一 ID server-id 2 # 启用中继日志 relay-l…

thop计算模型复杂度(params,flops)

thop安装 -pip install thop在线安装失败 -离线安装 github网址&#xff1a; pytorch-OpCounter:Count the MACs / FLOPs of your PyTorch model. - GitCode python setup.py install 测试&#xff1a; from options import config as c import os os.environ["CUD…

【高分系列卫星简介——高分三号卫星(GF-3)】

高分三号卫星&#xff08;GF-3&#xff09; 高分三号&#xff08;GF-3&#xff09;是我国首颗高分辨率、C频段、多极化合成孔径雷达&#xff08;SAR&#xff09;卫星&#xff0c;由中国空间技术研究院北京空间飞行器总部设计部研制&#xff0c;并于2016年8月10日成功发射。该卫…

vue实现扫雷代码复制即可用,vue2和vue3都可适用

效果预览 代码实现 <template><div id"app"><div class"mine-sweeper"><div class"board" v-for"row in board" :key"row-${row.index}"><divclass"cell":class"{ no-clickable…

Vue3:mitt实现组件通信

目录 一.性质 1.轻量级 2.单例 3.异步 4.事件绑定与解绑 二.作用 1.组件间通信 2.解耦 3.状态管理 4.事件的集中处理 三.使用 1.安装mitt 2.引入mitt&#xff1b;调用mitt&#xff1b;暴露mitt 3.组件1 4.组件2 四.代码 1.组件1 2.组件2 五.效果 一.性质 1…

qt-C++笔记之Q_DECLARE_METATYPE和qRegisterMetaType

qt-C笔记之Q_DECLARE_METATYPE和qRegisterMetaType code review! 文章目录 qt-C笔记之Q_DECLARE_METATYPE和qRegisterMetaType一.Q_DECLARE_METATYPE使用方法应用场景 二.为什么需要注册类型&#xff1f;三.使用 Q_DECLARE_METATYPE 处理自定义类型的简短示例3.1.自定义类型定…

ElasticSearch-2-核心语法集群高可用实战-Week2-3

ES批量操作 1.批量获取文档数据 这里多个文档是指&#xff0c;批量操作多个文档&#xff0c;搜索查询文档将在之后的章节讲解 批量获取文档数据是通过_mget的API来实现的 (1)在URL中不指定index和type 请求方式&#xff1a;GET 请求地址&#xff1a;_mget 功能说明 &#…

(C++23) expected 基础使用

文章目录 ⭐前言⭐expected&#x1f39b;️基础使用&#x1f39b;️单子操作 (Monadic operations)&#x1f39a;️and_then & or_else&#x1f39a;️transform & transform_error ⭐END&#x1f31f;跋&#x1f31f;交流方式 ⭐前言 在 C17 中&#xff0c;提出了 op…