mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Modify almost code, update version to 1.0.2
This commit is contained in:
@@ -70,7 +70,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
* @return [Class]
|
||||
* @throws IllegalStateException 如果当前 [Class] 未被正确装载
|
||||
*/
|
||||
val thisClass
|
||||
val instanceClass
|
||||
get() = hookClass.instance ?: error("Cannot get hook class \"${hookClass.name}\" cause ${hookClass.throwable?.message}")
|
||||
|
||||
/**
|
||||
@@ -138,7 +138,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
/**
|
||||
* 手动指定要 Hook 的方法、构造类
|
||||
*
|
||||
* 你可以调用 [thisClass] 来手动查询要 Hook 的方法
|
||||
* 你可以调用 [instanceClass] 来手动查询要 Hook 的方法
|
||||
*/
|
||||
var member: Member? = null
|
||||
|
||||
@@ -180,11 +180,11 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
if (hookClass.instance == null) return MethodFinder(hookInstance = this).failure(hookClass.throwable)
|
||||
hookAllMembers = HookAllMembers.HOOK_NONE
|
||||
isHookMemberSetup = true
|
||||
return MethodFinder(hookInstance = this, hookClass.instance).apply(initiate).build()
|
||||
return MethodFinder(hookInstance = this, hookClass.instance).apply(initiate).build(isBind = true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找 [hookClass] 需要 Hook 的构造类
|
||||
* 查找 [hookClass] 需要 Hook 的构造方法
|
||||
*
|
||||
* 你只能使用一次 [method] 或 [constructor] 方法 - 否则结果会被替换
|
||||
* @param initiate 方法体
|
||||
@@ -194,17 +194,35 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
if (hookClass.instance == null) return ConstructorFinder(hookInstance = this).failure(hookClass.throwable)
|
||||
hookAllMembers = HookAllMembers.HOOK_NONE
|
||||
isHookMemberSetup = true
|
||||
return ConstructorFinder(hookInstance = this, hookClass.instance).apply(initiate).build()
|
||||
return ConstructorFinder(hookInstance = this, hookClass.instance).apply(initiate).build(isBind = true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找 [Field]
|
||||
* 使用当前 [hookClass] 查找并得到 [Field]
|
||||
* @param initiate 方法体
|
||||
* @return [FieldFinder.Result]
|
||||
*/
|
||||
fun field(initiate: FieldFinder.() -> Unit) =
|
||||
if (hookClass.instance == null) FieldFinder(hookInstance = this).failure(hookClass.throwable)
|
||||
else FieldFinder(hookInstance = this, hookClass.instance).apply(initiate).build()
|
||||
fun HookParam.field(initiate: FieldFinder.() -> Unit) =
|
||||
if (hookClass.instance == null) FieldFinder(hookInstance = this@MemberHookCreater).failure(hookClass.throwable)
|
||||
else FieldFinder(hookInstance = this@MemberHookCreater, hookClass.instance).apply(initiate).build()
|
||||
|
||||
/**
|
||||
* 使用当前 [hookClass] 查找并得到方法
|
||||
* @param initiate 方法体
|
||||
* @return [MethodFinder.Result]
|
||||
*/
|
||||
fun HookParam.method(initiate: MethodFinder.() -> Unit) =
|
||||
if (hookClass.instance == null) MethodFinder(hookInstance = this@MemberHookCreater).failure(hookClass.throwable)
|
||||
else MethodFinder(hookInstance = this@MemberHookCreater, hookClass.instance).apply(initiate).build()
|
||||
|
||||
/**
|
||||
* 使用当前 [hookClass] 查找并得到构造方法
|
||||
* @param initiate 方法体
|
||||
* @return [ConstructorFinder.Result]
|
||||
*/
|
||||
fun HookParam.constructor(initiate: ConstructorFinder.() -> Unit) =
|
||||
if (hookClass.instance == null) ConstructorFinder(hookInstance = this@MemberHookCreater).failure(hookClass.throwable)
|
||||
else ConstructorFinder(hookInstance = this@MemberHookCreater, hookClass.instance).apply(initiate).build()
|
||||
|
||||
/**
|
||||
* 在方法执行完成前 Hook
|
||||
@@ -418,7 +436,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
* Hook 过程中开启了 [YukiHookAPI.Configs.isDebug] 输出调试信息
|
||||
* @param msg 调试日志内容
|
||||
*/
|
||||
internal fun onHookLogMsg(msg: String) {
|
||||
private fun onHookLogMsg(msg: String) {
|
||||
if (YukiHookAPI.Configs.isDebug) loggerI(msg = msg)
|
||||
}
|
||||
|
||||
|
@@ -25,14 +25,13 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/2/4.
|
||||
*/
|
||||
@file:Suppress("unused", "EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate")
|
||||
@file:Suppress("unused", "EXPERIMENTAL_API_USAGE", "MemberVisibilityCanBePrivate", "UNCHECKED_CAST")
|
||||
|
||||
package com.highcapable.yukihookapi.hook.core.finder
|
||||
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
@@ -42,17 +41,23 @@ import java.lang.reflect.Constructor
|
||||
* [Constructor] 查找类
|
||||
*
|
||||
* 可通过指定类型查找指定构造方法
|
||||
* @param hookInstance 当前 Hook 实例
|
||||
* @param hookClass 当前被 Hook 的 [Class]
|
||||
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiHookCreater.MemberHookCreater.member]
|
||||
* @param classSet 当前需要查找的 [Class] 实例
|
||||
*/
|
||||
class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, private val hookClass: Class<*>? = null) {
|
||||
class ConstructorFinder(
|
||||
override val hookInstance: YukiHookCreater.MemberHookCreater? = null,
|
||||
override val classSet: Class<*>? = null
|
||||
) : BaseFinder(tag = "Constructor", hookInstance, classSet) {
|
||||
|
||||
/** 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater] */
|
||||
private var isBindToHooker = false
|
||||
|
||||
/** 当前重查找结果回调 */
|
||||
private var remedyPlansCallback: (() -> Unit)? = null
|
||||
|
||||
/** [Constructor] 参数数组 */
|
||||
private var params: Array<out Class<*>>? = null
|
||||
|
||||
/** 是否使用了 [RemedyPlan] */
|
||||
private var isUsingRemedyPlan = false
|
||||
|
||||
/**
|
||||
* [Constructor] 参数
|
||||
*
|
||||
@@ -73,8 +78,18 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
*/
|
||||
private val result
|
||||
get() = if (params != null)
|
||||
ReflectionUtils.findConstructorExact(hookClass, *params!!)
|
||||
else ReflectionUtils.findConstructorExact(hookClass)
|
||||
ReflectionUtils.findConstructorExact(classSet, *params!!)
|
||||
else ReflectionUtils.findConstructorExact(classSet)
|
||||
|
||||
/**
|
||||
* 设置实例
|
||||
* @param isBind 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater]
|
||||
* @param constructor 当前找到的 [Constructor]
|
||||
*/
|
||||
private fun setInstance(isBind: Boolean, constructor: Constructor<*>) {
|
||||
memberInstance = constructor
|
||||
if (isBind) hookInstance?.member = constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到构造方法结果
|
||||
@@ -83,11 +98,12 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
* @return [Result]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun build() = try {
|
||||
override fun build(isBind: Boolean) = try {
|
||||
runBlocking {
|
||||
hookInstance.member = result
|
||||
isBindToHooker = isBind
|
||||
setInstance(isBind, result)
|
||||
}.result {
|
||||
hookInstance.onHookLogMsg(msg = "Find Constructor [${hookInstance.member}] takes ${it}ms [${hookInstance.tag}]")
|
||||
onHookLogMsg(msg = "Find Constructor [${memberInstance}] takes ${it}ms [${hookTag}]")
|
||||
}
|
||||
Result()
|
||||
} catch (e: Throwable) {
|
||||
@@ -103,22 +119,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
* @return [Result]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
|
||||
/**
|
||||
* 发生错误时输出日志
|
||||
* @param msg 消息日志
|
||||
* @param throwable 错误
|
||||
* @param isAlwaysPrint 忽略条件每次都打印错误
|
||||
*/
|
||||
private fun onFailureMsg(msg: String = "", throwable: Throwable? = null, isAlwaysPrint: Boolean = false) {
|
||||
fun print() = loggerE(msg = "NoSuchConstructor happend in [$hookClass] $msg [${hookInstance.tag}]", e = throwable)
|
||||
if (isAlwaysPrint) print()
|
||||
else Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (hookInstance.isNotIgnoredHookingFailure && !isUsingRemedyPlan) print()
|
||||
}.start()
|
||||
}
|
||||
override fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
|
||||
/**
|
||||
* [Constructor] 重查找实现类
|
||||
@@ -139,7 +140,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
* @param initiate 方法体
|
||||
*/
|
||||
fun constructor(initiate: ConstructorFinder.() -> Unit) =
|
||||
Result().apply { remedyPlans.add(Pair(ConstructorFinder(hookInstance, hookClass).apply(initiate), this)) }
|
||||
Result().apply { remedyPlans.add(Pair(ConstructorFinder(hookInstance, classSet).apply(initiate), this)) }
|
||||
|
||||
/**
|
||||
* 开始重查找
|
||||
@@ -154,13 +155,14 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
remedyPlans.forEachIndexed { p, it ->
|
||||
runCatching {
|
||||
runBlocking {
|
||||
hookInstance.member = it.first.result
|
||||
setInstance(isBindToHooker, it.first.result)
|
||||
}.result {
|
||||
hookInstance.onHookLogMsg(msg = "Find Constructor [${hookInstance.member}] takes ${it}ms [${hookInstance.tag}]")
|
||||
onHookLogMsg(msg = "Find Constructor [${memberInstance}] takes ${it}ms [${hookTag}]")
|
||||
}
|
||||
isFindSuccess = true
|
||||
it.second.onFindCallback?.invoke(hookInstance.member as Constructor<*>)
|
||||
hookInstance.onHookLogMsg(msg = "Constructor [${hookInstance.member}] trying ${p + 1} times success by RemedyPlan [${hookInstance.tag}]")
|
||||
it.second.onFindCallback?.invoke(memberInstance as Constructor<*>)
|
||||
remedyPlansCallback?.invoke()
|
||||
onHookLogMsg(msg = "Constructor [${memberInstance}] trying ${p + 1} times success by RemedyPlan [${hookTag}]")
|
||||
return@run
|
||||
}.onFailure {
|
||||
lastError = it
|
||||
@@ -175,7 +177,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
)
|
||||
remedyPlans.clear()
|
||||
}
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,6 +214,27 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
*/
|
||||
fun result(initiate: Result.() -> Unit) = apply(initiate)
|
||||
|
||||
/**
|
||||
* 获得 [Constructor] 实例处理类
|
||||
*
|
||||
* - ❗在 [memberInstance] 结果为空时使用此方法将无法获得对象
|
||||
* - ❗若你设置了 [remedys] 请使用 [wait] 回调结果方法
|
||||
* @return [Instance]
|
||||
*/
|
||||
fun get() = Instance()
|
||||
|
||||
/**
|
||||
* 获得 [Constructor] 实例处理类
|
||||
*
|
||||
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
|
||||
* - ❗若你没有设置 [remedys] 此方法将不会被回调
|
||||
* @param initiate 回调 [Instance]
|
||||
*/
|
||||
fun wait(initiate: Instance.() -> Unit) {
|
||||
if (memberInstance != null) initiate(get())
|
||||
else remedyPlansCallback = { initiate(get()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建构造方法重查找功能
|
||||
*
|
||||
@@ -238,5 +261,39 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
||||
if (isNoSuch) initiate(e ?: Throwable())
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* [Constructor] 实例处理类
|
||||
*
|
||||
* 调用与创建目标实例类对象
|
||||
*/
|
||||
inner class Instance {
|
||||
|
||||
/**
|
||||
* 执行构造方法创建目标实例
|
||||
* @param param 构造方法参数
|
||||
* @return [Any] or null
|
||||
*/
|
||||
private fun baseCall(vararg param: Any?) =
|
||||
if (param.isNotEmpty())
|
||||
(memberInstance as? Constructor<*>?)?.newInstance(*param)
|
||||
else (memberInstance as? Constructor<*>?)?.newInstance()
|
||||
|
||||
/**
|
||||
* 执行构造方法创建目标实例 - 不指定目标实例类型
|
||||
* @param param 构造方法参数
|
||||
* @return [Any] or null
|
||||
*/
|
||||
fun call(vararg param: Any?) = baseCall(*param)
|
||||
|
||||
/**
|
||||
* 执行构造方法创建目标实例 - 指定 [T] 目标实例类型
|
||||
* @param param 构造方法参数
|
||||
* @return [T] or null
|
||||
*/
|
||||
fun <T> newInstance(vararg param: Any?) = baseCall(*param) as? T?
|
||||
|
||||
override fun toString() = "[${(memberInstance as? Constructor<*>?)?.name ?: "<empty>"}]"
|
||||
}
|
||||
}
|
||||
}
|
@@ -32,6 +32,7 @@ package com.highcapable.yukihookapi.hook.core.finder
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
@@ -42,19 +43,12 @@ import java.lang.reflect.Field
|
||||
*
|
||||
* 可通过执行类型查找指定变量
|
||||
* @param hookInstance 当前 Hook 实例
|
||||
* @param hookClass 当前被 Hook 的 [Class]
|
||||
* @param classSet 当前需要查找的 [Class] 实例
|
||||
*/
|
||||
class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, private val hookClass: Class<*>? = null) {
|
||||
|
||||
/** 当前找到的 [Field] */
|
||||
private var fieldInstance: Field? = null
|
||||
|
||||
/**
|
||||
* [Field] 所在的 [Class]
|
||||
*
|
||||
* 不填默认为当前的 [hookClass]
|
||||
*/
|
||||
var classSet = hookClass
|
||||
class FieldFinder(
|
||||
override val hookInstance: YukiHookCreater.MemberHookCreater? = null,
|
||||
override val classSet: Class<*>? = null
|
||||
) : BaseFinder(tag = "Field", hookInstance, classSet) {
|
||||
|
||||
/**
|
||||
* [Field] 名称
|
||||
@@ -74,30 +68,30 @@ class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, p
|
||||
* 得到变量处理结果
|
||||
*
|
||||
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
|
||||
* @param isBind 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater]
|
||||
* @return [Result]
|
||||
* @throws IllegalStateException 如果 [name] 没有被设置
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun build() = when {
|
||||
override fun build(isBind: Boolean) = when {
|
||||
name.isBlank() -> {
|
||||
loggerE(msg = "Field name cannot be empty in Class [$classSet] [${hookInstance.tag}]")
|
||||
loggerE(msg = "Field name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
Result(isNoSuch = true)
|
||||
}
|
||||
else -> try {
|
||||
runBlocking {
|
||||
fieldInstance =
|
||||
memberInstance =
|
||||
if (type != null)
|
||||
ReflectionUtils.findFieldIfExists(classSet, type?.name, name)
|
||||
else classSet?.getDeclaredField(name)?.apply { isAccessible = true }
|
||||
}.result {
|
||||
hookInstance.onHookLogMsg(msg = "Find Field [${fieldInstance}] takes ${it}ms [${hookInstance.tag}]")
|
||||
onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]")
|
||||
}
|
||||
Result()
|
||||
} catch (e: Throwable) {
|
||||
Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (hookInstance.isNotIgnoredHookingFailure)
|
||||
loggerE(msg = "NoSuchField happend in [$classSet] [${hookInstance.tag}]", e = e)
|
||||
if (isNotIgnoredHookingFailure) loggerE(msg = "NoSuchField happend in [$classSet] [${hookTag}]", e = e)
|
||||
}.start()
|
||||
Result(isNoSuch = true, e)
|
||||
}
|
||||
@@ -111,12 +105,11 @@ class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, p
|
||||
* @return [Result]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
override fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
|
||||
/**
|
||||
* [Field] 查找结果实现类
|
||||
*
|
||||
* 可在这里处理找到的 [fieldInstance]
|
||||
* @param isNoSuch 是否没有找到变量 - 默认否
|
||||
* @param e 错误信息
|
||||
*/
|
||||
@@ -147,7 +140,7 @@ class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, p
|
||||
* 得到变量本身
|
||||
* @return [Field] or null
|
||||
*/
|
||||
fun give() = fieldInstance
|
||||
fun give() = memberInstance as? Field?
|
||||
|
||||
/**
|
||||
* 监听找不到变量时
|
||||
@@ -189,7 +182,8 @@ class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, p
|
||||
/** 设置变量实例为 null */
|
||||
fun setNull() = set(null)
|
||||
|
||||
override fun toString() = "[${self?.javaClass?.name ?: ""}] in [${instance?.javaClass?.name ?: ""}] value \"$self\""
|
||||
override fun toString() =
|
||||
"[${self?.javaClass?.name ?: "<empty>"}] in [${instance?.javaClass?.name ?: "<empty>"}] value \"$self\""
|
||||
}
|
||||
}
|
||||
}
|
@@ -25,13 +25,13 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/2/4.
|
||||
*/
|
||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_API_USAGE")
|
||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_API_USAGE", "UNCHECKED_CAST")
|
||||
|
||||
package com.highcapable.yukihookapi.hook.core.finder
|
||||
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
@@ -42,17 +42,23 @@ import java.lang.reflect.Method
|
||||
* [Method] 查找类
|
||||
*
|
||||
* 可通过指定类型查找指定方法
|
||||
* @param hookInstance 当前 Hook 实例
|
||||
* @param hookClass 当前 Hook 的 Class
|
||||
* @param hookInstance 当前 Hook 实例 - 填写后将自动设置 [YukiHookCreater.MemberHookCreater.member]
|
||||
* @param classSet 当前需要查找的 [Class] 实例
|
||||
*/
|
||||
class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, private val hookClass: Class<*>? = null) {
|
||||
class MethodFinder(
|
||||
override val hookInstance: YukiHookCreater.MemberHookCreater? = null,
|
||||
override val classSet: Class<*>? = null
|
||||
) : BaseFinder(tag = "Method", hookInstance, classSet) {
|
||||
|
||||
/** 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater] */
|
||||
private var isBindToHooker = false
|
||||
|
||||
/** 当前重查找结果回调 */
|
||||
private var remedyPlansCallback: (() -> Unit)? = null
|
||||
|
||||
/** [Method] 参数数组 */
|
||||
private var params: Array<out Class<*>>? = null
|
||||
|
||||
/** 是否使用了 [RemedyPlan] */
|
||||
private var isUsingRemedyPlan = false
|
||||
|
||||
/**
|
||||
* [Method] 名称
|
||||
*
|
||||
@@ -88,29 +94,44 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
*/
|
||||
private val result
|
||||
get() = if (params != null)
|
||||
ReflectionUtils.findMethodBestMatch(hookClass, returnType, name, *params!!)
|
||||
else ReflectionUtils.findMethodNoParam(hookClass, returnType, name)
|
||||
ReflectionUtils.findMethodBestMatch(classSet, returnType, name, *params!!)
|
||||
else ReflectionUtils.findMethodNoParam(classSet, returnType, name)
|
||||
|
||||
/**
|
||||
* 设置实例
|
||||
* @param isBind 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater]
|
||||
* @param method 当前找到的 [Method]
|
||||
*/
|
||||
private fun setInstance(isBind: Boolean, method: Method) {
|
||||
memberInstance = method
|
||||
if (isBind) hookInstance?.member = method
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到方法结果
|
||||
*
|
||||
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
|
||||
* @param isBind 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater]
|
||||
* @return [Result]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun build() = if (name.isBlank()) {
|
||||
loggerE(msg = "Method name cannot be empty in Class [$hookClass] [${hookInstance.tag}]")
|
||||
Result(isNoSuch = true)
|
||||
} else try {
|
||||
runBlocking {
|
||||
hookInstance.member = result
|
||||
}.result {
|
||||
hookInstance.onHookLogMsg(msg = "Find Method [${hookInstance.member}] takes ${it}ms [${hookInstance.tag}]")
|
||||
override fun build(isBind: Boolean) = when {
|
||||
name.isBlank() -> {
|
||||
loggerE(msg = "Method name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
Result(isNoSuch = true)
|
||||
}
|
||||
else -> try {
|
||||
runBlocking {
|
||||
isBindToHooker = isBind
|
||||
setInstance(isBind, result)
|
||||
}.result {
|
||||
onHookLogMsg(msg = "Find Method [${memberInstance}] takes ${it}ms [${hookTag}]")
|
||||
}
|
||||
Result()
|
||||
} catch (e: Throwable) {
|
||||
onFailureMsg(throwable = e)
|
||||
Result(isNoSuch = true, e)
|
||||
}
|
||||
Result()
|
||||
} catch (e: Throwable) {
|
||||
onFailureMsg(throwable = e)
|
||||
Result(isNoSuch = true, e)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,22 +142,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
* @return [Result]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
|
||||
/**
|
||||
* 发生错误时输出日志
|
||||
* @param msg 消息日志
|
||||
* @param throwable 错误
|
||||
* @param isAlwaysPrint 忽略条件每次都打印错误
|
||||
*/
|
||||
private fun onFailureMsg(msg: String = "", throwable: Throwable? = null, isAlwaysPrint: Boolean = false) {
|
||||
fun print() = loggerE(msg = "NoSuchMethod happend in [$hookClass] $msg [${hookInstance.tag}]", e = throwable)
|
||||
if (isAlwaysPrint) print()
|
||||
else Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (hookInstance.isNotIgnoredHookingFailure && !isUsingRemedyPlan) print()
|
||||
}.start()
|
||||
}
|
||||
override fun failure(throwable: Throwable?) = Result(isNoSuch = true, throwable)
|
||||
|
||||
/**
|
||||
* [Method] 重查找实现类
|
||||
@@ -158,7 +164,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
* @return [Result] 结果
|
||||
*/
|
||||
fun method(initiate: MethodFinder.() -> Unit) =
|
||||
Result().apply { remedyPlans.add(Pair(MethodFinder(hookInstance, hookClass).apply(initiate), this)) }
|
||||
Result().apply { remedyPlans.add(Pair(MethodFinder(hookInstance, classSet).apply(initiate), this)) }
|
||||
|
||||
/**
|
||||
* 开始重查找
|
||||
@@ -173,13 +179,14 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
remedyPlans.forEachIndexed { p, it ->
|
||||
runCatching {
|
||||
runBlocking {
|
||||
hookInstance.member = it.first.result
|
||||
setInstance(isBindToHooker, it.first.result)
|
||||
}.result {
|
||||
hookInstance.onHookLogMsg(msg = "Find Method [${hookInstance.member}] takes ${it}ms [${hookInstance.tag}]")
|
||||
onHookLogMsg(msg = "Find Method [${memberInstance}] takes ${it}ms [${hookTag}]")
|
||||
}
|
||||
isFindSuccess = true
|
||||
it.second.onFindCallback?.invoke(hookInstance.member as Method)
|
||||
hookInstance.onHookLogMsg(msg = "Method [${hookInstance.member}] trying ${p + 1} times success by RemedyPlan [${hookInstance.tag}]")
|
||||
it.second.onFindCallback?.invoke(memberInstance as Method)
|
||||
remedyPlansCallback?.invoke()
|
||||
onHookLogMsg(msg = "Method [${memberInstance}] trying ${p + 1} times success by RemedyPlan [${hookTag}]")
|
||||
return@run
|
||||
}.onFailure {
|
||||
lastError = it
|
||||
@@ -194,7 +201,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
)
|
||||
remedyPlans.clear()
|
||||
}
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,6 +238,29 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
*/
|
||||
fun result(initiate: Result.() -> Unit) = apply(initiate)
|
||||
|
||||
/**
|
||||
* 获得 [Method] 实例处理类
|
||||
*
|
||||
* - ❗在 [memberInstance] 结果为空时使用此方法将无法获得对象
|
||||
* - ❗若你设置了 [remedys] 请使用 [wait] 回调结果方法
|
||||
* @param instance 所在实例
|
||||
* @return [Instance]
|
||||
*/
|
||||
fun get(instance: Any? = null) = Instance(instance)
|
||||
|
||||
/**
|
||||
* 获得 [Method] 实例处理类
|
||||
*
|
||||
* - ❗若你设置了 [remedys] 必须使用此方法才能获得结果
|
||||
* - ❗若你没有设置 [remedys] 此方法将不会被回调
|
||||
* @param instance 所在实例
|
||||
* @param initiate 回调 [Instance]
|
||||
*/
|
||||
fun wait(instance: Any? = null, initiate: Instance.() -> Unit) {
|
||||
if (memberInstance != null) initiate(get(instance))
|
||||
else remedyPlansCallback = { initiate(get(instance)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建方法重查找功能
|
||||
*
|
||||
@@ -256,8 +286,42 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
fun onNoSuchMethod(initiate: (Throwable) -> Unit): Result {
|
||||
if (isNoSuch) initiate(e ?: Throwable())
|
||||
if (isNoSuch) initiate(e ?: Throwable("Initialization Error"))
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* [Method] 实例处理类
|
||||
* @param instance 当前 [Method] 所在类的实例对象
|
||||
*/
|
||||
inner class Instance(private val instance: Any?) {
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
* @param param 方法参数
|
||||
* @return [Any] or null
|
||||
*/
|
||||
private fun baseCall(vararg param: Any?) =
|
||||
if (param.isNotEmpty())
|
||||
(memberInstance as? Method?)?.invoke(instance, *param)
|
||||
else (memberInstance as? Method?)?.invoke(instance)
|
||||
|
||||
/**
|
||||
* 执行方法 - 不指定返回值类型
|
||||
* @param param 方法参数
|
||||
* @return [Any] or null
|
||||
*/
|
||||
fun call(vararg param: Any?) = baseCall(*param)
|
||||
|
||||
/**
|
||||
* 执行方法 - 指定 [T] 返回值类型
|
||||
* @param param 方法参数
|
||||
* @return [T] or null
|
||||
*/
|
||||
fun <T> invoke(vararg param: Any?) = baseCall(*param) as? T?
|
||||
|
||||
override fun toString() =
|
||||
"[${(memberInstance as? Method?)?.name ?: "<empty>"}] in [${instance?.javaClass?.name ?: "<empty>"}]"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
|
||||
* Copyright (C) 2019-2022 HighCapable
|
||||
* https://github.com/fankes/YukiHookAPI
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* This file is Created by fankes on 2022/2/18.
|
||||
*/
|
||||
package com.highcapable.yukihookapi.hook.core.finder.base
|
||||
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* 这是查找类功能的基本类实现
|
||||
* @param tag 当前查找类的标识
|
||||
* @param hookInstance 当前 Hook 实例
|
||||
* @param classSet 当前需要查找的 [Class] 实例
|
||||
*/
|
||||
abstract class BaseFinder(
|
||||
private val tag: String,
|
||||
open val hookInstance: YukiHookCreater.MemberHookCreater? = null,
|
||||
open val classSet: Class<*>? = null
|
||||
) {
|
||||
|
||||
/** 是否使用了重查找功能 */
|
||||
internal var isUsingRemedyPlan = false
|
||||
|
||||
/** 当前找到的 [Member] */
|
||||
internal var memberInstance: Member? = null
|
||||
|
||||
/**
|
||||
* 获取当前使用的 TAG
|
||||
* @return [String] 使用的 TAG
|
||||
*/
|
||||
internal val hookTag get() = hookInstance?.tag ?: "FinderMode"
|
||||
|
||||
/**
|
||||
* 判断是否没有设置 Hook 过程中的任何异常拦截
|
||||
* @return [Boolean] 没有设置任何异常拦截
|
||||
*/
|
||||
internal val isNotIgnoredHookingFailure get() = hookInstance?.isNotIgnoredHookingFailure ?: true
|
||||
|
||||
/**
|
||||
* 发生错误时输出日志
|
||||
* @param msg 消息日志
|
||||
* @param throwable 错误
|
||||
* @param isAlwaysPrint 忽略条件每次都打印错误
|
||||
*/
|
||||
internal fun onFailureMsg(msg: String = "", throwable: Throwable? = null, isAlwaysPrint: Boolean = false) {
|
||||
fun print() = loggerE(msg = "NoSuch$tag happend in [$classSet] $msg [${hookTag}]", e = throwable)
|
||||
if (isAlwaysPrint) print()
|
||||
else Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (isNotIgnoredHookingFailure && !isUsingRemedyPlan) print()
|
||||
}.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook 过程中开启了 [YukiHookAPI.Configs.isDebug] 输出调试信息
|
||||
* @param msg 调试日志内容
|
||||
*/
|
||||
internal fun onHookLogMsg(msg: String) {
|
||||
if (YukiHookAPI.Configs.isDebug) loggerI(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到结果
|
||||
*
|
||||
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
|
||||
* @param isBind 是否将结果设置到目标 [YukiHookCreater.MemberHookCreater]
|
||||
* @return [Any]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
abstract fun build(isBind: Boolean = false): Any
|
||||
|
||||
/**
|
||||
* 创建一个异常结果
|
||||
*
|
||||
* - ❗此功能交由方法体自动完成 - 你不应该手动调用此方法
|
||||
* @param throwable 异常
|
||||
* @return [Any]
|
||||
*/
|
||||
@DoNotUseMethod
|
||||
abstract fun failure(throwable: Throwable?): Any
|
||||
}
|
@@ -30,9 +30,10 @@
|
||||
package com.highcapable.yukihookapi.hook.factory
|
||||
|
||||
import com.highcapable.yukihookapi.hook.bean.HookClass
|
||||
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.utils.ReflectionUtils
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* [Class] 转换为 [HookClass]
|
||||
@@ -86,53 +87,46 @@ fun String.hasClass(loader: ClassLoader?) = try {
|
||||
*/
|
||||
fun Class<*>.hasMethod(name: String, vararg paramType: Class<*>, returnType: Class<*>? = null): Boolean =
|
||||
try {
|
||||
method(name, *paramType, returnType = returnType)
|
||||
if (paramType.isNotEmpty())
|
||||
ReflectionUtils.findMethodBestMatch(this, returnType, name, *paramType)
|
||||
else ReflectionUtils.findMethodNoParam(this, returnType, name)
|
||||
true
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并得到方法
|
||||
* @param name 方法名称
|
||||
* 查找构造方法是否存在
|
||||
* @param paramType params
|
||||
* @param returnType 返回类型 - 不填默认模糊
|
||||
* @return [Method] or null
|
||||
* @throws NoSuchMethodError
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
fun Class<*>.method(name: String, vararg paramType: Class<*>, returnType: Class<*>? = null): Method? =
|
||||
if (paramType.isNotEmpty())
|
||||
ReflectionUtils.findMethodBestMatch(this, returnType, name, *paramType)
|
||||
else ReflectionUtils.findMethodNoParam(this, returnType, name)
|
||||
fun Class<*>.hasConstructor(vararg paramType: Class<*>): Boolean =
|
||||
try {
|
||||
if (paramType.isNotEmpty())
|
||||
ReflectionUtils.findConstructorExact(this, *paramType)
|
||||
else ReflectionUtils.findConstructorExact(this)
|
||||
true
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并得到变量
|
||||
* @param initiate 查找方法体
|
||||
* @return [FieldFinder.Result]
|
||||
*/
|
||||
fun Class<*>.field(initiate: FieldFinder.() -> Unit) = FieldFinder(classSet = this).apply(initiate).build()
|
||||
|
||||
/**
|
||||
* 查找并得到方法
|
||||
* @param initiate 查找方法体
|
||||
* @return [MethodFinder.Result]
|
||||
*/
|
||||
fun Class<*>.method(initiate: MethodFinder.() -> Unit) = MethodFinder(classSet = this).apply(initiate).build()
|
||||
|
||||
/**
|
||||
* 查找并得到构造类
|
||||
* @param paramType params
|
||||
* @return [Constructor] or null
|
||||
* @throws NoSuchMethodError
|
||||
* @param initiate 查找方法体
|
||||
* @return [ConstructorFinder.Result]
|
||||
*/
|
||||
fun Class<*>.constructor(vararg paramType: Class<*>): Constructor<out Any>? =
|
||||
if (paramType.isNotEmpty())
|
||||
ReflectionUtils.findConstructorExact(this, *paramType)
|
||||
else ReflectionUtils.findConstructorExact(this)
|
||||
|
||||
/**
|
||||
* 执行静态方法
|
||||
* @param param 方法参数
|
||||
* @return [T] or null
|
||||
*/
|
||||
inline fun <reified T> Method.callStatic(vararg param: Any?) =
|
||||
if (param.isNotEmpty())
|
||||
invoke(null, *param) as? T?
|
||||
else invoke(null) as? T?
|
||||
|
||||
/**
|
||||
* 执行方法
|
||||
* @param instance 目标对象
|
||||
* @param param 方法参数
|
||||
* @return [T] or null
|
||||
*/
|
||||
inline fun <reified T> Method.call(instance: Any?, vararg param: Any?) =
|
||||
if (param.isNotEmpty())
|
||||
invoke(instance, *param) as? T?
|
||||
else invoke(instance) as? T?
|
||||
fun Class<*>.constructor(initiate: ConstructorFinder.() -> Unit) = ConstructorFinder(classSet = this).apply(initiate).build()
|
||||
|
@@ -192,10 +192,23 @@ open class PackageParam(private var wrapper: PackageParamWrapper? = null) {
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
*
|
||||
* - ❗为防止任何字符串都被当做 [Class] 进行 Hook - 推荐优先使用 [findClass]
|
||||
* @param initiate 方法体
|
||||
*/
|
||||
fun Class<*>.hook(initiate: YukiHookCreater.() -> Unit) =
|
||||
YukiHookCreater(packageParam = thisParam, hookClass = hookClass.bind()).apply(initiate).hook()
|
||||
fun String.hook(initiate: YukiHookCreater.() -> Unit) = findClass(name = this).hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
* @param initiate 方法体
|
||||
*/
|
||||
fun Class<*>.hook(initiate: YukiHookCreater.() -> Unit) = hookClass.hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
* @param initiate 方法体
|
||||
*/
|
||||
fun VariousClass.hook(initiate: YukiHookCreater.() -> Unit) = hookClass.hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
@@ -204,13 +217,6 @@ open class PackageParam(private var wrapper: PackageParamWrapper? = null) {
|
||||
fun HookClass.hook(initiate: YukiHookCreater.() -> Unit) =
|
||||
YukiHookCreater(packageParam = thisParam, hookClass = bind()).apply(initiate).hook()
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
* @param initiate 方法体
|
||||
*/
|
||||
fun VariousClass.hook(initiate: YukiHookCreater.() -> Unit) =
|
||||
YukiHookCreater(packageParam = thisParam, hookClass = hookClass).apply(initiate).hook()
|
||||
|
||||
/**
|
||||
* [VariousClass] 转换为 [HookClass] 并绑定到 [appClassLoader]
|
||||
* @return [HookClass]
|
||||
|
Reference in New Issue
Block a user