mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 17:55:24 +08:00
Added new hookAllMembers function in YukiMemberHookCreater and remove old way and fix some bug
This commit is contained in:
@@ -152,16 +152,26 @@ inner class MemberHookCreater internal constructor(private val priority: Int, in
|
||||
|
||||
> Hook 核心功能实现类,查找和处理需要 Hook 的方法、构造方法。
|
||||
|
||||
#### member [field]
|
||||
|
||||
```kotlin
|
||||
var member: Member?
|
||||
```
|
||||
#### ~~member [field]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.93` `移除`
|
||||
|
||||
请转移到 `members`
|
||||
|
||||
#### members [method]
|
||||
|
||||
```kotlin
|
||||
fun members(vararg member: Member?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.93` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 手动指定要 Hook 的方法、构造方法。
|
||||
@@ -176,72 +186,64 @@ var member: Member?
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
member = instanceClass.getMethod("test", StringType)
|
||||
members(instanceClass.getMethod("test", StringType))
|
||||
beforeHook {}
|
||||
afterHook {}
|
||||
}
|
||||
```
|
||||
|
||||
#### allMethods [method]
|
||||
|
||||
```kotlin
|
||||
fun allMethods(name: String)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找并 Hook 当前 `Class` 中指定 `name` 的全部方法。
|
||||
|
||||
**功能示例**
|
||||
|
||||
使用此方法可将当前类的全部同名方法进行批量 Hook。
|
||||
|
||||
!> 无法准确处理每个方法的 `param`,建议使用 `method` 对每个方法单独 Hook。
|
||||
同样地,你也可以传入一组方法同时进行 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
allMethods(name = "test")
|
||||
members(
|
||||
instanceClass.getMethod("test1", StringType),
|
||||
instanceClass.getMethod("test2", StringType),
|
||||
instanceClass.getMethod("test3", StringType)
|
||||
)
|
||||
beforeHook {}
|
||||
afterHook {}
|
||||
}
|
||||
```
|
||||
|
||||
#### allConstructors [method]
|
||||
|
||||
```kotlin
|
||||
fun allConstructors()
|
||||
```
|
||||
#### ~~allMethods [method]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
`v1.0.93` `作废`
|
||||
|
||||
> 查找并 Hook 当前 `Class` 中的全部构造方法。
|
||||
请使用 `method { name = /** name */ }.all()` 来取代它
|
||||
|
||||
**功能示例**
|
||||
#### ~~allConstructors [method]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
使用此方法可将当前类的全部构造方法进行批量 Hook。
|
||||
**变更记录**
|
||||
|
||||
!> 无法准确处理每个构造方法的 `param`,建议使用 `constructor` 对每个构造方法单独 Hook。
|
||||
`v1.0` `添加`
|
||||
|
||||
> 示例如下
|
||||
`v1.0.93` `作废`
|
||||
|
||||
请使用 `constructor().all()` 来取代它
|
||||
|
||||
#### allMembers [method]
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
allConstructors()
|
||||
beforeHook {}
|
||||
afterHook {}
|
||||
}
|
||||
fun allMembers()
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.93` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 查找并 Hook `hookClass` 中的全部方法、构造方法。
|
||||
|
||||
!> 警告:无法准确处理每个方法的返回值和 `param`,建议使用 `method` or `constructor` 对每个方法单独 Hook。
|
||||
|
||||
#### method [method]
|
||||
|
||||
```kotlin
|
||||
@@ -618,7 +620,7 @@ fun onHooked(result: (Member) -> Unit): Result
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 `member` Hook 成功的回调方法。
|
||||
> 监听 `members` Hook 成功的回调方法。
|
||||
|
||||
在首次 Hook 成功后回调。
|
||||
|
||||
@@ -636,9 +638,9 @@ fun onAlreadyHooked(result: (Member) -> Unit): Result
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 `member` 重复 Hook 的回调方法。
|
||||
> 监听 `members` 重复 Hook 的回调方法。
|
||||
|
||||
!> 同一个 `hookClass` 中的同一个 `member` 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。
|
||||
!> 同一个 `hookClass` 中的同一个 `members` 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。
|
||||
|
||||
##### onNoSuchMemberFailure [method]
|
||||
|
||||
@@ -652,7 +654,7 @@ fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 `member` 不存在发生错误的回调方法。
|
||||
> 监听 `members` 不存在发生错误的回调方法。
|
||||
|
||||
##### onConductFailure [method]
|
||||
|
||||
@@ -708,7 +710,7 @@ fun ignoredNoSuchMemberFailure(): Result
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 忽略 `member` 不存在发生的错误。
|
||||
> 忽略 `members` 不存在发生的错误。
|
||||
|
||||
##### ignoredConductFailure [method]
|
||||
|
||||
|
@@ -36,6 +36,8 @@ import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.FieldFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.MethodFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.factory.allConstructors
|
||||
import com.highcapable.yukihookapi.hook.factory.allMethods
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerI
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||
@@ -70,12 +72,6 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/** 更快回调 Hook 方法结果 */
|
||||
val PRIORITY_HIGHEST = YukiHookPriority.PRIORITY_HIGHEST
|
||||
|
||||
/**
|
||||
* Hook 模式定义
|
||||
*/
|
||||
@PublishedApi
|
||||
internal enum class HookMemberMode { HOOK_ALL_METHODS, HOOK_ALL_CONSTRUCTORS, HOOK_CONVENTIONAL }
|
||||
|
||||
/** [hookClass] 找不到时出现的错误回调 */
|
||||
private var onHookClassNotFoundFailureCallback: ((Throwable) -> Unit)? = null
|
||||
|
||||
@@ -183,16 +179,13 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/** [replaceAny]、[replaceUnit] 回调 */
|
||||
private var replaceHookCallback: (HookParam.() -> Any?)? = null
|
||||
|
||||
/** [replaceTo]、[replaceToTrue]、[replaceToFalse]、[intercept] 的值 */
|
||||
private var replaceHookResult: Any? = null
|
||||
|
||||
/** Hook 成功时回调 */
|
||||
private var onHookedCallback: ((Member) -> Unit)? = null
|
||||
|
||||
/** 重复 Hook 时回调 */
|
||||
private var onAlreadyHookedCallback: ((Member) -> Unit)? = null
|
||||
|
||||
/** 找不到 [member] 出现错误回调 */
|
||||
/** 找不到 [members] 出现错误回调 */
|
||||
private var onNoSuchMemberFailureCallback: ((Throwable) -> Unit)? = null
|
||||
|
||||
/** Hook 过程中出现错误回调 */
|
||||
@@ -207,9 +200,6 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/** 是否为替换 Hook 模式 */
|
||||
private var isReplaceHookMode = false
|
||||
|
||||
/** 是否为仅替换 Hook 结果模式 */
|
||||
private var isReplaceHookOnlyResultMode = false
|
||||
|
||||
/** 是否对当前 [MemberHookCreater] 禁止执行 Hook 操作 */
|
||||
@PublishedApi
|
||||
internal var isDisableMemberRunHook = false
|
||||
@@ -218,77 +208,84 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
@PublishedApi
|
||||
internal var findingThrowable: Throwable? = null
|
||||
|
||||
/** 标识是否已经设置了要 Hook 的 [member] */
|
||||
/** 标识是否已经设置了要 Hook 的 [members] */
|
||||
@PublishedApi
|
||||
internal var isHookMemberSetup = false
|
||||
|
||||
/** Hook 当前模式类型 */
|
||||
@PublishedApi
|
||||
internal var hookMemberMode = HookMemberMode.HOOK_CONVENTIONAL
|
||||
|
||||
/** 当前的查找实例 */
|
||||
@PublishedApi
|
||||
internal var finder: BaseFinder? = null
|
||||
|
||||
/** 全部方法的名称 */
|
||||
private var allMethodsName = ""
|
||||
/** 当前被 Hook 的方法、构造方法实例数组 */
|
||||
private val memberUnhooks = HashSet<YukiMemberHook.Unhook>()
|
||||
|
||||
/** 当前被 Hook 的方法、构造方法实例 */
|
||||
private var memberUnhook: YukiMemberHook.Unhook? = null
|
||||
/** 当前需要 Hook 的方法、构造方法 */
|
||||
internal val members = HashSet<Member>()
|
||||
|
||||
/**
|
||||
* 手动指定要 Hook 的方法、构造方法
|
||||
*
|
||||
* 你可以调用 [instanceClass] 来手动查询要 Hook 的方法
|
||||
*
|
||||
* - ❗不建议使用此方法设置目标需要 Hook 的 [Member] 对象 - 你可以使用 [method] 或 [constructor] 方法
|
||||
*
|
||||
* - ❗在同一个 [injectMember] 中你只能使用一次 [members]、[allMembers]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
* @param member 要指定的 [Member] 或 [Member] 数组
|
||||
* @throws IllegalStateException 如果 [member] 参数为空
|
||||
*/
|
||||
var member: Member? = null
|
||||
fun members(vararg member: Member?) {
|
||||
if (member.isEmpty()) error("Custom Hooking Members is empty")
|
||||
members.clear()
|
||||
member.forEach { it?.also { members.add(it) } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并 Hook [hookClass] 中指定 [name] 的全部方法
|
||||
*
|
||||
* 在同一个 [injectMember] 中
|
||||
* - ❗此方法已弃用 - 在之后的版本中将直接被删除
|
||||
*
|
||||
* 你只能使用一次 [allMethods]、[allConstructors]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
*
|
||||
* - ❗警告:无法准确处理每个方法的返回值和 param - 建议使用 [method] 对每个方法单独 Hook
|
||||
*
|
||||
* - ❗如果 [hookClass] 中没有方法可能会发生错误
|
||||
* - ❗请现在转移到 [MethodFinder]
|
||||
* @param name 方法名称
|
||||
* @return [ArrayList]<[MethodFinder.Result.Instance]>
|
||||
*/
|
||||
fun allMethods(name: String) {
|
||||
allMethodsName = name
|
||||
hookMemberMode = HookMemberMode.HOOK_ALL_METHODS
|
||||
isHookMemberSetup = true
|
||||
}
|
||||
@Deprecated("请使用新方式来实现 Hook 所有方法", ReplaceWith(expression = "method { this.name = name }.all()"))
|
||||
fun allMethods(name: String) = method { this.name = name }.all()
|
||||
|
||||
/**
|
||||
* 查找并 Hook [hookClass] 中的全部构造方法
|
||||
*
|
||||
* 在同一个 [injectMember] 中
|
||||
* - ❗此方法已弃用 - 在之后的版本中将直接被删除
|
||||
*
|
||||
* 你只能使用一次 [allMethods]、[allConstructors]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
*
|
||||
* - ❗警告:无法准确处理每个构造方法的 param - 建议使用 [constructor] 对每个构造方法单独 Hook
|
||||
*
|
||||
* - ❗如果 [hookClass] 中没有构造方法可能会发生错误
|
||||
* - ❗请现在转移到 [ConstructorFinder]
|
||||
* @return [ArrayList]<[ConstructorFinder.Result.Instance]>
|
||||
*/
|
||||
fun allConstructors() {
|
||||
allMethodsName = "<init>"
|
||||
hookMemberMode = HookMemberMode.HOOK_ALL_CONSTRUCTORS
|
||||
@Deprecated("请使用新方式来实现 Hook 所有构造方法", ReplaceWith(expression = "constructor().all()"))
|
||||
fun allConstructors() = constructor().all()
|
||||
|
||||
/**
|
||||
* 查找并 Hook [hookClass] 中的全部方法、构造方法
|
||||
*
|
||||
* - ❗在同一个 [injectMember] 中你只能使用一次 [members]、[allMembers]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
*
|
||||
* - ❗警告:无法准确处理每个方法的返回值和 param - 建议使用 [method] or [constructor] 对每个方法单独 Hook
|
||||
*
|
||||
* - ❗如果 [hookClass] 中没有方法可能会发生错误
|
||||
*/
|
||||
fun allMembers() {
|
||||
members.clear()
|
||||
hookClass.instance?.allConstructors { _, constructor -> members.add(constructor) }
|
||||
hookClass.instance?.allMethods { _, method -> members.add(method) }
|
||||
isHookMemberSetup = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找 [hookClass] 需要 Hook 的方法
|
||||
*
|
||||
* 在同一个 [injectMember] 中
|
||||
*
|
||||
* 你只能使用一次 [allMethods]、[allConstructors]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
* - ❗在同一个 [injectMember] 中你只能使用一次 [members]、[allMembers]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
* @param initiate 方法体
|
||||
* @return [MethodFinder.Result]
|
||||
*/
|
||||
inline fun method(initiate: MethodFinder.() -> Unit) = try {
|
||||
hookMemberMode = HookMemberMode.HOOK_CONVENTIONAL
|
||||
isHookMemberSetup = true
|
||||
MethodFinder(hookInstance = this, hookClass.instance).apply(initiate).apply { finder = this }.build(isBind = true)
|
||||
} catch (e: Throwable) {
|
||||
@@ -299,14 +296,11 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/**
|
||||
* 查找 [hookClass] 需要 Hook 的构造方法
|
||||
*
|
||||
* 在同一个 [injectMember] 中
|
||||
*
|
||||
* 你只能使用一次 [allMethods]、[allConstructors]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
* - ❗在同一个 [injectMember] 中你只能使用一次 [members]、[allMembers]、[method]、[constructor] 方法 - 否则结果会被替换
|
||||
* @param initiate 方法体
|
||||
* @return [ConstructorFinder.Result]
|
||||
*/
|
||||
inline fun constructor(initiate: ConstructorFinder.() -> Unit = { emptyParam() }) = try {
|
||||
hookMemberMode = HookMemberMode.HOOK_CONVENTIONAL
|
||||
isHookMemberSetup = true
|
||||
ConstructorFinder(hookInstance = this, hookClass.instance).apply(initiate).apply { finder = this }.build(isBind = true)
|
||||
} catch (e: Throwable) {
|
||||
@@ -357,7 +351,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/**
|
||||
* 在方法执行完成前 Hook
|
||||
*
|
||||
* 不可与 [replaceAny]、[replaceUnit]、[replaceTo] 同时使用
|
||||
* - 不可与 [replaceAny]、[replaceUnit]、[replaceTo] 同时使用
|
||||
* @param initiate [HookParam] 方法体
|
||||
*/
|
||||
fun beforeHook(initiate: HookParam.() -> Unit) {
|
||||
@@ -368,7 +362,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/**
|
||||
* 在方法执行完成后 Hook
|
||||
*
|
||||
* 不可与 [replaceAny]、[replaceUnit]、[replaceTo] 同时使用
|
||||
* - 不可与 [replaceAny]、[replaceUnit]、[replaceTo] 同时使用
|
||||
* @param initiate [HookParam] 方法体
|
||||
*/
|
||||
fun afterHook(initiate: HookParam.() -> Unit) {
|
||||
@@ -379,37 +373,34 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/**
|
||||
* 拦截并替换此方法内容 - 给出返回值
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* @param initiate [HookParam] 方法体
|
||||
*/
|
||||
fun replaceAny(initiate: HookParam.() -> Any?) {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = false
|
||||
replaceHookCallback = initiate
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截并替换此方法内容 - 没有返回值 ([Unit])
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* @param initiate [HookParam] 方法体
|
||||
*/
|
||||
fun replaceUnit(initiate: HookParam.() -> Unit) {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = false
|
||||
replaceHookCallback = initiate
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截并替换方法返回值
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* @param any 要替换为的返回值对象
|
||||
*/
|
||||
fun replaceTo(any: Any?) {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = true
|
||||
replaceHookResult = any
|
||||
replaceHookCallback = { any }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,12 +408,11 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
*
|
||||
* - ❗确保替换方法的返回对象为 [Boolean]
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
*/
|
||||
fun replaceToTrue() {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = true
|
||||
replaceHookResult = true
|
||||
replaceHookCallback = { true }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -430,12 +420,11 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
*
|
||||
* - ❗确保替换方法的返回对象为 [Boolean]
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
*/
|
||||
fun replaceToFalse() {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = true
|
||||
replaceHookResult = false
|
||||
replaceHookCallback = { false }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,12 +432,11 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
*
|
||||
* - ❗这将会禁止此方法执行并返回 null
|
||||
*
|
||||
* 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
* - 不可与 [beforeHook]、[afterHook] 同时使用
|
||||
*/
|
||||
fun intercept() {
|
||||
isReplaceHookMode = true
|
||||
isReplaceHookOnlyResultMode = true
|
||||
replaceHookResult = null
|
||||
replaceHookCallback = { null }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,17 +468,51 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
return
|
||||
}
|
||||
members.takeIf { it.isNotEmpty() }?.forEach { member ->
|
||||
runCatching {
|
||||
member.hook().also {
|
||||
when {
|
||||
it.first?.member == null -> error("Hook Member [$member] failed")
|
||||
it.second -> onAlreadyHookedCallback?.invoke(it.first?.member!!)
|
||||
else -> it.first?.also { e ->
|
||||
memberUnhooks.add(e)
|
||||
onHookedCallback?.invoke(e.member!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredHookingFailure) onHookFailureMsg(it, member)
|
||||
}
|
||||
} ?: Throwable("Finding Error isSetUpMember [$isHookMemberSetup] [$tag]").also {
|
||||
onNoSuchMemberFailureCallback?.invoke(it)
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredNoSuchMemberFailure) yLoggerE(
|
||||
msg = "$hostTagName " + (if (isHookMemberSetup)
|
||||
"Hooked Member with a finding error by $hookClass [$tag]"
|
||||
else "Hooked Member cannot be non-null by $hookClass [$tag]"),
|
||||
e = findingThrowable ?: it
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook 方法、构造方法
|
||||
* @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
private fun Member.hook(): Pair<YukiMemberHook.Unhook?, Boolean> {
|
||||
/** 定义替换 Hook 的 [HookParam] */
|
||||
val replaceHookParam = HookParam(createrInstance = this@YukiMemberHookCreater)
|
||||
|
||||
/** 定义替换 Hook 回调方法体 */
|
||||
val replaceMent = object : YukiMemberReplacement(priority) {
|
||||
override fun replaceHookedMember(wrapper: HookParamWrapper): Any? {
|
||||
return replaceHookParam.assign(wrapper).let { param ->
|
||||
override fun replaceHookedMember(wrapper: HookParamWrapper) =
|
||||
replaceHookParam.assign(wrapper).let { param ->
|
||||
try {
|
||||
if (replaceHookCallback != null || isReplaceHookOnlyResultMode)
|
||||
onHookLogMsg(msg = "Replace Hook Member [${member ?: "All Member $allMethodsName"}] done [$tag]")
|
||||
(if (isReplaceHookOnlyResultMode) replaceHookResult else replaceHookCallback?.invoke(param)).also { HookParam.invoke() }
|
||||
if (replaceHookCallback != null) onHookLogMsg(msg = "Replace Hook Member [${this@hook}] done [$tag]")
|
||||
replaceHookCallback?.invoke(param).also { HookParam.invoke() }
|
||||
} catch (e: Throwable) {
|
||||
onConductFailureCallback?.invoke(param, e)
|
||||
onAllFailureCallback?.invoke(e)
|
||||
@@ -498,7 +520,6 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 定义前 Hook 的 [HookParam] */
|
||||
@@ -513,8 +534,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
beforeHookParam.assign(wrapper).also { param ->
|
||||
runCatching {
|
||||
beforeHookCallback?.invoke(param)
|
||||
if (beforeHookCallback != null)
|
||||
onHookLogMsg(msg = "Before Hook Member [${member ?: "All of \"$allMethodsName\""}] done [$tag]")
|
||||
if (beforeHookCallback != null) onHookLogMsg(msg = "Before Hook Member [${this@hook}] done [$tag]")
|
||||
HookParam.invoke()
|
||||
}.onFailure {
|
||||
onConductFailureCallback?.invoke(param, it)
|
||||
@@ -528,8 +548,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
afterHookParam.assign(wrapper).also { param ->
|
||||
runCatching {
|
||||
afterHookCallback?.invoke(param)
|
||||
if (afterHookCallback != null)
|
||||
onHookLogMsg(msg = "After Hook Member [${member ?: "All of \"$allMethodsName\""}] done [$tag]")
|
||||
if (afterHookCallback != null) onHookLogMsg(msg = "After Hook Member [${this@hook}] done [$tag]")
|
||||
HookParam.invoke()
|
||||
}.onFailure {
|
||||
onConductFailureCallback?.invoke(param, it)
|
||||
@@ -539,74 +558,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hookMemberMode == HookMemberMode.HOOK_CONVENTIONAL)
|
||||
if (member != null)
|
||||
member.also { member ->
|
||||
runCatching {
|
||||
(if (isReplaceHookMode) YukiHookHelper.hookMethod(member, replaceMent)
|
||||
else YukiHookHelper.hookMethod(member, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first?.member == null -> error("Hook Member [$member] failed")
|
||||
it.second -> onAlreadyHookedCallback?.invoke(it.first?.member!!)
|
||||
else -> {
|
||||
memberUnhook = it.first
|
||||
onHookedCallback?.invoke(it.first?.member!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredHookingFailure) onHookFailureMsg(it)
|
||||
}
|
||||
}
|
||||
else Throwable("Finding Error isSetUpMember [$isHookMemberSetup] [$tag]").also {
|
||||
onNoSuchMemberFailureCallback?.invoke(it)
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredNoSuchMemberFailure) yLoggerE(
|
||||
msg = "$hostTagName " + (if (isHookMemberSetup)
|
||||
"Hooked Member with a finding error by $hookClass [$tag]"
|
||||
else "Hooked Member cannot be non-null by $hookClass [$tag]"),
|
||||
e = findingThrowable ?: it
|
||||
)
|
||||
}
|
||||
else runCatching {
|
||||
when (hookMemberMode) {
|
||||
HookMemberMode.HOOK_ALL_METHODS ->
|
||||
(if (isReplaceHookMode) YukiHookHelper.hookAllMethods(hookClass.instance, allMethodsName, replaceMent)
|
||||
else YukiHookHelper.hookAllMethods(hookClass.instance, allMethodsName, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first.isEmpty() -> throw NoSuchMethodError("No Method name \"$allMethodsName\" matched")
|
||||
it.second -> it.first.forEach { e -> if (e.member != null) onAlreadyHookedCallback?.invoke(e.member!!) }
|
||||
else -> {
|
||||
memberUnhook = it.first.first()
|
||||
it.first.forEach { e -> if (e.member != null) onHookedCallback?.invoke(e.member!!) }
|
||||
}
|
||||
}
|
||||
}
|
||||
HookMemberMode.HOOK_ALL_CONSTRUCTORS ->
|
||||
(if (isReplaceHookMode) YukiHookHelper.hookAllConstructors(hookClass.instance, replaceMent)
|
||||
else YukiHookHelper.hookAllConstructors(hookClass.instance, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first.isEmpty() -> throw NoSuchMethodError("No Constructor matched")
|
||||
it.second -> it.first.forEach { e -> if (e.member != null) onAlreadyHookedCallback?.invoke(e.member!!) }
|
||||
else -> {
|
||||
memberUnhook = it.first.first()
|
||||
it.first.forEach { e -> if (e.member != null) onHookedCallback?.invoke(e.member!!) }
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> error("Hooked got a no error possible")
|
||||
}
|
||||
}.onFailure {
|
||||
val isMemberNotFound = it.message?.lowercase()?.contains(other = "nosuch") == true ||
|
||||
it is NoSuchMethodError || it is NoSuchFieldError
|
||||
if (isMemberNotFound) onNoSuchMemberFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if ((isNotIgnoredHookingFailure && isMemberNotFound.not()) || (isNotIgnoredNoSuchMemberFailure && isMemberNotFound))
|
||||
yLoggerE(msg = "$hostTagName Hooked All Members with an error in $hookClass [$tag]", e = it)
|
||||
}
|
||||
return YukiHookHelper.hookMethod(hookMethod = this, if (isReplaceHookMode) replaceMent else beforeAfterHook)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -620,9 +572,12 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/**
|
||||
* Hook 失败但未设置 [onAllFailureCallback] 将默认输出失败信息
|
||||
* @param throwable 异常信息
|
||||
* @param member 异常 [Member] - 可空
|
||||
*/
|
||||
private fun onHookFailureMsg(throwable: Throwable) =
|
||||
yLoggerE(msg = "$hostTagName Try to hook ${hookClass.instance ?: hookClass.name}[$member] got an Exception [$tag]", e = throwable)
|
||||
private fun onHookFailureMsg(throwable: Throwable, member: Member? = null) = yLoggerE(
|
||||
msg = "$hostTagName Try to hook [${hookClass.instance ?: hookClass.name}]${member?.let { "[$it]" } ?: ""} got an Exception [$tag]",
|
||||
e = throwable
|
||||
)
|
||||
|
||||
/**
|
||||
* 判断是否没有设置 Hook 过程中的任何异常拦截
|
||||
@@ -631,7 +586,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
private val isNotIgnoredHookingFailure get() = onHookingFailureCallback == null && onAllFailureCallback == null
|
||||
|
||||
/**
|
||||
* 判断是否没有设置 Hook 过程中 [member] 找不到的任何异常拦截
|
||||
* 判断是否没有设置 Hook 过程中 [members] 找不到的任何异常拦截
|
||||
* @return [Boolean] 没有设置任何异常拦截
|
||||
*/
|
||||
internal val isNotIgnoredNoSuchMemberFailure get() = onNoSuchMemberFailureCallback == null && isNotIgnoredHookingFailure
|
||||
@@ -642,7 +597,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
*/
|
||||
internal val hostTagName get() = if (packageParam.appUserId != 0) "[$packageName][${packageParam.appUserId}]" else "[$packageName]"
|
||||
|
||||
override fun toString() = "[tag] $tag [priority] $priority [class] $hookClass [member] $member $allMethodsName [mode] $hookMemberMode"
|
||||
override fun toString() = "[tag] $tag [priority] $priority [class] $hookClass [members] $members"
|
||||
|
||||
/**
|
||||
* 监听 Hook 结果实现类
|
||||
@@ -672,7 +627,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听 [member] Hook 成功的回调方法
|
||||
* 监听 [members] Hook 成功的回调方法
|
||||
*
|
||||
* 在首次 Hook 成功后回调
|
||||
*
|
||||
@@ -686,9 +641,9 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听 [member] 重复 Hook 的回调方法
|
||||
* 监听 [members] 重复 Hook 的回调方法
|
||||
*
|
||||
* - ❗同一个 [hookClass] 中的同一个 [member] 不会被 API 重复 Hook - 若由于各种原因重复 Hook 会回调此方法
|
||||
* - ❗同一个 [hookClass] 中的同一个 [members] 不会被 API 重复 Hook - 若由于各种原因重复 Hook 会回调此方法
|
||||
* @param result 回调被重复 Hook 的 [Member]
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
@@ -698,7 +653,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听 [member] 不存在发生错误的回调方法
|
||||
* 监听 [members] 不存在发生错误的回调方法
|
||||
* @param result 回调错误
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
@@ -708,7 +663,7 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略 [member] 不存在发生的错误
|
||||
* 忽略 [members] 不存在发生的错误
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
fun ignoredNoSuchMemberFailure() = onNoSuchMemberFailure {}
|
||||
@@ -768,11 +723,15 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
* @param result 回调是否成功
|
||||
*/
|
||||
fun remove(result: (Boolean) -> Unit = {}) {
|
||||
memberUnhook?.remove()
|
||||
runCatching { preHookMembers.remove(this@MemberHookCreater.toString()) }
|
||||
if (memberUnhook != null) onHookLogMsg(msg = "Remove Hooked Member [${member ?: "All of \"$allMethodsName\""}] done [$tag]")
|
||||
result(memberUnhook != null)
|
||||
memberUnhook = null
|
||||
memberUnhooks.takeIf { it.isNotEmpty() }?.apply {
|
||||
forEach {
|
||||
it.remove()
|
||||
onHookLogMsg(msg = "Remove Hooked Member [${it.member}] done [$tag]")
|
||||
}
|
||||
runCatching { preHookMembers.remove(this@MemberHookCreater.toString()) }
|
||||
clear()
|
||||
result(true)
|
||||
} ?: result(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,6 @@ import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper
|
||||
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
|
||||
import de.robv.android.xposed.XC_MethodHook
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
@@ -58,12 +57,6 @@ internal object YukiHookedMembers {
|
||||
|
||||
/** 已经 Hook 的 [Member] 数组 */
|
||||
internal val hookedMembers = HashSet<YukiMemberHook.Unhook>()
|
||||
|
||||
/** 已经 Hook 的成组 [Method] 数组 */
|
||||
internal val hookedQueueMethods = HashMap<String, HashSet<YukiMemberHook.Unhook>>()
|
||||
|
||||
/** 已经 Hook 的成组 [Constructor] 数组 */
|
||||
internal val hookedQueueConstructors = HashMap<String, HashSet<YukiMemberHook.Unhook>>()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,59 +117,6 @@ internal object YukiHookHelper {
|
||||
else Pair(null, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook 当前 [hookClass] 所有 [methodName] 的方法
|
||||
*
|
||||
* 对接 [XposedBridge.hookAllMethods]
|
||||
* @param hookClass 当前 Hook 的 [Class]
|
||||
* @param methodName 方法名
|
||||
* @param callback 回调
|
||||
* @return [Pair] - ([HashSet] 成功 Hook 的 [YukiMemberHook.Unhook] 数组,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
internal fun hookAllMethods(
|
||||
hookClass: Class<*>?, methodName: String, callback: YukiHookCallback
|
||||
): Pair<HashSet<YukiMemberHook.Unhook>, Boolean> {
|
||||
var isAlreadyHook = false
|
||||
val hookedMembers = HashSet<YukiMemberHook.Unhook>().also {
|
||||
val allMethodsName = "$hookClass$methodName"
|
||||
if (YukiHookedMembers.hookedQueueMethods.contains(allMethodsName)) {
|
||||
isAlreadyHook = true
|
||||
YukiHookedMembers.hookedQueueMethods[allMethodsName]?.forEach { e -> it.add(e) }
|
||||
return@also
|
||||
}
|
||||
if (YukiHookBridge.hasXposedBridge.not()) return@also
|
||||
XposedBridge.hookAllMethods(hookClass, methodName, callback.compat()).takeIf { e -> e.isNotEmpty() }
|
||||
?.forEach { e -> it.add(YukiMemberHook.Unhook.wrapper(e, allMethodsName)) }
|
||||
YukiHookedMembers.hookedQueueMethods[allMethodsName] = it
|
||||
}
|
||||
return Pair(hookedMembers, isAlreadyHook)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook 当前 [hookClass] 所有构造方法
|
||||
*
|
||||
* 对接 [XposedBridge.hookAllConstructors]
|
||||
* @param hookClass 当前 Hook 的 [Class]
|
||||
* @param callback 回调
|
||||
* @return [Pair] - ([HashSet] 成功 Hook 的 [YukiMemberHook.Unhook] 数组,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
internal fun hookAllConstructors(hookClass: Class<*>?, callback: YukiHookCallback): Pair<HashSet<YukiMemberHook.Unhook>, Boolean> {
|
||||
var isAlreadyHook = false
|
||||
val hookedMembers = HashSet<YukiMemberHook.Unhook>().also {
|
||||
val allConstructorsName = "$hookClass<init>"
|
||||
if (YukiHookedMembers.hookedQueueConstructors.contains(allConstructorsName)) {
|
||||
isAlreadyHook = true
|
||||
YukiHookedMembers.hookedQueueConstructors[allConstructorsName]?.forEach { e -> it.add(e) }
|
||||
return@also
|
||||
}
|
||||
if (YukiHookBridge.hasXposedBridge.not()) return@also
|
||||
XposedBridge.hookAllConstructors(hookClass, callback.compat()).takeIf { e -> e.isNotEmpty() }
|
||||
?.forEach { e -> it.add(YukiMemberHook.Unhook.wrapper(e, allConstructorsName)) }
|
||||
YukiHookedMembers.hookedQueueConstructors[allConstructorsName] = it
|
||||
}
|
||||
return Pair(hookedMembers, isAlreadyHook)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行原始 [Member]
|
||||
*
|
||||
@@ -185,14 +125,10 @@ internal object YukiHookHelper {
|
||||
* @param args 参数实例
|
||||
* @return [Any] or null
|
||||
*/
|
||||
internal fun invokeOriginalMember(member: Member, instance: Any?, vararg args: Any?): Any? {
|
||||
val isHookedMember = YukiHookedMembers.hookedMembers.any { it.member.toString() == member.toString() }
|
||||
val isQueueMethod = YukiHookedMembers.hookedQueueMethods.any { it.value.any { e -> e.member.toString() == member.toString() } }
|
||||
val isQueueConstructor = YukiHookedMembers.hookedQueueConstructors.any { it.value.any { e -> e.member.toString() == member.toString() } }
|
||||
return if (YukiHookBridge.hasXposedBridge && (isHookedMember || isQueueMethod || isQueueConstructor))
|
||||
internal fun invokeOriginalMember(member: Member, instance: Any?, vararg args: Any?) =
|
||||
if (YukiHookBridge.hasXposedBridge && YukiHookedMembers.hookedMembers.any { it.member.toString() == member.toString() })
|
||||
XposedBridge.invokeOriginalMethod(member, instance, args)
|
||||
else null
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容对接 Hook 回调接口
|
||||
@@ -263,19 +199,17 @@ internal abstract class YukiMemberHook(override val priority: Int = YukiHookPrio
|
||||
/**
|
||||
* 已经 Hook 且可被解除 Hook 的 [Member] 实现类
|
||||
* @param instance 对接 [XC_MethodHook.Unhook]
|
||||
* @param tag 标识多个 [Member] Hook 的标签 - 例如 [YukiHookHelper.hookAllMethods]、[YukiHookHelper.hookAllConstructors]
|
||||
*/
|
||||
internal class Unhook private constructor(private val instance: XC_MethodHook.Unhook, private val tag: String) {
|
||||
internal class Unhook private constructor(private val instance: XC_MethodHook.Unhook) {
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* 从 [XC_MethodHook.Unhook] 创建 [Unhook] 实例
|
||||
* @param instance [XC_MethodHook.Unhook] 实例
|
||||
* @param tag 标识多个 [Member] Hook 的标签 - 默认空
|
||||
* @return [Unhook]
|
||||
*/
|
||||
internal fun wrapper(instance: XC_MethodHook.Unhook, tag: String = "") = Unhook(instance, tag)
|
||||
internal fun wrapper(instance: XC_MethodHook.Unhook) = Unhook(instance)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,37 +218,11 @@ internal abstract class YukiMemberHook(override val priority: Int = YukiHookPrio
|
||||
*/
|
||||
internal val member: Member? get() = instance.hookedMethod
|
||||
|
||||
/**
|
||||
* 解除 Hook 并从
|
||||
* [YukiHookedMembers.hookedMembers]、
|
||||
* [YukiHookedMembers.hookedQueueMethods]、
|
||||
* [YukiHookedMembers.hookedQueueConstructors]
|
||||
* 缓存数组中移除
|
||||
*/
|
||||
/** 解除 [instance] 的 Hook 并从 [YukiHookedMembers.hookedMembers] 缓存数组中移除 */
|
||||
internal fun remove() {
|
||||
if (tag.isNotBlank()) runCatching {
|
||||
when {
|
||||
YukiHookedMembers.hookedQueueMethods.contains(tag) -> {
|
||||
YukiHookedMembers.hookedQueueMethods[tag]?.takeIf { it.isNotEmpty() }?.forEach { it.unhook(isNeedRemove = false) }
|
||||
YukiHookedMembers.hookedQueueMethods.remove(tag)
|
||||
}
|
||||
YukiHookedMembers.hookedQueueConstructors.contains(tag) -> {
|
||||
YukiHookedMembers.hookedQueueConstructors[tag]?.takeIf { it.isNotEmpty() }?.forEach { it.unhook(isNeedRemove = false) }
|
||||
YukiHookedMembers.hookedQueueConstructors.remove(tag)
|
||||
}
|
||||
else -> unhook()
|
||||
}
|
||||
} else unhook()
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除 [instance] 的 Hook
|
||||
* @param isNeedRemove 是否需要从 [YukiHookedMembers.hookedMembers] 中移除
|
||||
*/
|
||||
private fun unhook(isNeedRemove: Boolean = true) {
|
||||
if (YukiHookBridge.hasXposedBridge.not()) return
|
||||
instance.unhook()
|
||||
if (isNeedRemove) runCatching { YukiHookedMembers.hookedMembers.remove(this) }
|
||||
runCatching { YukiHookedMembers.hookedMembers.remove(this) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user