Refine code

This commit is contained in:
Nullptr
2023-02-14 10:14:46 +08:00
parent 8cac525aa9
commit fc9bc3b28f

View File

@@ -112,8 +112,8 @@ hash_map<xstring, tree_map<xstring, tree_map<xstring, void *>>> *jni_method_map;
// Current context // Current context
HookContext *g_ctx; HookContext *g_ctx;
const JNINativeInterface *old_functions; const JNINativeInterface *old_functions = nullptr;
JNINativeInterface *new_functions; JNINativeInterface *new_functions = nullptr;
} // namespace } // namespace
@@ -143,16 +143,8 @@ if (methods[i].name == #method##sv) {
namespace { namespace {
jclass gClassRef;
jmethodID class_getName;
decltype(JNINativeInterface::RegisterNatives) old_RegisterNatives = nullptr;
string get_class_name(JNIEnv *env, jclass clazz) { string get_class_name(JNIEnv *env, jclass clazz) {
if (!gClassRef) { static auto class_getName = env->GetMethodID(env->FindClass("java/lang/Class"), "getName", "()Ljava/lang/String;");
jclass cls = env->FindClass("java/lang/Class");
gClassRef = (jclass) env->NewGlobalRef(cls);
env->DeleteLocalRef(cls);
class_getName = env->GetMethodID(gClassRef, "getName", "()Ljava/lang/String;");
}
auto nameRef = (jstring) env->CallObjectMethod(clazz, class_getName); auto nameRef = (jstring) env->CallObjectMethod(clazz, class_getName);
const char *name = env->GetStringUTFChars(nameRef, nullptr); const char *name = env->GetStringUTFChars(nameRef, nullptr);
string className(name); string className(name);
@@ -178,7 +170,23 @@ DCL_HOOK_FUNC(void, androidSetCreateThreadFunc, void* func) {
do { do {
auto get_created_java_vms = reinterpret_cast<jint (*)(JavaVM **, jsize, jsize *)>( auto get_created_java_vms = reinterpret_cast<jint (*)(JavaVM **, jsize, jsize *)>(
dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs")); dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs"));
if (!get_created_java_vms) break; if (!get_created_java_vms) {
for (auto &map: lsplt::MapInfo::Scan()) {
if (!map.path.ends_with("/libnativehelper.so")) continue;
void *h = dlopen(map.path.data(), RTLD_LAZY);
if (!h) {
LOGW("cannot dlopen libnativehelper.so: %s\n", dlerror());
break;
}
get_created_java_vms = reinterpret_cast<decltype(get_created_java_vms)>(dlsym(h, "JNI_GetCreatedJavaVMs"));
dlclose(h);
break;
}
if (!get_created_java_vms) {
LOGW("JNI_GetCreatedJavaVMs not found\n");
break;
}
}
JavaVM *vm = nullptr; JavaVM *vm = nullptr;
jsize num = 0; jsize num = 0;
jint res = get_created_java_vms(&vm, 1, &num); jint res = get_created_java_vms(&vm, 1, &num);
@@ -186,15 +194,14 @@ DCL_HOOK_FUNC(void, androidSetCreateThreadFunc, void* func) {
JNIEnv *env = nullptr; JNIEnv *env = nullptr;
res = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6); res = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
if (res != JNI_OK || env == nullptr) break; if (res != JNI_OK || env == nullptr) break;
new_functions = new JNINativeInterface(); default_new(new_functions);
memcpy(new_functions, env->functions, sizeof(*new_functions)); memcpy(new_functions, env->functions, sizeof(*new_functions));
old_RegisterNatives = new_functions->RegisterNatives;
new_functions->RegisterNatives = &env_RegisterNatives; new_functions->RegisterNatives = &env_RegisterNatives;
// Replace the function table in JNIEnv to hook RegisterNatives // Replace the function table in JNIEnv to hook RegisterNatives
old_functions = env->functions; old_functions = env->functions;
env->functions = new_functions; env->functions = new_functions;
} while(false); } while (false);
old_androidSetCreateThreadFunc(func); old_androidSetCreateThreadFunc(func);
} }
@@ -279,7 +286,7 @@ void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods
if (hooks.empty()) if (hooks.empty())
return; return;
old_RegisterNatives(env, env->FindClass(clz), hooks.data(), hooks.size()); old_functions->RegisterNatives(env, env->FindClass(clz), hooks.data(), static_cast<int>(hooks.size()));
} }
ZygiskModule::ZygiskModule(int id, void *handle, void *entry) ZygiskModule::ZygiskModule(int id, void *handle, void *entry)
@@ -468,11 +475,11 @@ void HookContext::sanitize_fds() {
if (exempted_fds.empty()) if (exempted_fds.empty())
return nullptr; return nullptr;
jintArray array = env->NewIntArray(off + exempted_fds.size()); jintArray array = env->NewIntArray(static_cast<int>(off + exempted_fds.size()));
if (array == nullptr) if (array == nullptr)
return nullptr; return nullptr;
env->SetIntArrayRegion(array, off, exempted_fds.size(), exempted_fds.data()); env->SetIntArrayRegion(array, off, static_cast<int>(exempted_fds.size()), exempted_fds.data());
for (int fd : exempted_fds) { for (int fd : exempted_fds) {
if (fd >= 0 && fd < MAX_FD_SIZE) { if (fd >= 0 && fd < MAX_FD_SIZE) {
allowed_fds[fd] = true; allowed_fds[fd] = true;
@@ -724,17 +731,14 @@ static bool unhook_functions() {
// Restore JNIEnv // Restore JNIEnv
if (g_ctx->env->functions == new_functions) { if (g_ctx->env->functions == new_functions) {
g_ctx->env->functions = old_functions; g_ctx->env->functions = old_functions;
if (gClassRef) { delete new_functions;
g_ctx->env->DeleteGlobalRef(gClassRef);
gClassRef = nullptr;
class_getName = nullptr;
}
} }
// Unhook JNI methods // Unhook JNI methods
for (const auto &[clz, methods] : *jni_hook_list) { for (const auto &[clz, methods] : *jni_hook_list) {
if (!methods.empty() && old_RegisterNatives( if (!methods.empty() && g_ctx->env->RegisterNatives(
g_ctx->env, g_ctx->env->FindClass(clz.data()), methods.data(), methods.size()) != 0) { g_ctx->env->FindClass(clz.data()), methods.data(),
static_cast<int>(methods.size())) != 0) {
LOGE("Failed to restore JNI hook of class [%s]\n", clz.data()); LOGE("Failed to restore JNI hook of class [%s]\n", clz.data());
success = false; success = false;
} }