作为前端工程师,想必大家都对网络请求的抓包和模拟请求都很熟悉,也有一些人基于这些抓包的信息去做了一些抢票工具之类的应用。
最近看到了一篇很有趣的文章,作者是对某租车小程序的网络请求进行抓包分析,还逆向解析了参数加密方式,很精彩的一篇文章,推荐大家阅读。
1、前序
最近临近暑期,想去海边玩。
想自驾游,无车呀,咋办,只能上某租车平台租车,打开一看价格不菲啊。
当我准备租的时候,改了时间,发现价格居然变少了,灵机一变的我突发奇想,会不会改了一个取车网点会不会也很便宜了呢?
果不其然,价格变低了不少,也就是说【时间+地点】可能会决定价格的变动,那怎么样做最优解呢?
最暴力的方式就是循环时间并且循环地点获取最低价格,那么怎么样调用这个查询接口呢?
思路:通过抓包的方式抓取到接口,然后动态的修改参数去获取查询结果的列表即可。
2、前置准备
抓包工具:fildder,以及配置好 https 证书,能抓到电脑小程序的请求,手机的也行配置好证书就行 微信小程序解密工具:UnpackMiniApp,用于解密微信小程序 微信小程序逆向工具:wxapkgconvertor,用于逆向微信小程序获取混淆的 JavaScript 代码 文件搜索工具:everything,用于快速搜索电脑系统文件。
3、开始抓包接口
首先先打开某租车小程序,已经打开过的建议先删除小程序避免找不到.wxapkg 文件。
进入小程序之后随便点击一下,保证.wxapkg 的存储。
找到选车页面,选择时间和网点之后点击立即选车,点击的同时打开 fildder 进行抓包。
通过抓包软件 fildder 可以看到响应数据找到对应的请求接口。
4、模拟请求研究参数
Postman 请求
上一节中通过 fildder 抓到对应的包之后,复制请求的 url 到 postman 进行二次请求测试。
入参研究
通过 postman 请求是 ge 请求,并且有四个参数,并且无需 header 的任何参数,那看起来应该是不难了
cid
:猜测是城市 idq
:不知道是什么,通过百分号看出来应该是 encodeURIComponent 过的参数sign
:一看就是加密的签名密钥,这个估计是重点uid
:未知的参数
做过爬虫的都知道有些参数不一定需要的,通过一个一个参数取消来判断哪些参数是不必要的,减少不必要的逆向工作。
cid 去除
发现不太行,cid 为必要参数。
q、sign、uid 的分别去除
分别都报错了,说明四个参数都是必要的好了,现在该研究参数是怎么来的了。
参数研究
q 参数
之前发现 q 参数是一个类似 encodeURIComponent 过的参数,这里做一下校验,请求到在线 UrlEncode 的网站解析发现是一个合法是数值。
{
"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
,然后再次发送请求看看结果。
果然失败了,意料之中,剩下几个参数不用研究,直接去源码中查看。
逆向解析
获取微信小程序加密包
首先先下载一个 everything(快速搜索文件的软件)输入.wxapkg 后缀名,然后点击修改时间倒叙排序(要提前删除小程序,重新进入登录,才能准确找到小程序加密包)。
进入文件夹,打开 UnpackMiniApp.exe 文件,选择需要破解的微信小程序包。
解析获取混淆源码
破解之后会有一个新的 wxapkg 文件,然后使用 wxapkgconvertor 转换为混淆过后的源码。
在当面文件夹会生成一个解析后的源码
逆向解析
代码格式化
获取到的源码是混淆且去掉空格的,打开 app-services.js
进行反混淆,优先使用网上的混淆还原工具去格式化,因为编辑器的格式化不一定正确。
寻找 sign 的加密方式
寻找参数的加密方式一般很简单一般搜索 "sign:"、"sign="、"sign"等关键字就行,毕竟是作为请求参数过来的.
搜索了一下 "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)
这种是什么意思等。
gpt 的回答是调用了 c.Ur 方法,并且把参数 concat 起来作为参数调用它,得到 sign,现在分开来看
cid:取到的是 a.x
,我们暂时用抓包到的cid
,根据观察同一个城市是不变的q:取的是 i
,就是我们抓包到的一个参数反解析得到的对象,我们根据它进行修改时间、城市就可以了u:看起来是可以不传的, u ? ";uid=".concat(u) : ""
这句代码可以看出,暂时取抓包抓到的a.$h:这个不知道是什么,继续往下看
点击应用 a.$h
,查看引入的地方。
返回的是 a
,再点击 a
,发现是一个常量对象,那就破解了 $h
。
加密函数推导
上一节已经把 c.Ur
的入参都搞定了就是用一个字符串 concat 起来就好了,现在就要做到 c.Ur
是什么函数了,同理点击找到定义。
追踪下去是定义了一个方法
主要函数有 Z、R 函数,不确定是什么,继续点击 Z、并且 R 函数传入了三个参数,e 就是我们的拼接字符串,void 0 和!0 ,不知道是什么意思,但是记住是三个参数。
Z 方法没有引入其他的方法了,直接复制下来,在看 R 方法。
网上看发现 n
是这个函数的参数,n.n(m)
也不知道是什么意思,看不懂,不过肯定是一个函数,那就直接先看 m
函数,传入了一个数字,搜索一下这个数字。
发现它就是定义了一个函数,但是又臭又长,不知道是什么意思,老样子 问 gpt 吧。
gpt 真是厉害,没看到任何关于 md5 的字母,却分析出来了,并且告诉我 c 就是入口函数,而且刚好是三个参数,刚好跟之前调用 R 方法的的三个参数对应上,那我就大胆猜测就是直接调用了这个方法。
到此所有的方法以及解析完成了,然后全部复制下来测试一遍看看。
本地 js 文件测试加密参数
本地方法
将拷贝的方法全部复制下来之后,组装一下,原来闭包的方式要改一下。
完整代码
测试校验
结果是这个数字,是不是很眼熟,打开之前 postman 请求的参数看看,发现是一模一样。
总结
本文的目的是为了学习抓包知识、js 混淆知识等、以及代码分析,掌握安全开发意识无论是混淆和反混淆技能都是很有必要的,在调研一些市面上的功能的时候可以用到,只有会了反破解,你才懂的如何去防止别人反破解。
“原文地址:
https://juejin.cn/post/7410289323737612315
作者:Archermon