mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Added any type finding function
This commit is contained in:
@@ -27,12 +27,35 @@
|
||||
*/
|
||||
package com.highcapable.yukihookapi.hook.bean
|
||||
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
|
||||
/**
|
||||
* 这是一个不确定性 [Class] 类名装载器
|
||||
* @param name 可指定多个类名 - 将会自动匹配存在的第一个类名
|
||||
*/
|
||||
class VariousClass(vararg var name: String) {
|
||||
|
||||
/**
|
||||
* 获取匹配的实体类
|
||||
*
|
||||
* - 使用当前 [loader] 装载目标 [Class]
|
||||
* @param loader 当前 [ClassLoader] - 若留空使用默认 [ClassLoader]
|
||||
* @return [Class]
|
||||
* @throws IllegalStateException 如果任何 [Class] 都没有匹配到
|
||||
*/
|
||||
fun get(loader: ClassLoader? = null): Class<*> {
|
||||
var finalClass: Class<*>? = null
|
||||
if (name.isNotEmpty()) run {
|
||||
name.forEach {
|
||||
runCatching {
|
||||
finalClass = classOf(it, loader)
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
return finalClass ?: error("VariousClass match failed of those $this")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
var result = ""
|
||||
return if (name.isNotEmpty()) {
|
||||
|
@@ -30,10 +30,12 @@
|
||||
package com.highcapable.yukihookapi.hook.core.finder
|
||||
|
||||
import com.highcapable.yukihookapi.annotation.YukiPrivateApi
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionTool
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
import java.lang.reflect.Constructor
|
||||
@@ -93,12 +95,12 @@ class ConstructorFinder(
|
||||
* - ❗有参 [Constructor] 必须使用此方法设定参数或使用 [paramCount] 指定个数
|
||||
*
|
||||
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
|
||||
* @param paramType 参数类型数组
|
||||
* @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun param(vararg paramType: Class<*>): IndexTypeCondition {
|
||||
fun param(vararg paramType: Any): IndexTypeCondition {
|
||||
if (paramType.isEmpty()) error("paramTypes is empty, please delete param() method")
|
||||
paramTypes = paramType
|
||||
paramTypes = ArrayList<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray()
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@ package com.highcapable.yukihookapi.hook.core.finder
|
||||
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.annotation.YukiPrivateApi
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
|
||||
@@ -63,9 +64,25 @@ class FieldFinder(
|
||||
/**
|
||||
* [Field] 类型
|
||||
*
|
||||
* - ❗只能是 [Class]、[String]、[VariousClass]
|
||||
*
|
||||
* - 可不填写类型 - 默认模糊查找并取第一个匹配的 [Field]
|
||||
*/
|
||||
var type: Class<*>? = null
|
||||
var type: Any? = null
|
||||
|
||||
/**
|
||||
* [Field] 筛选条件
|
||||
*
|
||||
* 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Field]
|
||||
*
|
||||
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
|
||||
* @param initiate 方法体
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
|
||||
modifiers = ModifierRules().apply(initiate)
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
|
||||
/**
|
||||
* 顺序筛选字节码的下标
|
||||
@@ -93,28 +110,14 @@ class FieldFinder(
|
||||
* - 可不填写类型 - 默认模糊查找并取第一个匹配的 [Field]
|
||||
*
|
||||
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
|
||||
* @param value 类型
|
||||
* @param value 类型 - ❗只能是 [Class]、[String]、[VariousClass]
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun type(value: Class<*>): IndexTypeCondition {
|
||||
fun type(value: Any): IndexTypeCondition {
|
||||
type = value
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
|
||||
/**
|
||||
* [Field] 筛选条件
|
||||
*
|
||||
* 可不设置筛选条件 - 默认模糊查找并取第一个匹配的 [Field]
|
||||
*
|
||||
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
|
||||
* @param initiate 方法体
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun modifiers(initiate: ModifierRules.() -> Unit): IndexTypeCondition {
|
||||
modifiers = ModifierRules().apply(initiate)
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到变量处理结果
|
||||
*
|
||||
@@ -127,7 +130,7 @@ class FieldFinder(
|
||||
override fun build(isBind: Boolean) = try {
|
||||
if (classSet != null) {
|
||||
runBlocking {
|
||||
memberInstance = ReflectionTool.findField(classSet, orderIndex, matchIndex, name, modifiers, type)
|
||||
memberInstance = ReflectionTool.findField(classSet, orderIndex, matchIndex, name, modifiers, type.compat())
|
||||
}.result { onHookLogMsg(msg = "Find Field [${memberInstance}] takes ${it}ms [${hookTag}]") }
|
||||
Result()
|
||||
} else Result(isNoSuch = true, Throwable("classSet is null"))
|
||||
@@ -135,7 +138,7 @@ class FieldFinder(
|
||||
Thread {
|
||||
/** 延迟使得方法取到返回值 */
|
||||
SystemClock.sleep(1)
|
||||
onFailureMsg(msg = "NoSuchField happend in [$classSet] [${hookTag}]", throwable = e)
|
||||
onFailureMsg(throwable = e)
|
||||
}.start()
|
||||
Result(isNoSuch = true, e)
|
||||
}
|
||||
|
@@ -30,10 +30,12 @@
|
||||
package com.highcapable.yukihookapi.hook.core.finder
|
||||
|
||||
import com.highcapable.yukihookapi.annotation.YukiPrivateApi
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionTool
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
import java.lang.reflect.Method
|
||||
@@ -81,9 +83,11 @@ class MethodFinder(
|
||||
/**
|
||||
* [Method] 返回值
|
||||
*
|
||||
* 可不填写返回值 - 默认模糊查找并取第一个匹配的 [Method]
|
||||
* - ❗只能是 [Class]、[String]、[VariousClass]
|
||||
*
|
||||
* - 可不填写返回值 - 默认模糊查找并取第一个匹配的 [Method]
|
||||
*/
|
||||
var returnType: Class<*>? = null
|
||||
var returnType: Any? = null
|
||||
|
||||
/**
|
||||
* [Method] 筛选条件
|
||||
@@ -109,12 +113,12 @@ class MethodFinder(
|
||||
* - ❗有参 [Method] 必须使用此方法设定参数或使用 [paramCount] 指定个数
|
||||
*
|
||||
* - ❗存在多个 [BaseFinder.IndexTypeCondition] 时除了 [order] 只会生效最后一个
|
||||
* @param paramType 参数类型数组
|
||||
* @param paramType 参数类型数组 - ❗只能是 [Class]、[String]、[VariousClass]
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun param(vararg paramType: Class<*>): IndexTypeCondition {
|
||||
fun param(vararg paramType: Any): IndexTypeCondition {
|
||||
if (paramType.isEmpty()) error("paramTypes is empty, please delete param() method")
|
||||
paramTypes = paramType
|
||||
paramTypes = ArrayList<Class<*>>().apply { paramType.forEach { add(it.compat() ?: UndefinedType) } }.toTypedArray()
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
|
||||
@@ -163,7 +167,7 @@ class MethodFinder(
|
||||
* @param value 个数
|
||||
* @return [BaseFinder.IndexTypeCondition]
|
||||
*/
|
||||
fun returnType(value: Class<*>): IndexTypeCondition {
|
||||
fun returnType(value: Any): IndexTypeCondition {
|
||||
returnType = value
|
||||
return IndexTypeCondition(IndexConfigType.MATCH)
|
||||
}
|
||||
@@ -173,7 +177,8 @@ class MethodFinder(
|
||||
* @return [Method]
|
||||
* @throws NoSuchMethodError 如果找不到方法
|
||||
*/
|
||||
private val result get() = ReflectionTool.findMethod(classSet, orderIndex, matchIndex, name, modifiers, returnType, paramCount, paramTypes)
|
||||
private val result
|
||||
get() = ReflectionTool.findMethod(classSet, orderIndex, matchIndex, name, modifiers, returnType.compat(), paramCount, paramTypes)
|
||||
|
||||
/**
|
||||
* 设置实例
|
||||
|
@@ -30,9 +30,12 @@ package com.highcapable.yukihookapi.hook.core.finder.base
|
||||
import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.annotation.YukiPrivateApi
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerI
|
||||
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
|
||||
import java.lang.reflect.Member
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -133,6 +136,18 @@ abstract class BaseFinder(
|
||||
*/
|
||||
internal val isNotIgnoredNoSuchMemberFailure get() = hookInstance?.isNotIgnoredNoSuchMemberFailure ?: true
|
||||
|
||||
/**
|
||||
* 将目标类型转换为可识别的兼容类型
|
||||
* @return [Class] or null
|
||||
*/
|
||||
internal fun Any?.compat() = when (this) {
|
||||
null -> null
|
||||
is Class<*> -> this
|
||||
is String -> runCatching { classOf(name = this, classSet!!.classLoader) }.getOrNull() ?: UndefinedType
|
||||
is VariousClass -> runCatching { get(classSet!!.classLoader) }.getOrNull() ?: UndefinedType
|
||||
else -> error("$tag match type \"$javaClass\" not allowed")
|
||||
} as Class<*>?
|
||||
|
||||
/**
|
||||
* 发生错误时输出日志
|
||||
* @param msg 消息日志
|
||||
|
@@ -176,19 +176,7 @@ open class PackageParam(private var wrapper: PackageParamWrapper? = null) {
|
||||
* @return [Class]
|
||||
* @throws IllegalStateException 如果任何 [Class] 都没有匹配到
|
||||
*/
|
||||
val VariousClass.clazz
|
||||
get() :Class<*> {
|
||||
var finalClass: Class<*>? = null
|
||||
if (name.isNotEmpty()) run {
|
||||
name.forEach {
|
||||
runCatching {
|
||||
finalClass = it.clazz
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
return finalClass ?: error("VariousClass match failed of those $this")
|
||||
}
|
||||
val VariousClass.clazz get() = get(appClassLoader)
|
||||
|
||||
/**
|
||||
* 通过字符串查找类是否存在
|
||||
@@ -214,9 +202,9 @@ open class PackageParam(private var wrapper: PackageParamWrapper? = null) {
|
||||
*
|
||||
* 使用此方法查询将会取 [name] 其中命中存在的第一个 [Class] 作为结果
|
||||
* @param name 可填入多个类名 - 自动匹配
|
||||
* @return [HookClass]
|
||||
* @return [VariousClass]
|
||||
*/
|
||||
fun findClass(vararg name: String) = VariousClass(*name).hookClass
|
||||
fun findClass(vararg name: String) = VariousClass(*name)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
@@ -245,7 +233,7 @@ open class PackageParam(private var wrapper: PackageParamWrapper? = null) {
|
||||
* @return [YukiHookCreater.Result]
|
||||
*/
|
||||
fun VariousClass.hook(isUseAppClassLoader: Boolean = true, initiate: YukiHookCreater.() -> Unit) =
|
||||
hookClass.hook(isUseAppClassLoader, initiate)
|
||||
get(if (isUseAppClassLoader) appClassLoader else null).hookClass.hook(isUseAppClassLoader, initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造类
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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/4/3.
|
||||
*/
|
||||
package com.highcapable.yukihookapi.hook.type.defined
|
||||
|
||||
/** 未定义类型实例 */
|
||||
internal class UndefinedClass
|
||||
|
||||
/**
|
||||
* 未定义类型
|
||||
* @return [UndefinedClass]
|
||||
*/
|
||||
internal val UndefinedType get() = UndefinedClass::class.java
|
@@ -29,6 +29,7 @@ package com.highcapable.yukihookapi.hook.utils
|
||||
|
||||
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
|
||||
import com.highcapable.yukihookapi.hook.store.MemberCacheStore
|
||||
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
|
||||
import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
@@ -52,7 +53,7 @@ internal object ReflectionTool {
|
||||
* @param modifiers 变量描述
|
||||
* @param type 变量类型
|
||||
* @return [Field]
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [type] 目标类不存在
|
||||
* @throws NoSuchFieldError 如果找不到变量
|
||||
*/
|
||||
internal fun findField(
|
||||
@@ -63,6 +64,7 @@ internal object ReflectionTool {
|
||||
modifiers: ModifierRules?,
|
||||
type: Class<*>?
|
||||
): Field {
|
||||
if (type == UndefinedType) error("Field match type class is not found")
|
||||
if (orderIndex == null && matchIndex == null && name.isBlank() && modifiers == null && type == null)
|
||||
error("You must set a condition when finding a Field")
|
||||
val hashCode = ("[$orderIndex][$matchIndex][$name][$type][$modifiers][$classSet]").hashCode()
|
||||
@@ -155,7 +157,7 @@ internal object ReflectionTool {
|
||||
* @param paramCount 方法参数个数
|
||||
* @param paramTypes 方法参数类型
|
||||
* @return [Method]
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 以及 [returnType] 目标类不存在
|
||||
* @throws NoSuchMethodError 如果找不到方法
|
||||
*/
|
||||
internal fun findMethod(
|
||||
@@ -168,6 +170,9 @@ internal object ReflectionTool {
|
||||
paramCount: Int,
|
||||
paramTypes: Array<out Class<*>>?
|
||||
): Method {
|
||||
if (returnType == UndefinedType) error("Method match returnType class is not found")
|
||||
paramTypes?.takeIf { it.isNotEmpty() }
|
||||
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Method match paramType[$p] class is not found") }
|
||||
if (orderIndex == null && matchIndex == null && name.isBlank() && modifiers == null && paramCount < 0 && paramTypes == null && returnType == null)
|
||||
error("You must set a condition when finding a Method")
|
||||
val hashCode =
|
||||
@@ -288,7 +293,7 @@ internal object ReflectionTool {
|
||||
* @param paramCount 构造方法参数个数
|
||||
* @param paramTypes 构造方法参数类型
|
||||
* @return [Constructor]
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件
|
||||
* @throws IllegalStateException 如果 [classSet] 为 null 或未设置任何条件或 [paramTypes] 目标类不存在
|
||||
* @throws NoSuchMethodError 如果找不到构造方法
|
||||
*/
|
||||
internal fun findConstructor(
|
||||
@@ -299,6 +304,8 @@ internal object ReflectionTool {
|
||||
paramCount: Int,
|
||||
paramTypes: Array<out Class<*>>?
|
||||
): Constructor<*> {
|
||||
paramTypes?.takeIf { it.isNotEmpty() }
|
||||
?.forEachIndexed { p, it -> if (it == UndefinedType) error("Constructor match paramType[$p] class is not found") }
|
||||
if (orderIndex == null && matchIndex == null && paramCount < 0 && paramTypes == null && modifiers == null)
|
||||
error("You must set a condition when finding a Constructor")
|
||||
val hashCode = ("[$orderIndex][$matchIndex][$paramCount][${paramTypes.typeOfString()}][$modifiers][$classSet]").hashCode()
|
||||
|
Reference in New Issue
Block a user