从其它 Hook API 迁移

此文档可以帮助你快速从你熟悉的 Hook API 迁移到 YukiHookAPI 来熟悉对 YukiHookAPI 的相关写法。

Rovo89 Xposed API

若你熟悉 Rovo89 Xposed API在新窗口中打开,你可以参考下方的相同点将自己的 API 快速迁移到 YukiHookAPI

迁移 Hook 入口点

XC_LoadPackage.LoadPackageParam 迁移至 PackageParam

YukiHookAPIPackageParam 实现了 lambda 方法体 this 用法,在 encase 方法体内即可全局得到 PackageParam 对象。

API 功能差异对比如下

override fun onHook() = encase {
    // 得到当前 Hook 的包名
    packageName
    // 得到当前 Hook 的 ApplicationInfo
    appInfo
    // 得到系统上下文对象
    systemContext
    // 得到宿主 Application 生命周期
    appContext
    // Hook 指定的 APP
    loadApp(name = "com.demo.test") {
        // Member Hook
        "com.demo.test.TestClass".toClass()
            .method {
                name = "test"
                param(BooleanType)
            }.hook {
                after {
                    // ...
                }
            }
        // Resources Hook (固定用法)
        resources().hook {
            injectResource {
                conditions {
                    name = "ic_launcher"
                    mipmap()
                }
                replaceToModuleResource(R.mipmap.ic_launcher)
            }
        }
    }
}
private lateinit var moduleResources: XModuleResources

override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
    moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
}

override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
    // 得到当前 Hook 的包名
    lpparam.packageName
    // 得到当前 Hook 的 ApplicationInfo
    lpparam.applicationInfo
    // 得到系统上下文对象
    // 在 Rovo89 Xposed API 中没有现成的调用方法,你需要自行反射 ActivityThread 来实现
    // 得到宿主 Application 生命周期
    AndroidAppHelper.currentApplication()
    // Class Hook
    if(lpparam.packageName == "com.demo.test")
        XposedHelpers.findAndHookMethod(
            "com.demo.test.TestClass", lpparam.classLoader,
            "test", Boolean::class.java,
            object : XC_MethodHook() {
                override fun afterHookedMethod(param: MethodHookParam) {
                    // ...
                }
            }
        )
}

override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
    // 得到当前 Hook 的包名
    resparam.packageName
    // Resources Hook
    resparam.res.setReplacement(
        "com.demo.test", "mipmap","ic_launcher",
        moduleResources.fwd(R.mipmap.ic_launcher)
    )
}

迁移 Hook 方法体

XC_MethodHook.MethodHookParam 迁移至 HookParam

Before/After Hook

YukiHookAPI 同样对 HookParam 实现了 lambda 方法体 this 用法,在 beforeafter 等方法体内即可全局得到 HookParam 对象。

API 功能差异对比如下

after {
    // 得到当前 Hook 的实例
    instance
    // 得到当前 Hook 的 Class 实例
    instanceClass
    // 得到并 cast 当前 Hook 的实例为指定类型 T
    instance<T>()
    // 得到方法参数数组
    args
    // 得到方法参数的第一位 T
    args().first().cast<T>()
    // 得到方法参数的最后一位 T
    args().last().cast<T>()
    // 得到方法参数的任意下标 T,这里用 2 举例
    args(index = 2).cast<T>()
    // 设置方法参数的任意下标,这里用 2 举例
    args(index = 2).set(...)
    // 得到返回值
    result
    // 得到返回值并 cast 为 T
    result<T>()
    // 修改返回值内容
    result = ...
    // 删除返回值内容
    resultNull()
    // 获取当前回调方法体范围内的数据存储实例
    dataExtra
    // 向 Hook APP 抛出异常
    Throwable("Fatal").throwToApp()
    // 执行未经 Hook 的原始方法并使用原始方法参数调用,泛型可略
    callOriginal<Any?>()
    // 执行未经 Hook 的原始方法并自定义方法参数调用,泛型可略
    invokeOriginal<Any?>(...)
}
override fun afterHookedMethod(param: MethodHookParam) {
    // 得到当前 Hook 的实例
    param.thisObject
    // 得到当前 Hook 的 Class 实例
    param.thisObject.javaClass
    // 得到并 cast 当前 Hook 的实例为指定类型 T
    param.thisObject as T
    // 得到方法参数数组
    param.args
    // 得到方法参数的第一位 T
    param.args[0] as T
    // 得到方法参数的最后一位 T
    param.args[param.args.lastIndex] as T
    // 得到方法参数的任意下标 T,这里用 2 举例
    param.args[2] as T
    // 设置方法参数的任意下标,这里用 2 举例
    param.args[2] = ...
    // 得到返回值
    param.result
    // 得到返回值并 cast 为 T
    param.result as T
    // 修改返回值内容
    param.result = ...
    // 删除返回值内容
    param.result = null
    // 获取当前回调方法体范围内的数据存储实例
    param.extra
    // 向 Hook APP 抛出异常
    param.throwable = Throwable("Fatal")
    // 执行未经 Hook 的原始方法
    XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
}

Replace Hook

replaceHook 方法比较特殊,YukiHookAPI 为它做出了多种形式以供选择。

API 功能差异对比如下

/// 无返回值的方法 void

replaceUnit {
    // 直接在这里实现被替换的逻辑
}

/// 有返回值的方法

replaceAny {
    // 在这里实现被替换的逻辑
    // ...
    // 需要返回方法对应的返回值,无需写 return,只需将参数放到最后一位
    // 假设这个方法的返回值是 Int,我们只需要保证最后一位是我们需要的返回值即可
    0
}

/// 有些方法我们只需替换其返回值,则有如下实现
/// 需要注意的是:直接替换返回值的方法传入的参数是固定不变的,若想实现动态替换返回值请使用上面的 replaceAny 方法体

// 替换为你需要的返回值
replaceTo(...)
// 替换为 Boolean 类型的返回值
replaceToTrue()
// 拦截返回值
intercept()
/// 无返回值的方法 void

override fun replaceHookedMethod(param: MethodHookParam): Any? {
    // 直接在这里实现被替换的逻辑
    return null
}

/// 有返回值的方法

override fun replaceHookedMethod(param: MethodHookParam): Int {
    // 在这里实现被替换的逻辑
    // ...
    // 假设这个方法的返回值是 Int
    return 0
}

/// 有些方法我们只需替换其返回值,则有如下实现

// 替换为你需要的返回值
override fun replaceHookedMethod(param: MethodHookParam) = ...
// 替换为 Boolean 类型的返回值
override fun replaceHookedMethod(param: MethodHookParam) = true
// 拦截返回值
override fun replaceHookedMethod(param: MethodHookParam) = null

迁移更多有关 Hook API 的功能

YukiHookAPI 是一套全新的 Hook API,与其它 Hook API 存在着本质区别,你可以参考 API 文档 以及 特色功能 来决定一些功能性的迁移和使用。