原文首发于WeChat8Xposed通用hook框架适配新版微信-单元测试适配新微信
如有访问异常或者问题讨论请前往原文浏览
最近在研究个人的微信bot,也就是想做一个微信聊天的机器人。搜索之下发现了一个有意思的库WechatSpellbook。
Wechat Spellbook 是一个使用Kotlin编写的开源微信插件框架,底层需要 Xposed 或 VirtualXposed 等Hooking框架的支持,而顶层可以轻松对接Java、Kotlin、Scala等JVM系语言。让程序员能够在几分钟内编写出简单的微信插件,随意揉捏微信的内部逻辑。
正好做下研究,利用这个框架配合xposed做 微信数据抓取 微信公众号阅读量的采集分析 还有微信机器人的制作
在使用中发现该库已经无法正常满足最版本的微信hook
需要重新对其做适配工作
于是我新建了一个项目 WeChat8Xposed
地址在 https://github.com/HuRuWo/WeChat8Xposed
fork了原库的代码作为组件 导入之后开始做适配工作。
我们知道的。xposed要生效hook到指定的位置的类和方法
最重要的就是类名和方法名
而由于大多数软件开启了混淆模式,有时候神奇的路径就会变化。即使是非常微小的版本差异也会导致路径大相径庭。
WechatSpellbook 原作者非常贴心的准备了一个MirrorUnitTest 测试文件来解析文件路径。
通过阅读MirrorUnitTest的源码,我大致了解就是通过apk的文件dex分析,来寻找指定的目标类。
几个核心的测试类方法:
检查安装包文件 也就是你要hook的版本的微信安装包 记得放在指定目录下面
映射类 映射方法 映射变量 也即是我们讲的特征值
变成一个Objects 传入MirrorUtil 作为查找目标类的特征值
val objects = MirrorClasses + MirrorMethods + MirrorFields
核心的适配 自动适配表达式 的工具类
通过传入特征值来寻找和记录类路径
清除上次的缓存
2.MirrorUtil.generateReportWithForceEval(objects)
测试是否能找到目标类
删掉因为解析产生出来的垃圾文件 大概有几百M 测试完成通过将全部自动删除
值得注意的是 原作者的库里留下了测试文件 MirrorUnitTest
针对一些目标版本做了测试从6.60版本一直到6.73版本的适配测试
如何做一个新版的适配测试呢
这就要拉下来我们要适配的版本apk
今天是2021-6-21日,官网最新的版本是 v806版本 下载链接 https://dldir1.qq.com/weixin/android/weixin806android1900_arm64.apk我们把
它拉下来放到文件下apks/domestic
目录下面
测试脚本新增一行
@Test fun verifyPlayStorePackage8_0_6() {
verifyPackage("$DOMESTIC_DIR/wechat-v8.0.6.apk")
}
然后点击运行测试 查看输出日志 分析通过特征值是否找到了指定的目标类一测就出问题了
没有找到 NotificationManagerCompat
scriptjava.lang.Error: Failed to evaluate NotificationManagerCompat at
com.gh0u1l5.wechatmagician.spellbook.mirror.android.support.v4.app.Classes$$special$$inlined$wxLazy$1.invoke(WechatGlobal.kt:112) at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) at
com.gh0u1l5.wechatmagician.spellbook.WechatGlobal$UnitTestLazyImpl.getValue(WechatGlobal.kt:138) at
com.gh0u1l5.wechatmagician.spellbook.util.MirrorUtil.generateReportWithForceEval(MirrorUtil.kt:64) at
com.gh0u1l5.wechatmagician.spellbook.MirrorUnitTest.verifyPackage(MirrorUnitTest.kt:84) at
com.gh0u1l5.wechatmagician.spellbook.MirrorUnitTest.verifyPlayStorePackage8_0_6(MirrorUnitTest.kt:152) at java.lang.reflect.Method.invoke(Native Method) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at
androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at
androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56) at
androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388) at
android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2091)
这个异常意味着特征类没有找到 需要重新制作特征类
也就是要重新适配路径核心就在mirror文件夹下面
有所有通用映射规则的 也就是wechat应用程序包的类结构映射。
哪个类出现异常就要修复哪个类的问题
具体的修复下篇分析。