一、前言之前一篇文章已经详细介绍了 微信小程序包的格式 ,在之前文章中也了解到小程序包存放在沙盒目录,但是微信为了让小程序包安全就对文件名做了一个处理,导致我们很难找到对应的小程序对应的包文件,所以本文就来开发一个辅助插件,可以查看微信小程序的appid以及快速找到对应的小程序包文件,然后利用之前的解析工具直接本地解析程序包即可,下面就开始我们的表演吧! 二、添加小程序菜单首先第一步还是国际惯例,我们如果想暂时小程序的一些信息包括appid,版本号,本地存放路径文件名等,那么如何在微信页面中展示呢?首先来看一下小程序的页面:
然后我们就开始找到这个布局菜单,添加我们想要的菜单信息了,这个找入口有很多方式,比如可以通过字符串信息反编译之后去找对应的id值,或者是利用ui工具直接查看id信息,这里我就用这种方式:
看到了id是c8p,然后去反编译微信之后在values/public.xml中查找这个值,记得是type=id,name=c8p这一项哦:
找到之后,把id值转化成十进制,然后去Jadx中搜索吧,这里要注意我也说了很多遍了,微信做了拆包操作,而且微信包很大,直接用Jadx打开微信会卡死的,所以需要解压依次打开它的所有dex文件即可,然后就是挨个dex中搜这个值即可:
然后继续查找:
查看引用的地方:
点击进去查看定义:
然后就来到这个类,用的是RecyclerView控件了,这个类应该就是操作初始化底部菜单的地方了,我们需要找到这个控件的adapter,查看如何添加菜单的,因为拆包导致这个类被分的很开,而这个类有很多内部类,所以我们依次在每个dex中查找这个包下的这个类以及他的内部类,最终在这个地方看到:
这里就要对android应用开发有点熟练了,应用开发都用过RecyclerView控件,他的adapter编写格式都是统一的,这里看到及时混淆了,一看大致逻辑就清楚了。不过可惜的是,这个地方有个很大的坑,害得我浪费很多时间:
我一直在g类中找a这个方法,但是找了好几遍都没找到,结果在smali代码中找到了:
所以说没有一个工具是万能的,千万别相信任何一个工具。被坑残了。然后我们看到返回值其实是g类的局部变量qWf,类型是com.tencent.mm.ui.base.n可以直接搜这个类看看:
看到这里就明白了,这个是微信内部的统一菜单类,有一个菜单子选项的列表,然后继续回去看g类的那个变量qWf:
看看他在哪里初始化的:
点击进行查看:
好了,在这里初始化的,所以我们就可以进行hook操作了:
hook操作就不多解释了,很简单了结合反射即可:
注意这里的菜单内容先不要关心,后面会介绍如何获取小程序的appid和版本号以及保存路径的,然后运行模块,查看添加的菜单信息:
好了到这里我们就把这三个菜单添加好了,第一个菜单是为了查看小程序的appid和版本号信息,点击可以复制,第二菜单是小程序包的保存路径,点击可以复制路径。第三个是解析小程序包源码。主要借助之前介绍的解析小程序包工具。 三、获取小程序的相关信息那么下面继续来看如何获取小程序包的appid和版本号信息,以及本地保存的文件路径,入口也很操作,用ui工具查看当前布局即可,不过这里我在介绍新的技巧就是用adb shell dumpsys activity top命令查看view结构:
我们知道WX内部的所有WebView都是自己开发的x5内核,而小程序加载肯定得用WebView的,所以从这找到突破口,然后去Jadx找这个u类,而且在之前分析过了,微信小程序的功能都在com.tencent.mm.plugin.appbrand这个包下面的:
看到这个类果然是继承微信的内部统一WebView,然后无意中发现这个类中有appid字段了,为什么我们会按照这思路去找appid呢?因为小程序入口在webview加载的,那么肯定在这个地方用到了appid了,所以我们的思路没有问题的,继续查看这个字段的使用:
看到这个地方在构造一个webview需要加载的url信息,看到appid参与其中了,还有一个字段,其实这个就是小程序的版本号,后面我们会看到。我们可以先hook这个方法看看appid是否能获取到:
这里做了一个处理,就是把appid分离出来以及版本号,然后保存到全局变量中,用于菜单显示使用,我们运行模块,看看运行结果:
我们知道小程序的appid都是wx开头的,这里可以看到的确拿到了appid值,那么第二个到底是不是版本号呢?后面会说,先来看看如何获取小程序包路径信息,这里我们这么操作,因为我们在之前已经知道了小程序包都是放在这个目录下: /data/data/com.tencent.mm/MicroMsg/4d0238658a35658e7bc9597a2de4d49e/appbrand/pkg/
我们全局搜索wxapkg,看看这个文件名是如何定义的:
找到这个地方,格式和我们看到的很类似,这样我们直接hook这个方法,看看返回值路径是什么,以及传入的参数是啥:
运行模块查看结果:
看到这里发现第一个参数就是小程序appid,第二个参数很有可能就是版本号,返回的路径也是上面我们知道的,那么有的同学好奇了,这里直接hook然后保存一下路径不就可以了吗?其实我们在hook发现,这个方法只有首次加载程序包会调用。但是我们想要的效果是每次打开小程序点击菜单都能看到。如果保存很不方便。所以这里我们直接用appid和版本号进行构造,构造方式如下:
小程序appid字符串的hashCode值和版本号即可。有了之前的固定路径那么就可以了。下面再来看一下这个参数到底是不是版本号呢?查看这个ae方法的调用地方:
这里通过字段名称就可以看到就是版本号了。所以到这里我们就把小程序的appid,版本号,路径构造方法获取到了,下面操作就简单了。需要hook上面继承webview类的u类的aeN方法即可,然后通过分解获取到appid和版本号,上面已经运行有结果了,这里不在演示了:
看到这个方法是每次打开小程序都会调用,我们只要做个简单判断,有appid和版本号就保存到全局变量。然后在打开菜单的时候,把这两个信息放到菜单中,然后在利用这两个字段构造出本地小程序包的路径放在第二菜单中。最后一个菜单就是解析小程序了。这里我们的操作很简单了,先把沙盒中的wxapkg拷贝到SD卡下的指定目录,然后在借助之前写的解析小程序包工具直接解析即可。 四、添加菜单点击事件下面还有一个问题就是菜单的点击事件,这个我们还是要回到之前的g类中以及内部类中进行查看,最终找到这个类,因为g类和内部类不是很多,按个找dex很快就定位到了:
然后我们拦截这个onItemClick方法,处理0,1,2这三个我们添加的菜单点击事件即可:
这样我们就处理了三个菜单选项的点击事件了,菜单名称使用之前hook成功的appid值,路径构造是appid值和版本号即可,主要说一下最后的解析工作:
先把wxapkg包从沙盒中拷贝到SD卡的指定目录中,然后传入路径,开始执行我之前写的解析小程序包的工具即可。 严重声明本文的意图只有一个就是通过分析app学习更多的逆向技术,如果有人利用本文知识和技术进行非法操作进行牟利,带来的任何法律责任都将由操作者本人承担,和本文作者无任何关系,最终还是希望大家能够秉着学习的心态阅读此文。 鉴于安全问题,样本和源码都去编码美丽小密圈自取!微信扫一扫进入小密圈:
五、总结好了到这里,我们就把整个工具插件写完了,我们主要分为三部分: 第一部分:添加菜单用于展示小程序的信息,包括appid,版本号,本地程序包路径。 第二部分:通过分析获取到小程序的appid,版本号信息保存用于第一步的菜单内容展示。 第三部分:添加子菜单的点击事件,路径和appid点击就是赋值信息。解析小程序包直接调用之前的工具即可。 而在这三部分的突破口都是利用界面View分析获取到的,有两种方式:一种是借助UI分析工具,一种是利用adb命令;两种方式都是可以操作使用的。下面来看看我们操作的效果吧:
复制路径和appid值
解析程序包到本地 到这里我们就完成了本次操作,大家可以看到这个插件对于小白用户没啥用途,但是对于我们后续的逆向操作非常有用的,我们如果想逆向哪个小程序,直接解压看源码即可。也可以拷贝到电脑上进行分析更方便了。其实每次写微信插件都很费劲的,原因就在于微信包太大了,导致电脑非常的卡。所以写个插件不容易,喜欢的就点个赞分享吧! |