JNI FindClass 遇到的 NoClassDefFoundError 错误

在上次的隐私合规工具套装文章中,有人留言了 jvmti 也可以实现方法的监控,这几天尝试写了下 demo,从打印的日志上来看,确实是可行,但 MethodEntry 这个 callback,回调频率也太高了吧,总感觉这玩意性能真的太差了,不如免 root 的 frida 方案(狗头)。

然后再说下使用 MethodEntry 遇到的一个问题,我想将执行的类与方法回调给 java 层,然后 java 层去判断隐私合规是否有调用,但使用 FindClass 时报了如下错误:

java.lang.NoClassDefFoundError: Class not found using the boot class loader

从报错日志看,FindClass 的这个类在系统类加载器找不到,由于 jvmti 是系统类加载器加载的类,如果 FindClass 加载的类是应用类的话,确实是无法找到的,这个是类加载双亲委托的规则。

查了下相关资料,这个问题还是比较接近的,但没有给解决办法:

文章引用了个 google 官方链接,常见问题解答:为什么 FindClass 找不到我的类? 官方的解决办法也是在 JNI_OnLoad 中去做 class 缓存,尝试在 JNI_OnLoad 中 FindClass,然后设置全局引用,NewGlobalRef 与 static 都试过:

kotlin 复制代码
jobject myClass;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
	jclass clazz = env->FindClass("com/codelang/jvmticheck/JvmtiHelper");
    myClass = (env)->NewGlobalRef(clazz);
}
kotlin 复制代码
static jclass myClass;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
	jclass clazz = env->FindClass("com/codelang/jvmticheck/JvmtiHelper");
    myClass = clazz;
}

但在 MethodEntry 中去获取这个 myClass 一直是个 null:

kotlin 复制代码
void MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method) {
    ALOGI("clazz %s",myClass!= nullptr?"not null":"null");
} 

搜到另一位使用 jvmti 的博主遇到的问题,跟我遇到的一样:

然后我又去找了下几个 jvmti 的 demo,没有人这么玩,所以,只能自己硬着头皮继续查资料了。

在 Java 中,系统类加载器是无法加载应用类的,为了解决这个问题,Java 的设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。它是从 JDK1.2 开始引入的,可以通过 Thread 类的 getContextClassLoader() 与 setContextClassLoader(ClassLoader cl) 来获取和设置当前线程的类加载器。

基于这个思路,我想在 jni 中应该也是一样的,尝试在 MethodEntry 中找下有关 context classLoader 的方法,别说,还真有:

那么,有了 context classLoader 之后该如何加载 Class 呢?巧了,正好 Class.forName 支持传入上下文类加载器来加载类:

我们的 jni 代码就可以写成:

显示效果,红色为 java 方法打印的日志:

总结

虽然解决了 boot classLoader 加载应用类的问题,但还有一个问题需要解决,那就是调用 Java 方法之后可能会造成的循环调用问题,这里需要做一些类、方法的排除。

jvmti demo 示例可查看 jvmticheck.cpp

相关推荐
莫名有雪1 小时前
BUUCTF_[网鼎杯 2020 朱雀组]phpweb(反序列化绕过命令)
android
爱写代码的山山4 小时前
虚幻UE5手机安卓Android Studio开发设置2025
android·ue5·虚幻
dal118网工任子仪6 小时前
94,【2】buuctf web [安洵杯 2019]easy_serialize_php
android·前端·php
Kevin Coding9 小时前
Flutter使用Flavor实现切换环境和多渠道打包
android·flutter·ios
yashunan9 小时前
Web_php_unserialize
android·前端·php
taopi202410 小时前
android java系统弹窗的基础模板
android·java·开发语言
志尊宝11 小时前
深入探索 Android 技术:从基础到前沿
android
字节全栈_BjO12 小时前
mysql死锁排查_mysql 死锁问题排查
android·数据库·mysql
恋猫de小郭1 天前
Android Studio 正式版 10 周年回顾,承载 Androider 的峥嵘十年
android·ide·android studio
aaaweiaaaaaa1 天前
php的使用及 phpstorm环境部署
android·web安全·网络安全·php·storm