案例-七麦数据
地址: https://www.qimai.cn/rank
逆向的目标是请求参数:
全局搜索:第三个文件不用看了,因为是CSS文件。
看到下面的请求的是URL有所搜索的关键字,而关键字是来自请求参数的。好像不太对。所以搜索 analysis 没啥用,要用其他方案搜索。
观察到每个请求都有analysis,说明所有请求都要过一个地方,根据经验,应该是axios,应该是一个拦截器做的事。
观察一下启动器,用到了promise。
所以应该搜索 interceptors
看到下面,这是源码
参数应该是在axios的拦截器上进行的加密,改成下述逻辑之后拦截器搜不到。
haha = 'interc'+'eptors'
axios[haha]['request']["use"](function(){}, function(){})
axios.interceptors.response.use(function(){}, function(){})
猜测. 网站的逻辑应该是用上述逻辑完成的.
遇到这种情况怎么办? 从axios源码下手。
o函数是xhr发送请求的函数。
python代码:
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")
import execjs
import requests
import json
f = open("七麦.js", mode='r', encoding="utf-8")
js_code = f.read()
f.close()
js = execjs.compile(js_code)
url = "https://api.qimai.cn/rank/index"
params = {
"brand": "free",
"device": "iphone",
"country": "cn",
"genre": "36",
"date": "2023-05-15",
"page": 3,
"is_rank_index": 1,
"snapshot": "23:08:06"
}
analysis = js.call("fn", url, params)
params['analysis'] = analysis
resp = requests.get(url, params, headers={
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
})
print(resp.json())
七麦.js
// global就是node的全局
window = global;
function o(n) {
t = "",
['66', '72', '6f', '6d', '43', '68', '61', '72', '43', '6f', '64', '65']['forEach'](function(n) {
t += window['unescape']('%u00' + n)
});
var t, e = t;
return window['String']["fromCharCode"](n)
}
function v1(t) {
t = window['encodeURIComponent'](t)["replace"](/%([0-9A-F]{2})/g, function(n, t) {
return o("0x" + t)
});
try {
return window["btoa"](t); // base64 浏览器的
} catch (n) {
return window["Buffer"]["from"](t)["toString"]("base64"); // base64 nodejs的
}
}
function h(n, t) {
for (var e = (n = n["split"](""))["length"], r = t["length"], a = "charCodeAt", i = 0; i < e; i++)
n[i] = o(n[i][a](0) ^ t[(i + 10) % r][a](0));
return n["join"]("")
}
function fn(url, params) {
let baseURL = 'https://api.qimai.cn'
let s = -56;
var e, r = +new Date - (s) - 1661224081041, a = [];
void 0 === params && (params = {}),
// 循环参数. 然后把参数的值. 塞入 数组a中
Object.keys(params)["forEach"](function(n) {
if (n === "analysis")
return !1;
params["hasOwnProperty"](n) && a["push"](params[n])
}),
a = a["sort"]()["join"](""),
a = v1(a),
a = (a += "@#" + url["replace"](baseURL, "")) + ("@#" + r) + ("@#" + 3);
e = v1(h(a, "xyz517cda96abcd"));
return e;
}