mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Merge YukiHookBridge
This commit is contained in:
@@ -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" +
|
||||
|
@@ -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 模式定义
|
||||
|
@@ -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 框架的名称
|
||||
|
@@ -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<String, PackageParamWrapper>()
|
||||
|
||||
/** 已在 [YukiHookDataChannel] 注册的包名数组 */
|
||||
private val dataChannelRegisters = HashSet<String>()
|
||||
|
||||
/** 当前 [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) {
|
||||
|
||||
/**
|
||||
* 拦截替换为指定结果
|
||||
|
Reference in New Issue
Block a user