开发背景:随着隐私合规要求的越来越严,已有线上老工程中必然散落着大量非法超频的隐私方法调用,如果手动一个个更改很容易会有遗漏,同时有些比如三方sdk又没法修改改。基于此XHook就诞生了,通过在app编译期间进行字节码插桩替换隐私方法调用。
当前支持了AndroidId、DeviceId、IMEI……隐私信息获取hook,具体可查看PrivacySentry。效果直接上图吧,第一张是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库
- 在工程目录的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' }
...
}
}
}- 在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方法和原始方法信息,以下两点需要特别注意:
- hook方法必须是静态方法(所以上述代码中的showToast额外使用了
@JvmStatic)因为插件为了方便织入hook方法,直接是当作静态方法处理的- 原始方法名和所属类不能被混淆,因为原始方法信息被混淆的话,插件就无法识别出需要被hook的方法了

