【爬虫逆向】逆向破解某租车微信小程序,sign的解析

844 阅读7分钟

0、工具下载链接

1、UnpackMiniApp

2、wxapkgconvertor

3、everythingfildder 搜索引擎搜一下都有

1、前序

最近临近暑期,想去海边玩.

想自驾游,无车呀,咋办,只能上某租车平台租车,打开一看价格不菲啊

image.png

当我准备租的时候,改了时间,发现价格居然变少了,灵机一变的我突发奇想,会不会改了一个取车网点会不会也很便宜了呢?

image.png

果不其然,价格变低了不少,也就是说【时间+地点】可能会决定价格的变动,那怎么样做最优解呢?

最暴力的方式就是循环时间并且循环地点获取最低价格,那么怎么样调用这个查询接口呢?

思路:通过抓包的方式抓取到接口,然后动态的修改参数去获取查询结果的列表即可

2、前置准备

  1. 抓包工具:fildder,以及配置好https证书,能抓到电脑小程序的请求,手机的也行配置好证书就行
  2. 微信小程序解密工具:UnpackMiniApp,用于解密微信小程序
  3. 微信小程序逆向工具:wxapkgconvertor,用于逆向微信小程序获取混淆的JavaScript代码
  4. 文件搜索工具:everything,用于快速搜索电脑系统文件

3、开始抓包接口

首先先打开某租车小程序,已经打开过的建议先删除小程序避免找不到.wxapkg文件

image.png

进入小程序之后随便点击一下,保证.wxapkg的存储

image.png

找到选车页面,选择时间和网点之后点击立即选车,点击的同时打开fildder进行抓包

image.png

通过抓包软件fildder可以看到响应数据找到对应的请求接口

image.png

4、模拟请求研究参数

4.1 Postman 请求

上一节中通过fildder抓到对应的包之后,复制请求的url到postman进行二次请求测试

image.png

4.2 入参研究

通过postman请求是ge请求,并且有四个参数,并且无需header的任何参数,那看起来应该是不难了

  • cid:猜测是城市id
  • q:不知道是什么,通过百分号看出来应该是encodeURIComponent过的参数
  • sign:一看就是加密的签名密钥,这个估计是重点
  • uid:未知的参数

做过爬虫的都知道有些参数不一定需要的,通过一个一个参数取消来判断哪些参数是不必要的,减少不必要的逆向工作

4.2.1 cid去除

image.png

发现不太行,cid为必要参数

4.2.2 q、sign、uid的分别去除

image.png

分别都报错了,说明四个参数都是必要的好了,现在该研究参数是怎么来的了

4.3 参数研究

4.3.1 q参数

之前发现q参数是一个类似encodeURIComponent过的参数,这里做一下校验,请求到在线UrlEncode的网站解析发现是一个合法是数值

image.png

{
    "pickupCityId": "14",
    "pickupTime": "2024-08-09 12:30",
    "returnCityId": "14",
    "returnTime": "2024-08-11 12:30",
    "entrance": 1,
    "holidaysWaitingFlag": 0,
    "pickupDoorFlag": false,
    "returnDoorFlag": false,
    "exclusivenearby": true,
    "pickupDeptId": "127248",
    "returnDeptId": "127248",
    "bucketIdList": [319, 991, 1138, 1187, 32, 2621, 137, 256, 270, 508, 522, 585, 1537, 2901, 2565, 2461, 2363, 2293, 3020, 1866, 2999, 1712, 1635, 1558, 1488, 1369, 928, 886, 389, 2663, 2698, 2852, 2915, 2992, 3048, 3069, 3195, 396, 1068, 1607, 1642, 1670, 1698, 1810, 1831, 2496, 2684, 2733, 2873, 2943, 3104, 3188, 2090, 298, 732, 1320]
}

见名知起义,可以大胆的先猜测它的含义,用于后续研究

  • pickupCityId:应该是取车城市
  • returnCityId:还车城市
  • pickupDeptId:取车网点
  • returnDeptId:还车网点

大胆假设一下,如果我修改了还车时间再编码一下发过去请求,会不会成功呢(校验sign的参数跟哪些参数有关,一般sign都是混合多个参数进行加密的)

修改还车时间为2024-08-30 12:30,然后再次发送请求看看结果

image.png

果然失败了,意料之中,剩下几个参数不用研究,直接去源码中查看

