当使用 XposedBridge.hookMethod 这个 api对java函数进行hook时:
public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook callback) {if (!(hookMethod instanceof Executable)) {throw new IllegalArgumentException("Only methods and constructors can be hooked: " + hookMethod);} else if (Modifier.isAbstract(hookMethod.getModifiers())) {throw new IllegalArgumentException("Cannot hook abstract methods: " + hookMethod);} else if (hookMethod.getDeclaringClass().getClassLoader() == XposedBridge.class.getClassLoader()) {throw new IllegalArgumentException("Do not allow hooking inner methods");} else if (hookMethod.getDeclaringClass() == Method.class && hookMethod.getName().equals("invoke")) {throw new IllegalArgumentException("Cannot hook Method.invoke");}if (callback == null) {throw new IllegalArgumentException("callback should not be null!");}if (!HookBridge.hookMethod(false, (Executable) hookMethod, LSPosedBridge.NativeHooker.class, callback.priority, callback)) {log("Failed to hook " + hookMethod);return null;}return callback.new Unhook(hookMethod);
}
会调用 HookBridge.hookMethod 这个内部api,实现在native层:
public class HookBridge {public static native boolean hookMethod(boolean useModernApi, Executable hookMethod, Class<?> hooker, int priority, Object callback);public static native boolean unhookMethod(boolean useModernApi, Executable hookMethod, Object callback);public static native boolean deoptimizeMethod(Executable method);public static native <T> T allocateObject(Class<T> clazz) throws InstantiationException;public static native Object invokeOriginalMethod(Executable method, Object thisObject, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;public static native <T> Object invokeSpecialMethod(Executable method, char[] shorty, Class<T> clazz, Object thisObject, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;@FastNativepublic static native boolean instanceOf(Object obj, Class<?> clazz);@FastNativepublic static native boolean setTrusted(Object cookie);public static native Object[][] callbackSnapshot(Class<?> hooker_callback, Executable method);
}
native层方法定义如下:
LSP_DEF_NATIVE_METHOD(jboolean, HookBridge, hookMethod, jboolean useModernApi, jobject hookMethod,jclass hooker, jint priority, jobject callback) {bool newHook = false;
#ifndef NDEBUGstruct finally {std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();bool &newHook;~finally() {auto finish = std::chrono::steady_clock::now();if (newHook) {LOGV("New hook took {}us",std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count());}}} finally {.newHook = newHook};
#endifauto target = env->FromReflectedMethod(hookMethod); //ArtMethod 结构体HookItem * hook_item = nullptr;hooked_methods.lazy_emplace_l(target, [&hook_item](auto &it) {hook_item = it.second.get();}, [&hook_item, &target, &newHook](const auto &ctor) {auto ptr = std::make_unique<HookItem>();hook_item = ptr.get();ctor(target, std::move(ptr));newHook = true;});if (newHook) {auto init = env->GetMethodID(hooker, "<init>", "(Ljava/lang/reflect/Executable;)V");auto callback_method = env->ToReflectedMethod(hooker, env->GetMethodID(hooker, "callback", //LSPosedBridge.NativeHooker"([Ljava/lang/Object;)Ljava/lang/Object;"),false);auto hooker_object = env->NewObject(hooker, init, hookMethod); //新建 NativeHooker 对象,传入 目标hookMethodhook_item->SetBackup(lsplant::Hook(env, hookMethod, hooker_object, callback_method)); //传入的目标method 和 NativeHooker对象env->DeleteLocalRef(hooker_object);}jobject backup = hook_item->GetBackup();if (!backup) return JNI_FALSE;JNIMonitor monitor(env, backup);if (useModernApi) {if (before_method_field == nullptr) {auto callback_class = JNI_GetObjectClass(env, callback);callback_ctor = JNI_GetMethodID(env, callback_class, "<init>", "(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)V");before_method_field = JNI_GetFieldID(env, callback_class, &#