2021年6月20日

WeChat8Xposed通用hook框架适配新版微信-单元测试适配新微信

作者 huruwo

MirrorUnitTest 测试版本适配

我们知道的。xposed要生效hook到指定的位置的类和方法

最重要的就是类名和方法名

而由于大多数软件开启了混淆模式,有时候神奇的路径就会变化。即使是非常微小的版本差异也会导致路径大相径庭。

WechatSpellbook 原作者非常贴心的准备了一个MirrorUnitTest 测试文件来解析文件路径。

MirrorUnitTest原理分析

通过阅读MirrorUnitTest的源码,我大致了解就是通过apk的文件dex分析,来寻找指定的目标类。

几个核心的测试类方法:

apkFile.exists()

检查安装包文件 也就是你要hook的版本的微信安装包 记得放在指定目录下面

MirrorClasses + MirrorMethods + MirrorFields

映射类 映射方法 映射变量 也即是我们讲的特征值

变成一个Objects 传入MirrorUtil 作为查找目标类的特征值

val objects = MirrorClasses + MirrorMethods + MirrorFields

MirrorUtil

核心的适配 自动适配表达式 的工具类

通过传入特征值来寻找和记录类路径

  1. MirrorUtil.clearUnitTestLazyFields(instance)

清除上次的缓存

2.MirrorUtil.generateReportWithForceEval(objects)

测试是否能找到目标类

apkFile.delete()

删掉因为解析产生出来的垃圾文件 大概有几百M 测试完成通过将全部自动删除

下载目标版本的apk文件

值得注意的是 原作者的库里留下了测试文件 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应用程序包的类结构映射。
哪个类出现异常就要修复哪个类的问题

具体的修复下篇分析。