有dao翻译 sign 再分析

【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】
其实网上关于有道翻译分析sign签名加密方法的分析文章已经铺天盖地了,但是只不过前段时间刚好无疑看到相关文章,但是没有写返回数据解密的逻辑,想着自己还是去看一下,然后详细写个文章。
分析post请求sign
首先通过浏览器的F12中,可以看到有一条https://dict.youdao.com/webtranslate/key
这个地址的网络请求。这条请求中夹带着sign
,同时这条请求返回了aesIv
、aesKey
、secretKey
这3个参数,基本不用问,看字面意思就很明确,是aes
加密所需要的iv
填充密钥、key
加密密钥。具体如下图:
因为发现每次翻译前都会有这个url地址的请求,所以我们先根据这个url地址进行拦截。拦截含有/webtranslate/key
的请求。然后我们看一下,程序会断点到哪里。这个时候就要注意了,一般拦截断点的地方大概率都不是加密的地方都需要向上一点点找。
首先看绿色的①->②->③,然后从绿色的3跳到了绿色的圈内,然后再圈内看蓝色的①->②->③
其实这样看整体思路就是比较清晰了。sign
加密是在k(t)
函数内完成的,因为是/webtranslate/key
的请求,并不是翻译任何英文,所以参数t=undefined
就是空,没有定义。
那现在看一下k函数
里面的及S函数
的加密逻辑吧。这里除了变量t为空之外,其他的基本都是固定的,只有a取了当前的时间。把它都赋值上再简单看一下代码逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | function _(e) { //③注释:其实最终也就是取的md5值 return i.createHash("md5").update(e.toString()).digest("hex") } function S(e, t) { //②然后对上面的参数取md5值 return _(`client=${d}&mysticTime=${e}&product=${u}&key=${t}`) } function k(e, t) { const a = (new Date).getTime(); return { sign: S(a, e), //①注释:这里直接调用到了上面的函数,a就是当前的时间, e="asdjnjfenknafdfsdfsd" client: d="fanyideskweb", product: u="webfanyi", appVersion: m="1.0.0", vendor: h="web", pointParam: p="client,mysticTime,product", mysticTime: a, keyfrom: g="fanyi.web", mid: b=1, screen: f=1, model: v=1, network: A="wifi", abtest: y=0, yduuid: t || "abcdefg" //注释:因为t为空,所以这里肯定取值是"abcdefg" } } |
其实大致逻辑就很清晰了。不过这里有一个注意点就是
①当请求uri地址是/webtranslate/key
这个时,注意这个函数k(e="asdjnjfenknafdfsdfsd" , t=undefined)所以是取"client=fanyideskweb&mysticTime=1737873042843&product=webfanyi&key=asdjnjfenknafdfsdfsd"的md5值。
②当请求uri地址是/webtranslate
这个时,注意这个函数k(e="Vy4EQ1uwPkUoqvcP1nIu6WiAjxFeA3Y9"
, t=undefined)所以是取"client=fanyideskweb&mysticTime=1737873219314&product=webfanyi&key=Vy4EQ1uwPkUoqvcP1nIu6WiAjxFeA3Y9"的md5值。
至此整体逻辑就是,首先每次都请求/webtranslate/key
这个接口,然后获取返回的aesIv
、aesKey
、secretKey
这3个参数,然后再通过secretKey
去组合进行md5加密你要翻译的英文,然后变为sign,其他的值除了那个时间戳,都是固定的。
至此请求分析完毕,但是!!!大家看下图:
针对翻译的请求的返回数据是加密的,那么我们直接跟进这个请求的返回结果继续追踪一下。如下图:
其实到这里就已经明显的不能再明显了。只要再跟进da.A.decodeData(o, ha.A.state.text.decodeKey, ha.A.state.text.decodeIv) 这个函数就OK了。
ha.A.state.text.decodeKey = aesKey = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl"
ha.A.state.text.decodeIv = aesIv = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4"
这些都是刚刚通过/webtranslate/key
这个接口获取到的数据,而刚刚接口o
就是返回的密文,我们再跟进去查看一下。
当跟进来后就到了这里,注意仔细看图,O = (e, t, a)
分别就对应上面的传参。
这里做一个简单的解释l.alloc(16, T(t))
这里的T()
函数就是进行md5加密,如下图:
注意下方有一个base64,明显就是要针对返回值进行base64解码,但是返回值中有"-"、"_"明显不对,base64中没有这个字符,在这个地方我思考了很久没有明白为什么。通过找别人分析的文章发现有一个人说如下:
后来自己做了一个详细的跟进,发现了关键点,如下图:
然后把整段代码喂给了gpt,最终gpt答复如下:
所以就简单了,后续遇到类似base64的乱码别放弃,追踪到指定解密位置,直接让gpt去一点点看,给你答案就OK了。那至此就非常非常简单了。
最终成品代码参考:https://www.cnblogs.com/hp-mzx/p/17684788.html
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