java - (JNI) 使用GetMethodID获取Java方法的内存地址

标签 java c++ jvm java-native-interface reverse-engineering

如何获取具有 JNI MethodID 的方法的内存位置?

我想通过使用 JNI 来 Hook 或操作 Java 方法,因为众所周知,JVM 会重新定位此类方法,因此无法使用指向方法的静态指针。

所以我使用 C++ 和 JNI 从 JVM 中获取 MethodID。

MethodID 可以转换为 Integer,它是一个十六进制内存地址。

我已经发现,在MethodID的内存位置,有一个指向HEAP地址的指针。这个堆地址指向一个

“jvm.dll.53A14DE8方法:元数据:MetaspaceObj”

(这就是我的逆向工具“ReClass.NET”所说的)

因此 jvm.dll.xxx Method 获得了一些函数指针,但这些不能是 Method,因为它们由 3 个字节组成(太小)或太大(30 个指令+)。 我想找到的方法只返回 1.0 的 float

这是 ReClass.NET 中的 jvm.dll.xxx 方法: That's the jvm.dll.xxx Method in ReClass.NET

或者是否有其他方法可以在没有 JVMTI 的情况下 native Hook /操作 Java 方法?

最佳答案

您无法像使用 native 方法那样 Hook Java 方法,即直接替换内存中的机器代码。

jmethodID 是对 Java 方法的不透明引用。它在不同的 JVM 中,甚至在同一 JVM 的不同版本中,可能会有不同的实现。例如,随着 Metaspace 的出现,jmethodID 的内部表示在 JDK 7 和 JDK 8 之间发生了变化。

现在,在 HotSpot JVM 中,jmethodID 是指向 Metaspace 中 Method 结构的指针。它不是Java方法的代码,而是代表JVM内部方法的内部结构。

请注意,Java 方法最初根本没有任何机器代码 - 相反,JVM 解释其字节码。由于 JIT 编译、重新编译或去优化,方法的机器代码可能会出现、更改或完全消失。此外,一个方法可能同时具有多个 JIT 编译版本。这就是为什么传统的 Hook 技术不能应用于 Java 方法。此外,一个方法可能会内联到其他 JIT 编译的方法中,在这种情况下 jmethodID 将毫无用处。

但是,有一种用于操作 Java 方法的标准技术 - bytecode instrumentation 。它可以通过标准 API 获得,即 RetransformClassesRedefineClasses JVM TI 的功能。

如果您使用 JNI,则也可以使用 JVM TI 函数。即使没有代理或特殊的 JVM 参数,JVM TI 也可以工作;它可以从任何 JNI 上下文中获得。例如。如何从 JNIEnv* 获取 jvmtiEnv*:

JavaVM* vm;
(*env)->GetJavaVM(env, &vm);

jvmtiEnv* jvmti;
(*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0);

关于java - (JNI) 使用GetMethodID获取Java方法的内存地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59530468/

相关文章:

java - 对话框中的滚动文本不起作用

c++ - 在 C++ 中找到立方根?

c++ - 注意事项 "protected versus private"

java - 我在哪里可以在 Windows PC 上永久设置 Java 堆大小?

java - 如何使用java 10的Application Class-Data Sharing特性?

java - Android - onTouchEvent 仅在第一次工作

Java类的用途非常有限,但不限于一个类。外在还是内在?

java - 以编程方式触发完整的堆栈转储?

Java:抽象泛型类和方法重载顺序

c++ - 为什么我不能使用 makefile 正确包含此文件?