This commit is contained in:
2022-02-08 02:30:20 +08:00
parent 8139f15bea
commit 738ffce6e6
11 changed files with 156 additions and 94 deletions

View File

@@ -36,8 +36,8 @@ import com.highcapable.yukihookapi.YukiHookAPI.encase
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.processName
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
import de.robv.android.xposed.callbacks.XC_LoadPackage
@@ -100,7 +100,7 @@ object YukiHookAPI {
/**
* 装载 Xposed API 回调
*
* - 装载代码将自动生成 - 你不应该手动使用此方法装载 Xposed 模块事件
* - 装载代码将自动生成 - 你不应该手动使用此方法装载 Xposed 模块事件
* @param lpparam Xposed [XC_LoadPackage.LoadPackageParam]
*/
@DoNotUseMethod

View File

@@ -45,7 +45,7 @@ package com.highcapable.yukihookapi.annotation
)
@Retention(AnnotationRetention.BINARY)
/**
* - 警告方法外部调用声明
* - 警告方法外部调用声明
* 此方法除继承和接口外不应该在这里被调用
* 如果调用此方法可能会出现错误或 APP 发生异常
*/

View File

@@ -45,7 +45,7 @@ package com.highcapable.yukihookapi.annotation
)
@Retention(AnnotationRetention.BINARY)
/**
* - 警告方法外部调用声明
* - 警告方法外部调用声明
* 此方法除继承和接口外不应该在这里被调用
* 如果调用此方法可能会出现错误或 APP 发生异常
*/

View File

