Skip to content

xpleemoon/XHook

Repository files navigation

XHook

开发背景:随着隐私合规要求的越来越严,已有线上老工程中必然散落着大量非法超频的隐私方法调用,如果手动一个个更改很容易会有遗漏,同时有些比如三方sdk又没法修改改。基于此XHook就诞生了,通过在app编译期间进行字节码插桩替换隐私方法调用。

当前支持了AndroidId、DeviceId、IMEI……隐私信息获取hook,具体可查看PrivacySentry。效果直接上图吧,第一张是AndroidId原始调用,第二张是AndroidId调用hook后反编译的结果

AndroidId原始调用图

AndroidId调用hook反编译图

虽然当前版本功能主要是替换隐私方法调用,但不仅限于此。若要进行其他方法替换的话,请基于@ReplaceClassHook@ReplaceMethodHook注解添加相关hook信息即可(建议统一在hook-lib源码库中新增)。

快速集成

  • xhook-lib库,为xhook插件提供hook方法和信息
  • xhook-annotation库,提供@ReplaceClassHook@ReplaceMethodHook注解,标记hook方法和原始方法信息
  • xhook-plugin库,提供xhook插件,同时在app编译期间,扫描收集hook信息,并针对目标代码进行hook信息织入
    • 0.1.1版本后,插件会自动为工程添加xhook-lib库和xhook-annotation库
  1. 在工程目录的build.gradle文件中添加xhook-plugin插件库依赖
buildscript {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
        ...
    }

    dependencies {
        ...
        // 添加hook-plugin依赖
        classpath("com.github.xpleemoon.XHook:xhook-plugin:latest_version")
    }

    subprojects {
        repositories {
          ...
          maven { url 'https://jitpack.io' }
          ...
        }
    }
}
  1. 在application module的build.gradle引用xhook插件即可
plugins {
    ...
    // 引用`xhook`插件
    id 'xhook'
}

进阶用法

若要配置黑名单,可以在application module的build.gradle设置插件的扩展

xHook {
    replaceCollectBlackList = ['com.xpleemoon.xhook.example.MainActivity']
    replaceWeaveBlackList = ["com.xpleemoon.hook_test"]
}

可在gradle.properties配置插件属性,具体如下

#调试开关,默认开启
xhook.enableDebug=true
#是否关闭插件,默认开启
xhook.enablePlugin=true
#是否关闭ReplaceMethodTransform,默认开启
xhook.enableReplaceMethodTransform=true
#ASM API version,默认是ASM7
xhook.ASM_API=ASM7

替换其他方法,可以在hook-lib库中或者也可以在其他库依赖zhook-annotation库,使用@ReplaceClassHook@ReplaceMethodHook注解,新增hook信息(谨慎使用,危险警告)

  • @ReplaceClassHook标记hook类
  • @ReplaceMethodHook标记hook方法,属性标记原始方法信息
    • originalClass标记原始方法的原始类
    • originalMethodName标记原始方法
    • originalInvokeOpcode标记原始方法的调用指令,这里关注点是静态方法和实例方法的调用指令
      • MethodInvokeOpcodes.INVOKESTATIC——静态方法调用指令
      • MethodInvokeOpcodes.INVOKEVIRTUAL——实例方法调用指令
@ReplaceClassHook
@Keep
object ToastHooks {

    @ReplaceMethodHook(
        originalClass = Toast::class,
        originalMethodName = "show",
        originalInvokeOpcode = MethodInvokeOpcodes.INVOKEVIRTUAL
    )
    @JvmStatic
    fun showToast(toast: Toast) {
        Log.d("ToastHooks", "hook toast.show")
        toast.show()
    }
}

@ReplaceMethodHook标记hook方法和原始方法信息,以下两点需要特别注意:

  1. hook方法必须是静态方法(所以上述代码中的showToast额外使用了@JvmStatic)因为插件为了方便织入hook方法,直接是当作静态方法处理的
  2. 原始方法名和所属类不能被混淆,因为原始方法信息被混淆的话,插件就无法识别出需要被hook的方法了

About

方法替换hook插件,目前主要用于hook隐私信息方法调用

Resources

License

Stars

Watchers

Forks

Packages

No packages published