5、逆向解析

5.1、获取微信小程序加密包

首先先下载一个everything(快速搜索文件的软件)输入.wxapkg后缀名,然后点击修改时间倒叙排序(要提前删除小程序,重新进入登录,才能准确找到小程序加密包)

image.png

进入文件夹,打开UnpackMiniApp.exe文件,选择需要破解的微信小程序包

image.png

5.2、解析获取混淆源码

破解之后会有一个新的wxapkg文件,然后使用wxapkgconvertor转换为混淆过后的源码

image.png

在当面文件夹会生成一个解析后的源码

image.png

6、逆向解析

6.1、代码格式化

获取到的源码是混淆且去掉空格的,打开app-services.js进行反混淆,优先使用网上的混淆还原工具去格式化,因为编辑器的格式化不一定正确

6.2、寻找sign的加密方式

寻找参数的加密方式一般很简单一般搜索 "sign:"、"sign="、"sign"等关键字就行,毕竟是作为请求参数过来的

image.png

搜索了一下 "sign:"就出现两个结果,并且出现了cid、q、uid,看起来很像了,把方法拆出来看

function(e) {
   var t = o.R.getState().baseInfo.bucketIdList,
      n = e.data || {},
      i = JSON.stringify((0, r.Z)((0, r.Z)({},
            n), {},
         {
            bucketIdList: null != t ? t: void 0
         })),
      u = (0, c.uP)(),
      l = {
         cid: a.x,
         q: i,
         sign: (0, c.Ur)("cid=".concat(a.x, ";q=").concat(i).concat(u ? ";uid=".concat(u) : "").concat(a.$h))
      };
   return u && (l.uid = u),
      l
}

貌似看不太懂,看不懂我们有gpt啊,问gpt,要善于借助chatgpt,比如 (0, c.Ur)这种是什么意思等

image.png

gpt的回答是调用了c.Ur方法,并且把参数concat起来作为参数调用它,得到sign,现在分开来看

  • cid:取到的是a.x ,我们暂时用抓包到的cid,根据观察同一个城市是不变的
  • q:取的是i,就是我们抓包到的一个参数反解析得到的对象,我们根据它进行修改时间、城市就可以了
  • u:看起来是可以不传的, u ? ";uid=".concat(u) : "" 这句代码可以看出,暂时取抓包抓到的
  • a.$h:这个不知道是什么,继续往下看

点击应用a.$h,查看引入的地方

image.png

返回的是a,再点击a,发现是一个常量对象,那就破解了$h

image.png

6.3、 加密函数推导

上一节已经把c.Ur的入参都搞定了就是用一个字符串concat起来就好了,现在就要做到c.Ur是什么函数了,同理点击找到定义

image.png

追踪下去是定义了一个方法

image.png

主要函数有Z、R函数,不确定是什么,继续点击Z、并且R函数传入了三个参数,e就是我们的拼接字符串,void 0和!0 ,不知道是什么意思,但是记住是三个参数

image.png

Z方法没有引入其他的方法了,直接复制下来,在看R方法

image.png

网上看发现n是这个函数的参数,n.n(m)也不知道是什么意思,看不懂,不过肯定是一个函数,那就直接先看m函数,传入了一个数字,搜索一下这个数字

image.png

image.png

发现它就是定义了一个函数,但是又臭又长,不知道是什么意思,老样子 问gpt吧

image.png

gpt真是厉害,没看到任何关于md5的字母,却分析出来了,并且告诉我c就是入口函数,而且刚好是三个参数,刚好跟之前调用R方法的的三个参数对应上,那我就大胆猜测就是直接调用了这个方法

image.png

到此所有的方法以及解析完成了,然后全部复制下来测试一遍看看

7、 本地js文件测试加密参数

7.1 本地方法

将拷贝的方法全部复制下来之后,组装一下,原来闭包的方式要改一下

image.png

完整代码

image.png

7.2 测试校验

结果是这个数字,是不是很眼熟,打开之前postman请求的参数看看,发现是一模一样

image.png

8、总结

本文的目的是为了学习抓包知识、js混淆知识等、以及代码分析,掌握安全开发意识无论是混淆和反混淆技能都是很有必要的,在调研一些市面上的功能的时候可以用到,只有会了反破解,你才懂的如何去防止别人反破解