逆向有道翻译接口参数,本文仅供研究与学习使用,切勿用于各种非法用途。
打开有道翻译页面,输入你好,无需提交数据,翻译结果便自行生成了,要想实现这种逻辑,推断 Ajax 加载。 打开开发者工具,选择 Fetch/XHR 过滤请求,可以看到有两个 url:webtranslate 和 key。 key 中为提交的中文数据,不做分析,仅看接口 webtranslate。
都 23 年了,就知道没那么简单,问题不大,有加密必定有解密!
一个 sign 值需要分析,mysticTime 为时间戳。
在 XHR/提取断点中下断:webtranslate m 中的值即为经过 url 编码的负载数据:
i=%E4%BD%A0%E5%A5%BD&from=auto&to=&dictResult=true&keyid=webfanyi&sign=0d43622e3f5b6fc6578cdc1b849f9d28&client=fanyideskweb&product=webfanyi&appVersion=1.0.0&vendor=web&pointParam=client%2CmysticTime%2Cproduct&mysticTime=1687161867680&keyfrom=fanyi.web
跟踪堆栈数据,可定位到如下位置:
主要看 y 的生成,在该段代码执行后 sign 值便生成了,调试跟踪定位到在其上方的 O 函数:
e 为固定值:fsdsogkndfokasodnaso d 为固定值:fanyideskweb u 为固定值:webfanyi p 为固定值:1.0.0 b 为固定值:web m 为固定值:client,mysticTime,product t 为时间戳 f 为固定值:fanyi.web
经过上述分析可得,sign: h(t, e),sign 是由 h 函数得来的,分析 h 函数:
入参 e 为时间戳,t 为固定字符串:fsdsogkndfokasodnaso,将参数格式化后,又调用 g 函数,进入分析:
入参 e 为:
client=fanyideskweb&mysticTime=1687163549482&product=webfanyi&key=fsdsogkndfokasodnaso
入参后,创建 md5 函数进行加密,得到结果:
785914f401740b9bad913162ba4091ee
对照分析无误!
固定时间戳后,对照网页 sign 值结果无误。
python实现,代码如下:
请求后得到密文数据,下一步的目标就清楚了,找到解密函数。
可定位的方式有很多,关键字搜索、单步调试分析、堆栈分析等等。 第一次分析时单步调试无疑能让你了解整个执行流程,但真的费时间和精力,对我就是这么干的...... 建议还是通过关键字搜索如:decode,其次通过调用堆栈定位! 逐步调试最终定位到如下位置:
其中 o 为密文,执行完该局代码后生成明文数据 n。 直接看代码:
全局搜索 decodeKey 可得: 通过控制台打印输出得: key 和 iv 对照无误。 哪一种加密函数需要传入密文数据还有 key 值和 iv 向量? 其实大家心中已经有一些答案了,考考 ChatGpt: 跟进代码中看看是不是: 进入后发现: aes-128-cbc 加密,有 key,有 iv,执行完后生成明文数据,下一步就是还原该解密函数了。
首先判断t即传入的加密参数是否为空,为空则返回 null,不为空则继续执行下面的代码。 v 函数为:
对密钥和向量进行 MD5 加密,并返回字节数据。 接下来就是正常的 AES 算法了,不懂的可自行百度理解。
直接上代码:
执行得到数据:
{"code":0,"dictResult":{"ce":{"word":{"trs":[{"voice":"hello&type=2","#text":"hello","#tran":"喂,你好(用于问候或打招呼);喂,你好(打电话时的招呼语);喂,你好(引起别人注意的招呼语);<非正式>喂,嘿 (认为别人说了蠢话或分心);<英,旧>嘿(表示惊讶);招呼,问候;(Hello)(法、印、美、俄)埃洛(人名);说(或大声说)“喂”;打招呼;"},{"voice":"hi&type=2","#text":"hi","#tran":"嗨!(表示问候或用以唤起注意);(Hi)人名;(柬)希;"},{"voice":"how+do+you+do&type=2","#text":"how do you do","#tran":"你好;"}],"phone":"nǐ hǎo","return-phrase":"你好"}}},"translateResult":[[{"tgt":"hello","src":"你好","srcPronounce":"nĭhăo"}]],"type":"zh-CHS2en"}
对照网页代码生成数据无误:
直接上代码:
输入黑丝,执行结果:
任务完成。
const j
=
(e,t)
=
>
Object
(a[
"a"
])(
"https://dict.youdao.com/webtranslate/key"
,
Object
(n[
"a"
])(
Object
(n[
"a"
])({}, e), O(t)))
, y
=
(e,t)
=
>
Object
(a[
"d"
])(
"https://dict.youdao.com/webtranslate"
,
Object
(n[
"a"
])(
Object
(n[
"a"
])({}, e), O(t)), {
headers: {
"Content-Type"
:
"application/x-www-form-urlencoded"
}
})
const j
=
(e,t)
=
>
Object
(a[
"a"
])(
"https://dict.youdao.com/webtranslate/key"
,
Object
(n[
"a"
])(
Object
(n[
"a"
])({}, e), O(t)))
, y
=
(e,t)
=
>
Object
(a[
"d"
])(
"https://dict.youdao.com/webtranslate"
,
Object
(n[
"a"
])(
Object
(n[
"a"
])({}, e), O(t)), {
headers: {
"Content-Type"
:
"application/x-www-form-urlencoded"
}
})
function h(e, t) {
return
g(`client
=
${d}&mysticTime
=
${e}&product
=
${u}&key
=
${t}`)
}
function h(e, t) {
return
g(`client
=
${d}&mysticTime
=
${e}&product
=
${u}&key
=
${t}`)
}
function g(e) {
return
r.a.createHash(
"md5"
).update(e.toString()).digest(
"hex"
)
}
function g(e) {
return
r.a.createHash(
"md5"
).update(e.toString()).digest(
"hex"
)
}
import
time
mysticTime
=
str
(
int
(time.time()
*
1000
))
import
time
mysticTime
=
str
(
int
(time.time()
*
1000
))
import
hashlib
data
=
"client=fanyideskweb&mysticTime={}&product=webfanyi&key=fsdsogkndfokasodnaso"
.
format
(mysticTime)
sign
=
hashlib.md5(data.encode(encoding
=
'utf-8'
)).hexdigest()
import
hashlib
data
=
"client=fanyideskweb&mysticTime={}&product=webfanyi&key=fsdsogkndfokasodnaso"
.
format
(mysticTime)
sign
=
hashlib.md5(data.encode(encoding
=
'utf-8'
)).hexdigest()
import
hashlib
import
time
import
requests
class
Youdao():
def
__init__(
self
):
self
.url
=
'https://dict.youdao.com/webtranslate'
def
get_enmes(
self
, input_data):
mysticTime
=
str
(
int
(time.time()
*
1000
))
print
(mysticTime)
data
=
"client=fanyideskweb&mysticTime={}&product=webfanyi&key=fsdsogkndfokasodnaso"
.
format
(mysticTime)
sign
=
hashlib.md5(data.encode(encoding
=
'utf-8'
)).hexdigest()
print
(sign)
data
=
{
'i'
: input_data,
'from'
:
'auto'
,
'to'
: '',
'dictResult'
:
'true'
,
'keyid'
:
'webfanyi'
,
'sign'
: sign,
'client'
:
'fanyideskweb'
,
'product'
:
'webfanyi'
,
'appVersion'
:
'1.0.0'
,
'vendor'
:
'web'
,
'pointParam'
:
'client,mysticTime,product'
,
'mysticTime'
: mysticTime,
'keyfrom'
:
'fanyi.web'
}
headers
=
{
'Referer'
:
"https://fanyi.youdao.com"
,
"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"
,
}
cookies
=
{
"OUTFOX_SEARCH_USER_ID"
:
"-390346570@10.110.96.160"
,
"OUTFOX_SEARCH_USER_ID_NCOO"
:
"1229562063.3960004"
}
response
=
requests.post(
self
.url, headers
=
headers, data
=
data, cookies
=
cookies).text
print
(response)
def
start():
input_data
=
input
(
'请输入要翻译内容:'
)
op.get_enmes(input_data)
if
__name__
=
=
'__main__'
:
op
=
Youdao()
start()
import
hashlib
import
time
import
requests
class
Youdao():
def
__init__(
self
):
self
.url
=
'https://dict.youdao.com/webtranslate'
def
get_enmes(
self
, input_data):
mysticTime
=
str
(
int
(time.time()
*
1000
))
print
(mysticTime)
data
=
"client=fanyideskweb&mysticTime={}&product=webfanyi&key=fsdsogkndfokasodnaso"
.
format
(mysticTime)
sign
=
hashlib.md5(data.encode(encoding
=
'utf-8'
)).hexdigest()
print
(sign)
data
=
{
'i'
: input_data,
'from'
:
'auto'
,
'to'
: '',
'dictResult'
:
'true'
,
'keyid'
:
'webfanyi'
,
'sign'
: sign,
'client'
:
'fanyideskweb'
,
'product'
:
'webfanyi'
,
'appVersion'
:
'1.0.0'
,
'vendor'
:
'web'
,
'pointParam'
:
'client,mysticTime,product'
,
'mysticTime'
: mysticTime,
'keyfrom'
:
'fanyi.web'
}
headers
=
{
'Referer'
:
"https://fanyi.youdao.com"
,
"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"
,
}
cookies
=
{
"OUTFOX_SEARCH_USER_ID"
:
"-390346570@10.110.96.160"
,
"OUTFOX_SEARCH_USER_ID_NCOO"
:
"1229562063.3960004"
}
response
=
requests.post(
self
.url, headers
=
headers, data
=
data, cookies
=
cookies).text
print
(response)
def
start():
input_data
=
input
(
'请输入要翻译内容:'
)
op.get_enmes(input_data)
if
__name__
=
=
'__main__'
:
op
=
Youdao()
start()
.then(o
=
>{
an[
"a"
].cancelLastGpt();
const n
=
an[
"a"
].decodeData(o, sn[
"a"
].state.text.decodeKey, sn[
"a"
].state.text.decodeIv)
, a
=
n ? JSON.parse(n) : {};
0
=
=
=
a.code ? e.success && t(e.success)(a) : e.fail && t(e.fail)(a)
})
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-6-20 14:11
被行简编辑
,原因: