Refine hookJniNativeMethods

This commit is contained in:
LoveSy 2024-07-14 22:19:30 +08:00 committed by John Wu
parent 93bcf2cd25
commit f2d057baba

View File

@ -572,29 +572,38 @@ void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods
// Backup existing methods // Backup existing methods
auto total = g_hook->runtime_callbacks->getNativeMethodCount(env, clazz); auto total = g_hook->runtime_callbacks->getNativeMethodCount(env, clazz);
vector<JNINativeMethod> old_methods(total); auto old_methods = std::make_unique_for_overwrite<JNINativeMethod[]>(total);
g_hook->runtime_callbacks->getNativeMethods(env, clazz, old_methods.data(), total); g_hook->runtime_callbacks->getNativeMethods(env, clazz, old_methods.get(), total);
auto new_methods = std::make_unique_for_overwrite<JNINativeMethod[]>(total);
// Replace the method // Replace the method
for (auto i = 0; i < numMethods; ++i) { for (auto i = 0; i < numMethods; ++i) {
auto &method = methods[i]; auto &method = methods[i];
auto res = env->RegisterNatives(clazz, &method, 1); // It's useful to allow nullptr function pointer for restoring hook
if (!method.fnPtr) continue;
// It's normal that the method is not found // It's normal that the method is not found
if (res == JNI_ERR || env->ExceptionCheck()) { if (env->RegisterNatives(clazz, &method, 1) == JNI_ERR ||
auto exception = env->ExceptionOccurred(); env->ExceptionCheck() == JNI_TRUE) {
if (exception) env->DeleteLocalRef(exception); if (auto *exception = env->ExceptionOccurred(); exception) {
env->DeleteLocalRef(exception);
}
env->ExceptionClear(); env->ExceptionClear();
method.fnPtr = nullptr; method.fnPtr = nullptr;
} else { continue;
}
// Find the old function pointer and return to caller // Find the old function pointer and return to caller
for (const auto &old_method : old_methods) { g_hook->runtime_callbacks->getNativeMethods(env, clazz, new_methods.get(), total);
if (strcmp(method.name, old_method.name) == 0 && for (auto j = 0; j < total; ++j) {
strcmp(method.signature, old_method.signature) == 0) { auto &new_method = new_methods[j];
auto &old_method = old_methods[j];
if (new_method.fnPtr == method.fnPtr && old_method.fnPtr != new_method.fnPtr &&
strcmp(new_method.name, method.name) == 0) {
ZLOGD("replace %s#%s%s %p -> %p\n", clz, ZLOGD("replace %s#%s%s %p -> %p\n", clz,
method.name, method.signature, old_method.fnPtr, method.fnPtr); method.name, method.signature, old_method.fnPtr, method.fnPtr);
method.fnPtr = old_method.fnPtr; method.fnPtr = old_method.fnPtr;
break;
} }
} }
} old_methods.swap(new_methods);
} }
} }