Merge YukiHookBridge

This commit is contained in:
2022-05-18 03:07:13 +08:00
parent 8909a08962
commit e95f5ff3d8
4 changed files with 101 additions and 74 deletions

View File

@@ -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" +

View File

@@ -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 模式定义

View File

@@ -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 框架的名称

View File

@@ -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) {
/**
* 拦截替换为指定结果