From e95f5ff3d8382758bc3d3d32dc26e4b83cacaa78 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Wed, 18 May 2022 03:07:13 +0800 Subject: [PATCH] Merge YukiHookBridge --- .../sources/CodeSourceFileTemplate.kt | 57 ++-------- .../hook/core/YukiMemberHookCreater.kt | 6 +- .../hook/xposed/YukiHookModuleStatus.kt | 8 +- .../hook/xposed/bridge/YukiHookBridge.kt | 104 +++++++++++++++--- 4 files changed, 101 insertions(+), 74 deletions(-) diff --git a/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/sources/CodeSourceFileTemplate.kt b/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/sources/CodeSourceFileTemplate.kt index 564ab6aa..f7fe62af 100644 --- a/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/sources/CodeSourceFileTemplate.kt +++ b/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/sources/CodeSourceFileTemplate.kt @@ -35,18 +35,6 @@ import java.util.* */ object CodeSourceFileTemplate { - /** 定义 Jvm 方法名 */ - private const val IS_ACTIVE_METHOD_NAME = "__--" - - /** 定义 Jvm 方法名 */ - private const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_" - - /** 定义 Jvm 方法名 */ - private const val GET_XPOSED_VERSION_METHOD_NAME = "--__" - - /** 定义 Jvm 方法名 */ - private const val GET_XPOSED_TAG_METHOD_NAME = "_-_-" - /** * 获得文件注释 * @param entryClassName 入口类名 @@ -148,11 +136,8 @@ object CodeSourceFileTemplate { "\n" + "import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" + "import com.highcapable.yukihookapi.hook.log.loggerE\n" + - "import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" + "import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge\n" + "import de.robv.android.xposed.IXposedHookZygoteInit\n" + - "import de.robv.android.xposed.XC_MethodReplacement\n" + - "import de.robv.android.xposed.XposedHelpers\n" + "import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" + "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + "\n" + @@ -161,9 +146,11 @@ object CodeSourceFileTemplate { "object ${entryClassName}_Impl {\n" + "\n" + " private const val modulePackageName = \"$modulePackageName\"\n" + + "\n" + " private val hookEntry = $entryClassName()\n" + + "\n" + + " private var moduleClassLoader: ClassLoader? = null\n" + " private var isZygoteBinded = false\n" + - " private var lpparam: XC_LoadPackage.LoadPackageParam? = null\n" + "\n" + " private fun callXposedLoaded(\n" + " isZygoteLoaded: Boolean = false,\n" + @@ -184,39 +171,9 @@ object CodeSourceFileTemplate { " YukiHookBridge.callXposedLoaded(isZygoteLoaded, lpparam, resparam)\n" + " }\n" + "\n" + - " private fun hookModuleAppStatus(lpparam: XC_LoadPackage.LoadPackageParam? = this.lpparam, isHookResourcesStatus: Boolean = false) {\n" + - " runCatching {\n" + - " lpparam?.let { this.lpparam = it }\n" + - " if (isHookResourcesStatus.not()) {\n" + - " XposedHelpers.findAndHookMethod(\n" + - " YukiHookModuleStatus::class.java.name,\n" + - " this.lpparam?.classLoader,\n" + - " \"$IS_ACTIVE_METHOD_NAME\",\n" + - " object : XC_MethodReplacement() {\n" + - " override fun replaceHookedMethod(param: MethodHookParam?) = true\n" + - " })\n" + - " XposedHelpers.findAndHookMethod(\n" + - " YukiHookModuleStatus::class.java.name,\n" + - " this.lpparam?.classLoader,\n" + - " \"$GET_XPOSED_TAG_METHOD_NAME\",\n" + - " object : XC_MethodReplacement() {\n" + - " override fun replaceHookedMethod(param: MethodHookParam?) = YukiHookBridge.executorName\n" + - " })\n" + - " XposedHelpers.findAndHookMethod(\n" + - " YukiHookModuleStatus::class.java.name,\n" + - " this.lpparam?.classLoader,\n" + - " \"$GET_XPOSED_VERSION_METHOD_NAME\",\n" + - " object : XC_MethodReplacement() {\n" + - " override fun replaceHookedMethod(param: MethodHookParam?) = YukiHookBridge.executorVersion\n" + - " })\n" + - " } else XposedHelpers.findAndHookMethod(\n" + - " YukiHookModuleStatus::class.java.name,\n" + - " this.lpparam?.classLoader,\n" + - " \"$HAS_RESOURCES_HOOK_METHOD_NAME\",\n" + - " object : XC_MethodReplacement() {\n" + - " override fun replaceHookedMethod(param: MethodHookParam?) = true\n" + - " })\n" + - " }\n" + + " private fun hookModuleAppStatus(classLoader: ClassLoader? = null, isHookResourcesStatus: Boolean = false) {\n" + + " classLoader?.let { moduleClassLoader = it }\n" + + " runCatching { YukiHookBridge.hookModuleAppStatus(moduleClassLoader, isHookResourcesStatus) }\n" + " }\n" + "\n" + " @YukiGenerateApi\n" + @@ -232,7 +189,7 @@ object CodeSourceFileTemplate { " @YukiGenerateApi\n" + " fun callHandleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + " if (lpparam == null) return\n" + - " if (lpparam.packageName == modulePackageName) hookModuleAppStatus(lpparam)\n" + + " if (lpparam.packageName == modulePackageName) hookModuleAppStatus(lpparam.classLoader)\n" + " callXposedLoaded(lpparam = lpparam)\n" + " }\n" + "\n" + diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreater.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreater.kt index 1fe5a0ad..ac0a3045 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreater.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreater.kt @@ -57,13 +57,13 @@ import java.lang.reflect.Member class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackageParam, @PublishedApi internal val hookClass: HookClass) { /** 默认 Hook 回调优先级 */ - val PRIORITY_DEFAULT = 50 + val PRIORITY_DEFAULT = YukiHookBridge.Hooker.PRIORITY_DEFAULT /** 延迟回调 Hook 方法结果 */ - val PRIORITY_LOWEST = -10000 + val PRIORITY_LOWEST = YukiHookBridge.Hooker.PRIORITY_LOWEST /** 更快回调 Hook 方法结果 */ - val PRIORITY_HIGHEST = 10000 + val PRIORITY_HIGHEST = YukiHookBridge.Hooker.PRIORITY_HIGHEST /** * Hook 模式定义 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt index 7afd093f..61dc0326 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt @@ -58,16 +58,16 @@ import de.robv.android.xposed.XposedBridge object YukiHookModuleStatus { /** 定义 Jvm 方法名 */ - private const val IS_ACTIVE_METHOD_NAME = "__--" + internal const val IS_ACTIVE_METHOD_NAME = "__--" /** 定义 Jvm 方法名 */ - private const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_" + internal const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_" /** 定义 Jvm 方法名 */ - private const val GET_XPOSED_VERSION_METHOD_NAME = "--__" + internal const val GET_XPOSED_VERSION_METHOD_NAME = "--__" /** 定义 Jvm 方法名 */ - private const val GET_XPOSED_TAG_METHOD_NAME = "_-_-" + internal const val GET_XPOSED_TAG_METHOD_NAME = "_-_-" /** * 获取当前 Hook 框架的名称 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt index 9d07f814..8c2edd27 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiHookBridge.kt @@ -38,12 +38,16 @@ import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.type.HookEntryType import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper +import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus import com.highcapable.yukihookapi.hook.xposed.bridge.dummy.YukiModuleResources import com.highcapable.yukihookapi.hook.xposed.bridge.dummy.YukiResources +import com.highcapable.yukihookapi.hook.xposed.channel.YukiHookDataChannel import de.robv.android.xposed.* import de.robv.android.xposed.callbacks.XC_InitPackageResources import de.robv.android.xposed.callbacks.XC_LoadPackage +import java.lang.reflect.Field import java.lang.reflect.Member +import java.lang.reflect.Method /** * 这是一个对接 Xposed Hook 入口与 [XposedBridge] 的装载类实现桥 @@ -68,6 +72,9 @@ object YukiHookBridge { /** 当前 [PackageParamWrapper] 实例数组 */ private var packageParamWrappers = HashMap() + /** 已在 [YukiHookDataChannel] 注册的包名数组 */ + private val dataChannelRegisters = HashSet() + /** 当前 [PackageParam] 方法体回调 */ internal var packageParamCallback: (PackageParam.() -> Unit)? = null @@ -105,14 +112,11 @@ object YukiHookBridge { * 获取当前 Hook 框架的名称 * * 从 [XposedBridge] 获取 TAG - * - * - ❗装载代码将自动生成 - 若要调用请使用 [YukiHookAPI.executorName] * @return [String] 无法获取会返回 unknown - [hasXposedBridge] 不存在会返回 invalid */ - @YukiGenerateApi - val executorName + internal val executorName get() = runCatching { - (XposedBridge::class.java.getDeclaredField("TAG").apply { isAccessible = true }.get(null) as? String?) + (Hooker.findField(XposedBridge::class.java, name = "TAG").get(null) as? String?) ?.replace(oldValue = "Bridge", newValue = "")?.replace(oldValue = "-", newValue = "")?.trim() ?: "unknown" }.getOrNull() ?: "invalid" @@ -120,13 +124,9 @@ object YukiHookBridge { * 获取当前 Hook 框架的版本 * * 获取 [XposedBridge.getXposedVersion] - * - * - ❗装载代码将自动生成 - 若要调用请使用 [YukiHookAPI.executorVersion] * @return [Int] 无法获取会返回 -1 */ - @YukiGenerateApi - val executorVersion - get() = runCatching { XposedBridge.getXposedVersion() }.getOrNull() ?: -1 + internal val executorVersion get() = runCatching { XposedBridge.getXposedVersion() }.getOrNull() ?: -1 /** * 是否存在 [XposedBridge] @@ -196,6 +196,37 @@ object YukiHookBridge { dynamicModuleAppResources?.let { moduleAppResources = it } } + /** + * Hook 模块自身激活状态和 Resources Hook 支持状态 + * + * - ❗装载代码将自动生成 - 你不应该手动使用此方法装载 Xposed 模块事件 + * @param classLoader 模块的 [ClassLoader] + * @param isHookResourcesStatus 是否 Hook Resources 支持状态 + */ + @YukiGenerateApi + fun hookModuleAppStatus(classLoader: ClassLoader?, isHookResourcesStatus: Boolean = false) { + Hooker.findClass(classLoader, YukiHookModuleStatus::class.java).also { statusClass -> + if (isHookResourcesStatus.not()) { + Hooker.hookMethod(Hooker.findMethod(statusClass, YukiHookModuleStatus.IS_ACTIVE_METHOD_NAME), + object : Hooker.YukiMemberReplacement() { + override fun replaceHookedMember(wrapper: HookParamWrapper) = true + }) + Hooker.hookMethod(Hooker.findMethod(statusClass, YukiHookModuleStatus.GET_XPOSED_TAG_METHOD_NAME), + object : Hooker.YukiMemberReplacement() { + override fun replaceHookedMember(wrapper: HookParamWrapper) = executorName + }) + Hooker.hookMethod(Hooker.findMethod(statusClass, YukiHookModuleStatus.GET_XPOSED_VERSION_METHOD_NAME), + object : Hooker.YukiMemberReplacement() { + override fun replaceHookedMember(wrapper: HookParamWrapper) = executorVersion + }) + } else + Hooker.hookMethod(Hooker.findMethod(statusClass, YukiHookModuleStatus.HAS_RESOURCES_HOOK_METHOD_NAME), + object : Hooker.YukiMemberReplacement() { + override fun replaceHookedMember(wrapper: HookParamWrapper) = true + }) + } + } + /** * 标识 Xposed API 装载完成 * @@ -251,7 +282,7 @@ object YukiHookBridge { assignWrapper(HookEntryType.RESOURCES, resparam.packageName, appResources = YukiResources.createFromXResources(resparam.res)) else null else -> null - }?.let { YukiHookAPI.onXposedLoaded(it) } + }?.also { YukiHookAPI.onXposedLoaded(it) } } /** @@ -261,6 +292,45 @@ object YukiHookBridge { */ internal object Hooker { + /** 默认 Hook 回调优先级 */ + internal const val PRIORITY_DEFAULT = 50 + + /** 延迟回调 Hook 方法结果 */ + internal const val PRIORITY_LOWEST = -10000 + + /** 更快回调 Hook 方法结果 */ + internal const val PRIORITY_HIGHEST = 10000 + + /** + * 查找 [Class] + * @param classLoader 当前 [ClassLoader] + * @param baseClass 当前类 + * @return [Field] + * @throws IllegalStateException 如果 [ClassLoader] 为空 + */ + internal fun findClass(classLoader: ClassLoader?, baseClass: Class<*>) = + classLoader?.loadClass(baseClass.name) ?: error("ClassLoader is null") + + /** + * 查找变量 + * @param baseClass 所在类 + * @param name 变量名称 + * @return [Field] + * @throws NoSuchFieldError 如果找不到变量 + */ + internal fun findField(baseClass: Class<*>, name: String) = baseClass.getDeclaredField(name).apply { isAccessible = true } + + /** + * 查找方法 + * @param baseClass 所在类 + * @param name 方法名称 + * @param paramTypes 方法参数 + * @return [Method] + * @throws NoSuchMethodError 如果找不到方法 + */ + internal fun findMethod(baseClass: Class<*>, name: String, vararg paramTypes: Class<*>) = + baseClass.getDeclaredMethod(name, *paramTypes).apply { isAccessible = true } + /** * Hook 方法 * @@ -338,28 +408,28 @@ object YukiHookBridge { /** * Hook 方法回调接口 - * @param priority Hook 优先级 + * @param priority Hook 优先级 - 默认 [PRIORITY_DEFAULT] */ - internal abstract class YukiMemberHook(override val priority: Int) : YukiHookCallback(priority) { + internal abstract class YukiMemberHook(override val priority: Int = PRIORITY_DEFAULT) : YukiHookCallback(priority) { /** * 在方法执行之前注入 * @param wrapper 包装实例 */ - abstract fun beforeHookedMember(wrapper: HookParamWrapper) + open fun beforeHookedMember(wrapper: HookParamWrapper) {} /** * 在方法执行之后注入 * @param wrapper 包装实例 */ - abstract fun afterHookedMember(wrapper: HookParamWrapper) + open fun afterHookedMember(wrapper: HookParamWrapper) {} } /** * Hook 替换方法回调接口 - * @param priority Hook 优先级 + * @param priority Hook 优先级- 默认 [PRIORITY_DEFAULT] */ - internal abstract class YukiMemberReplacement(override val priority: Int) : YukiHookCallback(priority) { + internal abstract class YukiMemberReplacement(override val priority: Int = PRIORITY_DEFAULT) : YukiHookCallback(priority) { /** * 拦截替换为指定结果