反向目标:有道翻译接口参数主页:https://fanyi.youdao.com/接口:https://fanyi.youdao.com/tran。..逆向参数:FormData:salt:16261583727540sign:151e4b19b07ae410e0e1861a6706d30cbv:5b3e307b66a6c075d525ed231dcc8dcd逆向过程抓包分析我们在有道翻译页面随便输入文字,可以看到页面没有加载,所以可以推导出翻译结果是Aja是的,打开开发者工具,选择XHR过滤Ajax请求,可以看到有一个POST请求,URL为https://fanyi.youdao.com/tran...当我们输入“test”时,返回数据类似如下结构:{"translateResult":[[{"tgt":"test","src":"test"}]],"errorCode":0,"type":"zh-CHS2en","smartResult":{"entries":["","[Test]test\r\n","measurement\r\n"],"type":1}}translateResult为翻译结果,smartResult是智能推荐其他翻译,那么这个URL就是我们需要的翻译接口。由于是POST请求,我们观察它的FormData:i:stringtobetranslated;来自:要翻译的语言;至:目标语言;lts:时间戳;smartresult、client、doctype、version、keyfrom:固定值;action:实时翻译FY_BY_REALTlME,手动点击翻译FY_BY_CLICKBUTTION;每次salt、sign、bv的值都会变化,需要进一步分析。参数reversesalt,sign,bv三个加密参数,全局搜索任意一个,搜索结果比较多,依次比较,可以发现从fanyi.min.js文件的8969行左右开始,所有的参数FormData完成,埋下断点调试,可以看到所有的数据都和最终结果一致,加密的四个参数都在r中赋值,trackr,查找可以看到r=v.generateSaltSign(n);,其中n为输入待翻译的字符串:继续跟进generateSaltSign函数,点击跳转到r函数,这里可以看到密钥加密代码:varr=function(e){vart=n.md5(navigator.appVersion),r=""+(newDate).getTime(),i=r+parseInt(10*Math.random(),10);return{ts:r,bv:t,salt:i,sign:n.md5("fanyideskweb"+e+i+"Y2FYu%TNSbMCxc3t2u^XT")}};解析此密钥加密代码:navigator.appVersion是UserAgentbv的值,由UserAgent通过MD5加密。ts的值是13位时间戳的值,salt的值是在ts的值上加上一个0-9的随机整数得到的。sign的值由待翻译的字符串、salt的值和另外两个固定的字符串组成,再经过MD5加密得到最终结果。这个过程比较简单,可以直接用Python重现:importtimeimportrandomimporthashlibquery="stringtobetranslated"user_agent="Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.124Safari/537.36"lts=str(int(time.time()*1000))#13位时间戳,单位毫秒salt=lts+str(random.randint(0,9))#13位时间戳+随机数,生成salt值sign="fanyideskweb"+query+salt+"Y2FYu%TNSbMCxc3t2u^XT"#拼接字符串形成signsign=hashlib.md5(sign.encode()).hexdigest()#对sign进行MD5加密生成最终的sign值bv=hashlib.md5(user_agent.encode()).hexdigest()#用MD5加密UA,生成bv值或者直接引用JS,使用nodejs中的加密模块CryptoJS进行MD5加密,改写JS如下://引用crypto-js加密模块varCryptoJS=require('crypto-js')functiongetEncryptedParams(data,ua){varbv=CryptoJS.MD5(ua).toString(),lts=""+(newDate).getTime(),salt=lts+parseInt(10*Math.random(),10)varsign=CryptoJS.MD5('fanyideskweb'+data+salt+']BjuETDhU)zqSxf-=B#7m').toString()return{bv:bv,lts:lts,??salt:salt,sign:sign}}完整代码youdao_encrypt.js获取加密参数salt,sign,bv://reference到crypto-js加密模块varCryptoJS=require('crypto-js')functiongetEncryptedParams(data,ua){varbv=CryptoJS.MD5(ua).toString(),lts=""+(newDate).getTime(),salt=lts+parseInt(10*Math.random(),10)varsign=CryptoJS.MD5('fanyideskweb'+data+salt+']BjuETDhU)zqSxf-=B#7m').toString()return{bv:bv,lts:lts,??salt:salt,sign:sign}}//varua="Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.124Safari/537.36"//vardata="测试"//console.log(getEncryptedParams(data,ua));youdaofanyi.py#!/usr/bin/envpython3#-*-coding:utf-8-*-importtimeimportrandomimporthashlibimportexecjsimportrequeststranslate_url='https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'user_agent='Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.124Safari/537.36'defget_translation_result(parameters):headers={'User-Agent':user_agent,'Host':'fanyi.youdao.com','来源':'https://fanyi.youdao.com','Referer':'https://fanyi.youdao.com/','X-Requested-With':'XMLHttpRequest','sec-ch-ua':'"Not;ABrand";v="99","GoogleChrome";v="91","Chromium";v="91"','Cookie':'OUTFOX_SEARCH_USER_ID="-1848382357@10.169.0.84";___rl__test__cookies=1625907853887;OUTFOX_SEARCH_USER_ID_NCOO=132978720.55854891'}response=requests.post(url=translate_url,headers=headers,data=parameters)result=response.json()['translateResult'][0][0]['tgt']returnresultdefget_parameters(query,translate_from,translate_to):lts=str(int(time.time()*1000))#以毫秒为单位的13位时间戳salt=lts+str(random.randint(0,9))#13位时间戳+随机数,生成盐值sign="fanyideskweb"+query+salt+"Y2FYu%TNSbMCxc3t2u^XT"#连接字符串形成符号sign=hashlib.md5(sign.encode()).hexdigest()#将符号执行MD5加密生成最终符号值bv=hashlib.md5(user_agent.encode()).hexdigest()#用MD5加密UA生成bv值参数={'i':query,'from':translate_from,'to':translate_to,'smartresult':'dict','client':'fanyideskweb','salt':salt,'sign':sign,'lts':lts,??'bv':bv,'doctype':'json','version':'2.1','keyfrom':'fanyi.web','action':'FY_BY_REALTlME'}returnparametersdefget_parameters_by_javascript(query,translate_from,translate_to):withopen('youdao_encrypt.js','r',encoding='utf-8')asf:youdao_js=f.read()params=execjs.compile(youdao_js).call('get_params',query,user_agent)#通过JavaScript代码获取各个参数bv=hashlib.md5(user_agent.encode()).hexdigest()#用MD5加密UA生成bv值parameters={'i':query,'from':translate_from,'to':translate_to,'smartresult':'dict','client':'fanyideskweb','salt':params['salt'],'sign':params['sign'],'lts':params['lts'],'bv':bv,'doctype':'json','version':'2.1','keyfrom':'fanyi.web','action':'FY_BY_REALTlME'}returnparametersdefmain():query=input('请输入要翻译的文字:')#原始语言,目标语言,默认自动处理translate_from=translate_to='AUTO'#通过Python获取加密参数或通过JavaScript获取参数,二者选其一param=get_parameters_by_python(query,translate_from,translate_to)#param=get_parameters_by_javascript(query,translate_from,translate_to)result=get_translation_result(param)print('翻译结果为:',result)if__name__=='__main__':main()