@@ -35,7 +35,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
/**
* 标识 YukiHook 注入 Xposed 入口的类注释
*
* - 你的项目 source 目录必须为 ../src/main/ 后方内容根据你自行喜好定义即可 - 否则编译会报错
* - 你的项目 source 目录必须为 ../src/main/ 后方内容根据你自行喜好定义即可 - 否则编译会报错
*
* - 你的 Hook 入口类(HookEntryClass) 需要按照此格式创建 --> 你的模块APP包名/hook/...可允许子包名存在.../你的入口类
*
@@ -49,7 +49,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
*
* - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.Configs.modulePackageName] 填写模块包名即可 - 但不按照规则定义包名你将会收到编译警告
*
* - 最后这一点很重要:请不要随意修改项目 ../src/main/assets/xposed_init 中的内容 - 否则可能会导致模块装载发生错误
* - 最后这一点很重要:请不要随意修改项目 ../src/main/assets/xposed_init 中的内容 - 否则可能会导致模块装载发生错误
*
* 你必须将被注释的类继承于 [YukiHookXposedInitProxy] 接口实现 [YukiHookXposedInitProxy.onHook] 方法 - 否则编译会报错
*

View File

@@ -49,10 +49,15 @@ import java.lang.reflect.Member
*
* 这是一个 API 对接类 - 实现原生对接 [XposedBridge]
* @param packageParam 需要传入 [PackageParam] 实现方法调用
* @param hookClass 要 Hook 的 [Class]
* @param hookClass 要 Hook 的 [Class] - 必须已使用当前 Hook APP 的 [ClassLoader] 装载
*/
class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Class<*>) {
/**
* Hook 全部方法的标识
*/
enum class HookAllMembers { HOOK_ALL_METHODS, HOOK_ALL_CONSTRUCTORS, HOOK_NONE }
/** 设置要 Hook 的方法、构造类 */
private var hookMembers = HashMap<String, MemberHookCreater>()
@@ -69,7 +74,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
/**
* Hook 执行入口
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* @throws IllegalStateException 如果必要参数没有被设置
*/
@DoNotUseMethod
@@ -110,6 +115,12 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
/** 标识是否已经设置了要 Hook 的 [member] */
private var isHookMemberSetup = false
/** 是否 Hook 全部方法以及类型 */
private var hookAllMembers = HookAllMembers.HOOK_NONE
/** 全部方法的名称 */
private var allMethodsName = ""
/**
* 手动指定要 Hook 的方法、构造类
*
@@ -117,6 +128,32 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
*/
var member: Member? = null
/**
* Hook [hookClass] 中指定 [name] 的全部方法
*
* - ⚡警告:无法准确处理每个方法的返回值和 param - 建议使用 [method] 对每个方法单独 Hook
*
* - ⚡如果 [hookClass] 中没有方法可能会发生错误
* @param name 方法名称
*/
fun allMethods(name: String) {
allMethodsName = name
hookAllMembers = HookAllMembers.HOOK_ALL_METHODS
isHookMemberSetup = true
}
/**
* Hook [hookClass] 中的全部构造方法
*
* - ⚡警告:无法准确处理每个构造方法的 param - 建议使用 [constructor] 对每个构造方法单独 Hook
*
* - ⚡如果 [hookClass] 中没有构造方法可能会发生错误
*/
fun allConstructors() {
hookAllMembers = HookAllMembers.HOOK_ALL_CONSTRUCTORS
isHookMemberSetup = true
}
/**
* 查找需要 Hook 的方法
*
@@ -125,6 +162,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
* @return [MethodFinder.Result]
*/
fun method(initiate: MethodFinder.() -> Unit): MethodFinder.Result {
hookAllMembers = HookAllMembers.HOOK_NONE
isHookMemberSetup = true
return MethodFinder(hookInstance = this, hookClass).apply(initiate).build()
}
@@ -137,6 +175,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
* @return [ConstructorFinder.Result]
*/
fun constructor(initiate: ConstructorFinder.() -> Unit): ConstructorFinder.Result {
hookAllMembers = HookAllMembers.HOOK_NONE
isHookMemberSetup = true
return ConstructorFinder(hookInstance = this, hookClass).apply(initiate).build()
}
@@ -243,7 +282,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
/**
* Hook 创建入口
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [Result]
*/
@DoNotUseMethod
@@ -252,81 +291,103 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
/**
* Hook 执行入口
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
*/
@DoNotUseMethod
fun hook() {
if (member != null)
member.also { member ->
runCatching {
if (isReplaceHookMode)
XposedBridge.hookMethod(member, object : XC_MethodReplacement() {
override fun replaceHookedMethod(baseParam: MethodHookParam?): Any? {
if (baseParam == null) return null
return HookParam(baseParam).let { param ->
try {
if (replaceHookCallback != null)
onHookLogMsg(msg = "Replace Hook Member [${member}] done [$tag]")
replaceHookCallback?.invoke(param)
} catch (e: Throwable) {
onConductFailureCallback?.invoke(param, e)
onAllFailureCallback?.invoke(e)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(e)
null
}
}
}
})
else
XposedBridge.hookMethod(member, object : XC_MethodHook() {
override fun beforeHookedMethod(baseParam: MethodHookParam?) {
if (baseParam == null) return
HookParam(baseParam).also { param ->
runCatching {
beforeHookCallback?.invoke(param)
if (beforeHookCallback != null)
onHookLogMsg(msg = "Before Hook Member [${member}] done [$tag]")
}.onFailure {
onConductFailureCallback?.invoke(param, it)
onAllFailureCallback?.invoke(it)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(it)
}
}
}
override fun afterHookedMethod(baseParam: MethodHookParam?) {
if (baseParam == null) return
HookParam(baseParam).also { param ->
runCatching {
afterHookCallback?.invoke(param)
if (afterHookCallback != null)
onHookLogMsg(msg = "After Hook Member [${member}] done [$tag]")
}.onFailure {
onConductFailureCallback?.invoke(param, it)
onAllFailureCallback?.invoke(it)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(it)
}
}
}
})
}.onFailure {
onHookingFailureCallback?.invoke(it)
onAllFailureCallback?.invoke(it)
if (onHookingFailureCallback == null && onAllFailureCallback == null) onHookFailureMsg(it)
/** 定义替换回调方法体 */
val replaceMent = object : XC_MethodReplacement() {
override fun replaceHookedMethod(baseParam: MethodHookParam?): Any? {
if (baseParam == null) return null
return HookParam(baseParam).let { param ->
try {
if (replaceHookCallback != null)
onHookLogMsg(msg = "Replace Hook Member [${member}] done [$tag]")
replaceHookCallback?.invoke(param)
} catch (e: Throwable) {
onConductFailureCallback?.invoke(param, e)
onAllFailureCallback?.invoke(e)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(e)
null
}
}
}
else {
onHookingFailureCallback?.invoke(Throwable())
onAllFailureCallback?.invoke(Throwable())
}
/** 定义前后 Hook 回调方法体 */
val beforeAfterHook = object : XC_MethodHook() {
override fun beforeHookedMethod(baseParam: MethodHookParam?) {
if (baseParam == null) return
HookParam(baseParam).also { param ->
runCatching {
beforeHookCallback?.invoke(param)
if (beforeHookCallback != null)
onHookLogMsg(msg = "Before Hook Member [${member}] done [$tag]")
}.onFailure {
onConductFailureCallback?.invoke(param, it)
onAllFailureCallback?.invoke(it)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(it)
}
}
}
override fun afterHookedMethod(baseParam: MethodHookParam?) {
if (baseParam == null) return
HookParam(baseParam).also { param ->
runCatching {
afterHookCallback?.invoke(param)
if (afterHookCallback != null)
onHookLogMsg(msg = "After Hook Member [${member}] done [$tag]")
}.onFailure {
onConductFailureCallback?.invoke(param, it)
onAllFailureCallback?.invoke(it)
if (onConductFailureCallback == null && onAllFailureCallback == null)
onHookFailureMsg(it)
}
}
}
}
if (hookAllMembers == HookAllMembers.HOOK_NONE)
if (member != null)
member.also { member ->
runCatching {
if (isReplaceHookMode)
XposedBridge.hookMethod(member, replaceMent)
else XposedBridge.hookMethod(member, beforeAfterHook)
}.onFailure {
onHookingFailureCallback?.invoke(it)
onAllFailureCallback?.invoke(it)
if (onHookingFailureCallback == null && onAllFailureCallback == null) onHookFailureMsg(it)
}
}
else {
onHookingFailureCallback?.invoke(Throwable())
onAllFailureCallback?.invoke(Throwable())
if (onHookingFailureCallback == null && onAllFailureCallback == null)
loggerE(
msg = if (isHookMemberSetup)
"Hooked Member with a finding error in Class [$hookClass] [$tag]"
else "Hooked Member cannot be non-null in Class [$hookClass] [$tag]"
)
}
else runCatching {
when (hookAllMembers) {
HookAllMembers.HOOK_ALL_METHODS ->
if (isReplaceHookMode)
XposedBridge.hookAllMethods(hookClass, allMethodsName, replaceMent)
else XposedBridge.hookAllMethods(hookClass, allMethodsName, beforeAfterHook)
HookAllMembers.HOOK_ALL_CONSTRUCTORS ->
if (isReplaceHookMode)
XposedBridge.hookAllConstructors(hookClass, replaceMent)
else XposedBridge.hookAllConstructors(hookClass, beforeAfterHook)
else -> error("Hooked got a no error possible")
}
}.onFailure {
onAllFailureCallback?.invoke(it)
if (onHookingFailureCallback == null && onAllFailureCallback == null)
loggerE(
msg = if (isHookMemberSetup)
"Hooked Member with a finding error in Class [$hookClass] [$tag]"
else "Hooked Member cannot be non-null in Class [$hookClass] [$tag]"
)
loggerE(msg = "Hooked All Members with an error in Class [$hookClass] [$tag]")
}
}

View File

@@ -52,9 +52,9 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
/**
* [Constructor] 参数
*
* - 无参 [Constructor] 不要使用此方法
* - 无参 [Constructor] 不要使用此方法
*
* - 有参 [Constructor] 必须使用此方法设定参数
* - 有参 [Constructor] 必须使用此方法设定参数
* @param param 参数数组
*/
fun param(vararg param: Class<*>) {
@@ -75,7 +75,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
/**
* 得到构造方法结果
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [Result]
*/
@DoNotUseMethod
@@ -123,7 +123,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
/**
* 开始重查找
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
*/
@DoNotUseMethod
internal fun build() {

View File

@@ -51,21 +51,21 @@ class FieldFinder(private val hookInstance: YukiHookCreater.MemberHookCreater, p
/**
* [Field] 名称
*
* - 必须设置
* - 必须设置
*/
var name = ""
/**
* [Field] 类型
*
* - 必须设置
* - 必须设置
*/
var type: Class<*>? = null
/**
* 得到变量处理结果
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [Result]
* @throws IllegalStateException 如果 [name] 没有被设置
*/

View File

@@ -52,7 +52,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
/**
* [Method] 名称
*
* - 必须设置
* - 必须设置
*/
var name = ""
@@ -66,9 +66,9 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
/**
* [Method] 参数
*
* - 无参 [Method] 不要使用此方法
* - 无参 [Method] 不要使用此方法
*
* - 有参 [Method] 必须使用此方法设定参数
* - 有参 [Method] 必须使用此方法设定参数
* @param param 参数数组
*/
fun param(vararg param: Class<*>) {
@@ -90,7 +90,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
/**
* 得到方法结果
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* @return [Result]
*/
@DoNotUseMethod
@@ -141,7 +141,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
/**
* 开始重查找
*
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
* - 此功能交由方法体自动完成 - 你不应该手动调用此方法
*/
@DoNotUseMethod
internal fun build() {

View File

@@ -73,7 +73,7 @@ abstract class YukiBaseHooker : PackageParam() {
/**
* 赋值并克隆一个 [PackageParam]
*
* - 此方法为私有功能性 API - 你不应该手动调用此方法
* - 此方法为私有功能性 API - 你不应该手动调用此方法
* @param packageParam 需要使用的 [PackageParam]
*/
@DoNotUseMethod

View File

@@ -77,8 +77,9 @@ open class PackageParam(private var baseParam: PackageParamWrapper? = null) {
/**
* 赋值并克隆另一个 [PackageParam]
*
* - ⚡此方法为私有功能性 API - 你不应该手动调用此方法
* @param another 另一个 [PackageParam]
* - 此方法为私有功能性 API - 你不应该手动调用此方法
*/
@DoNotUseMethod
internal fun baseAssignInstance(another: PackageParam) {
@@ -105,7 +106,7 @@ open class PackageParam(private var baseParam: PackageParamWrapper? = null) {
/**
* 将目标 [Class] 绑定到 [appClassLoader]
*
* - 请注意未绑定到 [appClassLoader] 的 [Class] 不能被装载 - 调用 [hook] 方法会自动绑定
* - 请注意未绑定到 [appClassLoader] 的 [Class] 不能被装载 - 调用 [hook] 方法会自动绑定
* @return [Class]
* @throws NoClassDefFoundError 如果找不到类会报错
*/

View File

@@ -36,7 +36,7 @@ import com.highcapable.yukihookapi.hook.factory.encase
/**
* YukiHook 的 Xposed 装载 API 调用接口
*
* - 请在此类上添加注释 [InjectYukiHookWithXposed] 标记模块 Hook 入口
* - 请在此类上添加注释 [InjectYukiHookWithXposed] 标记模块 Hook 入口
*
* Hook 开始时将自动调用 [onHook] 方法
*