首先还是看响应,返回了一串加密数据
继续放大招hook JSON,详细流程在上一篇文章
然后直接跟栈找到解密位置
var t = 1 === (null === e || void 0 === e ? void 0 : e.status) ? A(A({}, e), {}, {
content: JSON.parse((0,
_.B6)(e.content))
}) : e;
t是解密之后的结果
然后就是解密函数:
经过测试是标准的AES-ECB解密模式
function f(e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "aahc3TfyfCEmER33"
, r = n.enc.Utf8.parse(t)
, o = n.AES.decrypt(e, r, {
mode: n.mode.ECB,
padding: n.pad.Pkcs7
});
return o.toString(n.enc.Utf8)
}
然后我们只需正确请求接口就ok了
简单看一下加密参数,就sign是比较可疑的
对于XHR请求的包,直接跟栈就对了!
就是跟栈的时候注意看一下url对不对,别跟错接口了😂😂
一直跟到找不到sign的踪迹为止
找到位置之后打断点,观察sign生成的全过程
经过分析sign的生成,是先经过md5然后AES加密生成
注:当看到加密函数传入字符串的时候,一定要先用123456测试一下,不要上来就扎入细节当中
整个加密参数的生成流程我们都清除了,下面就是扣代码环节了
经过调试已经可以生成正确的sign了
然后就是解密数据了,过程相对简单,就是应该普通的AES-ECB解密
完整的vscode代码:
// 加密参数sign生成算法
var CryptoJS = require('crypto-js');
s = function(e) {
e = decodeURIComponent(e);
for (var t = String.fromCharCode(e.charCodeAt(0) - e.length), r = 1; r < e.length; r++)
t += String.fromCharCode(e.charCodeAt(r) - t.charCodeAt(r - 1));
return t
};
function aes_encode(e) {
var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : "%5C%C2%80%C2%9A%C2%A8%C2%B6%C2%B8y%C2%9B%C2%B2%C2%8F%7C%7F%C2%97%C3%88%C2%A9d"
, r = CryptoJS.enc.Utf8.parse(s(t))
, o = CryptoJS.AES.encrypt(e, r, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return o.toString()
}
function get_sign(query){
var LI = '6dVjYLFyzfkFkk'
var con_str = "6key_web_new_fanyi".concat(LI).concat(query.replace(/(^\s*)|(\s*$)/g, ""));
var r = CryptoJS.MD5(con_str).toString().substring(0,16)
console.log(r)
return aes_encode(r)
}
/*var ret = get_sign('早上好')
console.log(ret)
console.log('over')*/
//解密响应数据算法
function aes_decode(e) {
var t = "aahc3TfyfCEmER33"
, r = CryptoJS.enc.Utf8.parse(t)
, o = CryptoJS.AES.decrypt(e, r, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return o.toString(CryptoJS.enc.Utf8)
}
/*var ret = aes_decode('nCRjxZwyh/7P3ee74BIU0r+VpYqC1/VewPqzx0un7jyNV2TcReI50gWyVhig1cg85spz3Z+vU9BuH+MZ9gpZDbFxsl6nE06WcFjQ1vllnHa/X9uvHGHQl4tTYa3B3DlS1qukVA9HNWk0rAyvPSnz68Wkf6p5bUFNBfLUvZKMQVy3FmCWe/NkT0FSRS3EL7WediKsKpF8Gq+m/NsT9zVE3sDqIe64/a4F9twH0KVZc+bCH+1eiXP29Po0pKMNkmuhWZN8biNTndn7IEkD1zJKhpTXSl0tJRb87q/u9/l51U5yjeiVxoTCwlOzoZygtiv55xamsuOEWt92DpT0dPSH1bl+XyrchrkYbYi+K6HJgVw=')
console.log(ret)
console.log('over')*/
最后就是python代码的编写了:
经过测试,也拿到正确的响应数据,并成功解密
解析具体的json串的时候报错:TypeError: string indices must be integers
解决: 将json字符串解析为字典即可》response_json = json.loads(decrypt_text)
完整的python代码:
import requests
import execjs
import json
headers = {
"authority": "ifanyi.iciba.com",
"pragma": "no-cache",
"cache-control": "no-cache",
"accept": "application/json, text/plain, */*",
"content-type": "application/x-www-form-urlencoded",
"sec-ch-ua-mobile": "?0",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Core/1.94.253.400 QQBrowser/12.6.5678.400",
"origin": "https://www.iciba.com",
"sec-fetch-site": "same-site",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
"referer": "https://www.iciba.com/",
"accept-language": "zh-CN,zh;q=0.9"
}
url = "https://ifanyi.iciba.com/index.php"
# query = input('请输入需要查询的单词:')
query = '早上好'
with open('金山词霸.js','r',encoding='utf-8') as f:
ctx = execjs.compile(f.read())
sign = ctx.call('get_sign',query)
params = {
"c": "trans",
"m": "fy",
"client": "6",
"auth_user": "key_web_new_fanyi",
"sign": sign
}
data = {
"from": "zh",
"to": "en",
"q": query
}
response = requests.post(url, headers=headers, params=params, data=data)
encry_text = response.json()['content']
print(encry_text)
decrypt_text = ctx.call('aes_decode',encry_text)
print(decrypt_text)
print(type(decrypt_text))
# 将 JSON 字符串解析为字典
response_json = json.loads(decrypt_text)
print(response_json['out'])
ok,今天的你就到此为止吧,明天还要接着狼🐺啊!