某程机票查询,token、transactionid、sign逆向
声明:本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关.本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责。
0x01目标
机票查询,详情打印输出
0x02确定API
选好出发地、目的地及日期点击查询,观察请求包。在xxx/search/batchSearch中发现需要的数据。
0x03确定加密参数
多次请求,变换地址,对比网络包差别。发现在Cookie中仅bfa发生变化,但是后续请求发现该值可以固定,不过不排除多次请求可能被风控。Header中,有三个值发生变化即今天的主角:1001开头的token、sign和transactionid。本文主要记录对这三个参数的分析过程。
0x04参数逆向
token逆向
查看网络请求堆栈,在请求之前打上断点,在此请求。此时在header中三个参数均已生成,继续往前跟,找到生成的位置。
跟到以下代码,将多个对象赋值到了headers中,其中包括一个函数V(e)生成的对象,查看r的值发现是sign,跟进V函数。
var a = {
withCredentials: !0,
responseType: "json",
headers: Object.assign({
Accept: "application/json",
"Content-Type": "application/json;charset=utf-8"
}, V(e), r),
validateStatus: function(t) {
try {
n.g.i("XWc")
} catch (o) {}
return t >= 200 && t < 300 || 432 === t
}
};
跟到代码发现token来源于变量i,变量i的生成如下代码,即window.signature就是生成token的关键函数,传入的r是请求参数。
i = "function" === typeof window.signature ? window.signature(r) : "";
查看window.signature函数位置,发现代码是经过混淆的,一堆_unknown_xx的东西,搞得我也unknown了。还有这个函数命名,庐山升龙霸可还行。
并且整个JS文件是一个自执行函数,将代码拷贝到IDE中执行,本来还想说把加密的位置导出的,结果发现运行这个js文件后,他已经将signature导出到了window中,按照经验来看,这种加密肯定是要校验浏览器环境的,先用插件吐个环境用用。执行加密,正常生成,并且多次使用了浏览器环境的API。
sign逆向
前面跟token时跟到了将sign也赋值到headers中,这边继续向前跟,往上找r的生成位置
找到r的生成位置,代码如下,等同于h.T(t),下断点跟进这个函数
var r = (0,h.T)(t)
在return中看到sign:r,同样在return中r = (new (i())).update(a).digest(“hex”),其实第一眼看到sign的值凭借经验就能判断应该是一个hash函数。在这边下断点使用这个函数将a换成1加密测试,发现是标准的md5函数,往上翻下a包含哪些东西。
=>0 sign: r
=>1 r = (new (i())).update(a).digest("hex")
=>2 var a = t.transactionID + e
=>3 e += t.departureCityCode + t.arrivalCityCode + t.departureDate
sign的生成伪代码如下:
MD5(transactionID + departureCityCode + arrivalCityCode + departureDate)
transactionID逆向
在前面跟值的过程中我们发现,transactionID在很早就一直存在于参数中,并且最后的网络包中也随参数提交,往前跟到参数生成位置,发现是从window中取了一个全局变量
var t = window.GlobalSearchCriteria
直接在网络包中搜索transactionID看是否是前面的请求返回,果然在请求中发现,还帮我们把请求参数都构建好了,真贴心。
0x05城市代码获取
在搜索的主页翻请求即可找到城市对应代码的接口,API是xxx/SearchBoxRecommend,从返回的内容中将城市对应代码解析到本地即可。然后搜索时提示用户输入城市名,再用城市名去匹配即可获取城市代码。
0x06调用顺序
整个搜索流程如下:首先获取城市代码,然后请求获取transactionID即参数构造,使用参数生成token,生成sign,发起请求获取航班信息。