JS逆向破解某租车微信小程序

作为前端工程师,想必大家都对网络请求的抓包和模拟请求都很熟悉,也有一些人基于这些抓包的信息去做了一些抢票工具之类的应用。

最近看到了一篇很有趣的文章,作者是对某租车小程序的网络请求进行抓包分析,还逆向解析了参数加密方式,很精彩的一篇文章,推荐大家阅读。


以下是正文:

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": [3199911138118732262113725627050852258515372901256524612363229330201866299917121635155814881369928886389266326982852291529923048306931953961068160716421670169818101831249626842733287329433104318820902987321320]
}

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

  • 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), {},
         {
            bucketIdListnull != 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 混淆知识等、以及代码分析,掌握安全开发意识无论是混淆和反混淆技能都是很有必要的,在调研一些市面上的功能的时候可以用到,只有会了反破解,你才懂的如何去防止别人反破解

原文地址:https://juejin.cn/post/7410289323737612315

作者:Archermon

© 版权声明
THE END
喜欢就支持一下吧, 不喜欢也支持一下吧
点赞15 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称常用语 夸夸
夸夸
还有吗!没看够!
表情代码图片

    暂无评论内容