今天我们来js逆向某道翻译返回的翻译数据解密:
1. 抓包:
搜url,打断点:
2.分析:
I = (e,t)=>Object(a["d"])("https://dict.youdao.com/webtranslate", Object(n["a"])(Object(n["a"])({}, e), k(t)), {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
#通过console观察知道Object(n["a"])(Object(n["a"])是在做合并
# 整理简化一下逻辑:
I = function(e,t){
a.d("https://dict.youdao.com/webtranslate", n.a( e, k(t)), {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
}
这里的逻辑:
I = function(e,t){
return a.d("https://dict.youdao.com/webtranslate", 参数, 请求头)
}
##猜测这里: 99%是发请求了
重新断点a.d ,进入
发现post(url,参数,请求头).then
发现这里跟axios很像,猜测:
e:response
n:reslove()
整理得出:该位置的a.d是发请求
又因为是axios请求,所以谁调用了T后面,百分之百有.then() ——>I().then()
所以找下一个调用栈:发现了then()
断定’‘o=>:’'就是返回的数据解密逻辑
# 分析:
At["a"].cancelLastGpt(); ——>与数据o无关
# 发现解密入口:
const n = At["a"].decodeData(o, Key, Iv)
a = n ? JSON.parse(n) : {};
进入At[“a”].decodeData(),拿到解密函数:
解密函数:
V = (t,o,n)=>{
if (!t)
return null;
const a = e.alloc(16, y(o))
, c = e.alloc(16, y(n))
, i = r.a.createDecipheriv("aes-128-cbc", a, c);
let s = i.update(t, "base64", "utf-8");
return s += i.final("utf-8"),
s
}
y():
分析得到,解密逻辑为:
返回的数据是ba64,需要进行aes解密 ——> 需要key 和iv
把key 和 iv丢入y() ——> 算md5(要注意的是:该md5少了‘hex’)
——>拿到key 和iv 后进行aes解密
3.代码:
python:
import time
import requests
from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64
t = 'fsdsogkndfokasodnaso'
u = "webfanyi"
e = str(int(time.time() * 1000))
d = "fanyideskweb"
s = f'client={d}&mysticTime={e}&product={u}&key={t}'
obj = md5()
obj.update(s.encode())
sign = obj.hexdigest()
data = {
"i": input('请输入你要查询的单词:'),
"from": "auto",
"to": "",
"dictResult": "true",
"keyid": "webfanyi",
"sign": sign,
"client": "fanyideskweb",
"product": "webfanyi",
"appVersion": "1.0.0",
"vendor": "web",
"pointParam": "client,mysticTime,product",
"mysticTime": e,
"keyfrom": "fanyi.web",
}
url = "https://dict.youdao.com/webtranslate"
header = {
"Referer": "https://fanyi.youdao.com/",
"Cookie": "OUTFOX_SEARCH_USER_ID=-922898077@10.110.96.160; _ga=GA1.2.50793062.1656497331; OUTFOX_SEARCH_USER_ID_NCOO=1490949463.084894; search-popup-show=11-8",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
}
resp = requests.post(url, data=data, headers=header)
decodeKey = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl"
decodeIv = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4"
def my_md5(s):
obj = md5()
obj.update(s.encode("utf-8"))
# return obj.hexdigest() # 返回32位的十六进制字符串
return obj.digest() # 返回16位字节
key = my_md5(decodeKey)
iv = my_md5(decodeIv)
aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
txt = resp.text.replace("_", "/").replace("-", "+")
bs = base64.b64decode(txt)
ming = aes.decrypt(bs)
ming = unpad(ming, 16)
ming_str = ming.decode("utf-8")
print(ming_str)
js:
通过分析已经知道源码是md5+aes解密,我们同样可以用js的第三方库crypto来完成解密:
var crypto = require("crypto");
function g(e) {
return crypto.createHash("md5").update(e).digest();
}
var decrypt = (t,o,n)=>{
if (!t)
return null;
const a = Buffer.alloc(16, g(o))
, c = Buffer.alloc(16, g(n))
, i = crypto.createDecipheriv("aes-128-cbc", a, c);
let s = i.update(t, "base64", "utf-8");
return s += i.final("utf-8"),
s
}
decodeKey = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl"
decodeIv = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4"
data='需要解析的数据'
r = decrypt(data, decodeKey, decodeIv)
console.log(r);