前言

Android应用中JNI代码,是作为本地方法运行的。而大部分情况下,这些JNI方法均需要传递Dalvik虚拟机实例作为第一个参数。例如,你需要用虚拟机实例来创建jstring和其他的Java对象、查找类或成员变量等。大部分情况下,在你用JNI接口从Java层调用Native层中的代码时,你并不需要在native代码中自己初始化一个Dalvik虚拟机实例。但是,如果你在搞逆向或者写exp,你总是需要钻研各种非常规的情况。

最近,我在逆向时需要在native代码中手动创建虚拟机实例用于在JNI接口函数中传递Java对象。在本文中,我将分享我是如何实现这种方法的。

标准方法

在JNI中创建JVM虚拟机实例的官方文档在地址How to Create a JVM Instance in JNI。但是,不幸的是这种方法在Android上面是不能正常运行的,因为jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*)函数不是导出函数,无法直接调用。假如你不熟悉这个方法的话,可以根据它的名字在jni.h文件中查找一下,确认是否是导出函数。在我这里,jni.h文件位于android-sdk/ ndk-bundle/platforms/android-9/arch-x86/usr/include/jni.h。相关代码如下:

如果你尝试编译调用上述截图中函数的代码,你可能会得到下面的错误:

官方文档中介绍的如何创建JVM的方法在这里可以用来理解上述的API函数和它们的选项和参数的用途。如果你想在Android中使用这些方法,你必须显示从so库中调用这些方法。

官方文档中介绍的如何初始化虚拟机的类路径,在此处是非常有用的。其内容如下:

上面的配置,设置当前的类路径为当前目录(.)。如果你想要虚拟机访问系统或者app的类,这是必须设置的。实验表明,将该值设置为一个目录并不会起作用。我尝试将其设置为/data/local/tmp,同时在该目录下放置了一个dex文件、含有dex文件的jar包和apk文件。只有在设置jar包、dex文件或apk文件的全路径时,上述选项才起作用。奇怪的是,当类路径中没有一个合法的文件时,系统类(例如java.lang.String)都不能访问。换句话说,除非类路径中至少有一个文件,否则语句(*env)->FindClass(env, "java.lang.String")返回0,甚至java.lang.String这样定义在框架中的类都无法访问。

为了测试,下面将一个apk文件push到模拟器或真机设备中。

JavaVMOption的使用如下:

你现在可以使用FindClass函数来加载系统或者app的类。此外,如果你需要加载本地库到你的虚拟机中,例如在静态初始化器中加载一个库文件,你可以使用optionString = "-Djava.library.path=/data/local/tmp"这样的设置。这有个样例代码。

UniccUnlock方法

从文件UniccUnlock.cpp中,展示了另外一种创建虚拟机的类似技巧。我不敢说我完全理解了它在做什么,但是其中吸引我的是get_transaction_code部分。下面是它的做的事:

代码看起来像是根据成员值判断当前设备是否已经解锁或者是解锁方法是否成功。反正我是不很确定,不过我也就想抽取其中创建虚拟机的代码而已。

该方法是通过在库文件libnativehelper.so或者libdvm.so中加载创建虚拟机相关的方法。但是,下面几行代码看起来很奇怪:

任何地方都无法找到这几个方法的文档说明。不过,发现这些方法调用的人相当聪明。如果不调用这些方法,你就会得到下面奇怪的错误信息:

除了这几个奇怪的方法,这种方式创建虚拟机对我很好使。但是,我想知道_ZN13JniInvocationC1Ev方法都做了什么,在不同版本间的Android系统中是否可移植。我的直觉告诉我,硬编码的方法名可能会导致在不同的设备或者Android版本间的不兼容性。

Surfaceflinger 方法

最终,我在谷歌的Surfaceflinger服务的源码中找到了:DdmConnection.cpp。

它默认查找了在libdvm.so中的函数JNI_CreateJavaVM。它没有调用方法_ZN13JniInvocation,而是调用了库libandroid_runtime.so中的Java_com_android_internal_util_WithFramework_registerNatives方法。registerNatives方法的内容在此描述了。

同时,感兴趣的是创建虚拟机的选项:

这些选项在这篇文档中详细描述了。根据文档,它仅仅用于调试JVM时使用。

同时,我注意到它JNI的版本是1_4,但是我设置为1_6了,因为谷歌的样例代码中就是这样设置的。下面就是jni.h中支持的版本号:

最后,我使用上面的方式来创建虚拟机,因为它来自谷歌,具有很好的健壮性和兼容性。

最终代码

下面就是最终的创建虚拟机的代码:

下面是其使用方法:

android native java_在Android Native层中创建Java虚拟机实例相关推荐

  1. 在Android Native层中创建Java虚拟机实例

    前言 Android应用中JNI代码,是作为本地方法运行的.而大部分情况下,这些JNI方法均需要传递Dalvik虚拟机实例作为第一个参数.例如,你需要用虚拟机实例来创建jstring和其他的Java对 ...

  2. 【开发环境】Android 命令行中执行 Java 程序 ( IntelliJ IDEA 中创建 Java / Kotlin 工程 | dx 打包 DEX 字节码文件 | dalvikvm 命令 )

    文章目录 前言 一.IntelliJ IDEA 中创建 Java / Kotlin 工程 二.准备 Java 和 Kotlin 代码 三.编译在 PC 上可执行的 Java / Kotlin JAR ...

  3. 如何使用PowerShell在Azure中创建SQL虚拟机

    介绍 ( Introduction ) The first time that you create your VM in Azure manually using the UI is a very ...

  4. 在VScode中创建Java项目

    在VScode中创建Java项目 1. 配置SDK环境 2.在vscode中下载Java插件 之前使用过idea或者其他IDE编写Java已经下载并配置好了sdk,可以直接跳转到第二步.没有配置过sd ...

  5. android sqlite自定义函数,如何在SQLite中创建用户定义的函数?

    SQLite不像Oracle或MS SQL Server那样支持用户定义的功能.对于SQLite,必须使用C / C ++创建一个回调函数,并使用sqlite3_create_function调用将该 ...

  6. android file isdirectory,android – 为什么我不能在Environment.DIRECTORY_PICTURES中创建一个目录?...

    这是我的代码 File selfieLocation = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),"Dail ...

  7. 如何用pycharm调用Java_JPype实现在python中调用JAVA的实例

    一.JPype简述 1.JPype是什么? JPype是一个能够让 python 代码方便地调用 Java 代码的工具,从而克服了 python 在某些领域(如服务器端编程)中的不足. 2.JPype ...

  8. 在Vmware中创建苹果虚拟机

    由于macos的特殊性,按道理说苹果系统只能出现在自家的电脑上,但是Mac系统以其简单易用.设计直观.安全性极高赢得了广大消费者的认可.然而面对动辄上万元的苹果电脑,很多人望而却步,但是又有很多人工作 ...

  9. ndk c调用java_使用NDK将Android转换为C,然后在C中调用Java函数

    因此,我正在重新创建Palm Pilot程序以在Android中运行.我必须继续使用C编写的库,但我正在重写应用程序的UI组件和蓝牙组件以在Android中运行.要在蓝牙连接的另一端初始化设备,我从C ...

最新文章

  1. 这篇 ReentrantLock 看不懂,加我我给你发红包
  2. netty之ObjectSizeEstimator
  3. OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)
  4. uva 10627 - Infinite Race(数论)
  5. (SSO)单点登录原理和总结
  6. sap 分割评估_SAP那些事-实战篇-73-受托加工的几种方案探讨
  7. YARP(Yet Another Reverse Proxy)是使用 .NET 构建的高度可定制的反向代理
  8. 一篇万字长文读懂微软PDB、SourceLink——.net core之nuget 包调试
  9. c# out关键字 vb_c# 关键字:ref 和 out
  10. linux下printf语句执行时间,linux下printf中\n刷新缓冲区的疑问(已解决)
  11. 从viewState说开去
  12. java从文件读入个人信息_Nacos 作为配置中心 读取Properties配置信息
  13. php laravel 中文手册,Laravel 5.6 中文离线手册文档(兼容5.5)(PDF版)
  14. 2021年5月国产数据库大事记-墨天轮
  15. 关于电脑热点打开后手机连接无IP分配解决办法
  16. android dialog遮挡键盘,彻底解决软键盘遮挡DialogFragment
  17. 使用OpenCV和Python进行人脸识别
  18. saber软件安装后怎么打开_Saber2016安装包和安装详细安装步骤
  19. electron使用下载监听接口(will-download)出现不触发done
  20. 如何把程序员从久坐颈椎病中拯救出来?我为程序员做了这个救命APP

热门文章

  1. 微信小程序和微信小程序之间的跳转和传参示例代码附讲解
  2. 记录一次MySQL两千万数据的大表优化解决过程,提供三种解决方案
  3. Spring Boot轻松理解动态注入,删除bean
  4. linux中pipe
  5. 根据listObject中的某个字段排序
  6. BOM和DOM的区别
  7. nexus 4 下 DualBootInstallation 安装 ubuntu touch
  8. 《爱情公寓2》将播 恶搞宣传片大喊“有种别看”
  9. silverlight 无法发布 如何灵活配置IP
  10. 【电路】pmic芯片设计细节