北航网站每天早上七点预约羽毛球馆,时间过于逆天,根本起不来。本想写一个抢票的脚本,苦于通不过点按式的验证码,在网上找验证码破解在线服务接口效果也很不稳定,遂作罢。退而求其次,写一个监控脚本得了,抢抢别人退的票。
打开网站羽毛球预约,打开开发者模式,来回更换日期,发现是通过下图的post请求拿到的数据。先尝试直接把请求copy为curl在postman重放,果然失败。再仔细研究研究吧,发现路径参数有个nocache=1744633922114,值每次都在变,这不一眼毫秒级时间戳吗,没难度。多发几个请求测试发现除了nocache,请求头里有个Sign字段也每次都在变,这个就不好猜了,感觉大概率是某种加密。
老老实实逆向吧,先看看这个请求发出来之前的调用栈:先看看最外层两个调用。先点进i看看,打个断点。
如下图所示:发现n.headers.sign就已经出现sign了,而n是入参,所以肯定在调用i函数之前sign就已经计算好了。那再看看B吧。在B函数的末尾打个断点,再请求。
如下图所示:发现u就是sign值,而u是在j(c, a.path, o)这个函数获得值的
在console里输入j,看看这是个什么函数就一目了然了!
function j(e, n, t, a) {
var c = (a || U) + n;
if ("object" == Object(o["a"])(t))
for (var i = Object.keys(t).sort(), u = 0, r = i.length; u < r; u++) {
var l = i[u]
, s = t[l];
"object" != Object(o["a"])(s) && "" !== s && null !== s && void 0 !== s && (c += l + s)
}
return c += e + " " + (a || U),
d.a.MD5(c).toString()
}
现在逻辑已经一目了然啦!
这段代码的主要逻辑是生成一个基于输入参数的MD5哈希值。它接收四个参数,其中最后一个参数是可选的。
首先,代码会将默认值U与参数n拼接起来,形成一个初始字符串。接着检查参数t是否为对象类型,如果是的话,它会将t的所有属性名排序后遍历,把符合条件的属性名和属性值拼接到初始字符串上。这里的条件是属性值不能是对象类型,也不能是空字符串、null或undefined。
然后,代码会把参数e和一个空格拼接上去,同样使用可选参数a或者默认值U。最后,对这个拼接好的完整字符串进行MD5哈希计算,并返回哈希结果的字符串形式。
破解到这里就结束了,写一个python脚本,果然生效!
然后配合钉钉机器人,在监控到余票的时候发消息提醒。
然后把脚本部署到云服务器上,大功告成!