之前用到了文章A Measurement Study of Wechat Mini-Apps提出的微信小程序半自动化收集工具MiniCrawler。最近深入看一下工具实现细节。
工具介绍
工具有两个功能,一是小程序元数据收集,另一个是小程序包下载。
小程序元数据收集
具体原理不难,就是拿到用户的请求参数,然后替换 request 中的 keyword 字段,批量发起请求。
- 用户手动在小程序搜索页面输入关键词,工具会帮助拿到用户向服务七搜索请求的一些参数,主要是认证参数
- 用户把这些参数和待搜索词列表放在指定位置
- 工具即可用这些拿到的参数批量发起小程序搜索请求,拿到服务器返回的多个小程序的元数据(小程序名、小程序 AppId 等)
小程序包下载
要求
- 微信 App 得是 7.0.20 版本
- 编译并安装 XposedPlugin
- 打开任意小程序页面
- 运行
adb shell am broadcast -a android.intent.myper --es appid "{待下载小程序的appid}"
,工具会自动下载链接及相关信息到 /sdcard/apps.txt
逆向 XposedPlugin
看了 XposedPlugin 源码,注册了个 android.intent.myper
的 receiver 用来接收待下载小程序的 appid。
Q:具体如何起到启动目标小程序的作用?
A:com.example.vsa.xposedutility.tests.WechatMiniAppsDownloader
中,工具接了 appid 之后 invoke 了小程序 API(代码如下)。通过调起 wx.navigateToMiniProgram
,appid 作为参数传进去,达到从当前小程序(任意的,但需要是小程序的 context)跳转到目标小程序的目的。
1 | Method method = next.getClass().getMethod("invokeHandler", String.class, String.class, Integer.TYPE); |
Q:如何拿到下载链接及包的相关信息?
A:com.example.vsa.xposedutility.tests.Wechat7020
类中 hookAll
中可以看出(如下图),关注的是微信 App 里的两个类:com.tencent.mm.plugin.appbrand.appcache.ba
、com.tencent.mm.plugin.appbrand.jsapi.l
。
1 | public void beforeHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable { |
逆向微信
com.tencent.mm.plugin.appbrand.appcache.ba
根据 XposedPlugin 代码行为,应该在 hook 到该类之后写数据(包下载 url)到 /sdcard/apps.txt
,但实测后没有该文件。只有在初始,需要下载微信小程序 jssdk 包的时候会调用一下,但下载普通小程序根本不走这。
自己又静态分析了一阵,找到了 com.tencent.mm.plugin.appbrand.appcache.bt.a(str,...)
方法,参数 str 就是下载链接。不知道为什么在我这边是 .bt
类,而作者那边是 .ba
类,apk 版本是一样的。
com.tencent.mm.plugin.appbrand.jsapi.l
里面 invokeHandler
是调起小程序 api 的方法
1 | public final String invokeHandler(String str, String str2, int i) |
里面 str 就是 invoke 的小程序方法名,本场景下是 navigateToMiniProgram
,str2 是传给这个小程序方法的参数,本场景下是 JSON,包括 appId 等信息。
函数体内有一句String y = dVar.y(str, str2, i);
,这里 trace 到后面是一个抽象类,该抽象类由多个子类实现。这些子类与 wx.{subAPI}
一一对应。navigateToMiniprogram
是 com.tencent.mm.plugin.appbrand.jsapi.miniprogram_navigator.g
。