/20230510/logo.svg

小天同学 第三方 APP 开发

官方 APP 使用不便 于是想开发一个使用更便捷的第三方 APP 项目地址

APP 逆向

抓包 发现 data 有加密 尝试解密失败,试图寻找源码 使用工具frida-dexdump 脱壳,但得到的代码可读性很低,发现有小程序,于是转战

微信小程序 逆向

原以为小程序和微信服务器的沟通只是为了拿到手机号明文,于是想要直接使用小程序的请求方式完成登录等全部流程

  • 使用工具 unveilr 直接对__APP__.wxapkg进行解包
  • 使用微信开发者工具打开解包后的文件并尝试编译,成功 (好运)
  • 尝试使用 Burpsuite 和 proxifier 对 PC 端小程序抓包,参考了相关教程,寻找登录请求,发现和 APP 抓到的包有相同的加密
  • 由于解包后的小程序代码有混淆,可读性差,于是直接调试
  • 小程序的主要 JS 代码位于根目录下,由于其中的函数均声明了 "use strict" 所以先删除
  • 搜索加密函数 直接使用console.log打印,在调试器里导出为全局变量 就可以进行加解密操作了
  • 在某些情况下,会提示字符串不是 UTF-8,这时候需要将 \\/ 改为 \/ 可能还需要增减 = 的数量
  • 到这里以为已经结束了,抓到的包可以直接解出,但是解密小程序的登录请求后发现里面还有一层加密且无法使用同样的解密方式解密
  • 解密的微信小程序登录请求包中存在一个名为code的 key 通过查阅微信开发者文档,判断应该是与微信服务器的交流中拿到的,奈何微信的数据包加密十分抽象,没有思路拿到 code 于是思路再次中断

又回到最初的起点🎵

  • 偶然发现小程序的解密方式对 APP 抓到的包同样适用,于是柳暗花明,拿到验证码登录和打开饮水机的请求方式
  • 现在只需要复现加解密函数即可,找到 crypto-js 库,发现完全一致,仅需的两个参数:密钥和密钥偏移量,也写在小程序的源码中

上面提到的code应该是微信服务端同时发送到小程序服务端和小程序客户端,一起发送给小程序服务端的还有被加密的手机号,小程序客户端需要用code才能拿到明文手机号

APP 开发

  • 在伪造请求时要注意发送数据的编码类型
  • 在新版本中,如果要发送 http 请求,需要在 AndroidManifest.xmlapplication 中 增加 android:usesCleartextTraffic="true"
  • 可能是由于编码方式的问题 返回的字符串有多余的 \"\\ 字符
  • 在 kotlin 中进行解密操作时,由于 \\/ 字符的出现,需要使用三层`对整体字符串进行包裹,使其转为raw` 后再进行替换操作
  • 替换字符串时,kotlin 的正则貌似不大好用