Loading... # js逆向爬虫1 目标:有道翻译 首先输入两个翻译,发现提交的参数请求中两个参数不同,一个是带time的,另一个是sign。很明显一个是时间生成器生成的数,另一个是做了加密的签名,很可能包含mysticTime的加密 <img src="http://xherlock.top/usr/uploads/2022/12/2480774246.png" alt="image-20221224231117551" style="zoom:67%;" style=""> 在截包器中搜索关键词sign,发现有很多js包含,不好定位;因此转而去直接搜索mysticTime,定位到app.js ![image-20221224231430496.png](http://xherlock.top/usr/uploads/2022/12/100857499.png) 查看源文件,格式化后Ctrl+F搜索定位mysticTime,发现只有一个匹配结果,且很容易看出sign后的那个b函数就是签名函数 ![image-20221224231548222.png](http://xherlock.top/usr/uploads/2022/12/3941740608.png) 打断点调试,输入一个新的翻译,页面来到sign前,此时t已经在前一行的getTime函数中得到值;只需知道sign函数即可,单步进入函数 ![image-20221224232029705.png](http://xherlock.top/usr/uploads/2022/12/123016899.png) 发现函数返回一个拼接的字符串(r="fanyideskweb",i="webfanyi"),并经过p函数加密处理,再次单步进入p函数 ![image-20221224232239587.png](http://xherlock.top/usr/uploads/2022/12/521569294.png) 此时这个函数看起来很像Crypto库的哈希函数加密的,光标移到方法名前的c.a,可以看到其下有很多方法,基本验证猜想 ![image-20221224232354743.png](http://xherlock.top/usr/uploads/2022/12/1783457524.png) 在网上搜索到了示例代码如下,格式完全一样 ![image-20221224232648330.png](http://xherlock.top/usr/uploads/2022/12/2972544874.png) 最后只需确定最开始f函数传入的e值,再次运行发现传入e值不变,仍然为"fsdsogkndfokasodnaso" 编写js代码 ~~~js const crypto = require('crypto'); const r = "fanyideskweb", i = "webfanyi"; function p(e) { return crypto.createHash("md5").update(e.toString()).digest("hex") } function b(e, t) { return p(`client=${r}&mysticTime=${e}&product=${i}&key=${t}`) } function f() { const e = 'fsdsogkndfokasodnaso', s = 'client,mysticTime,product', u = 'fanyi.web', l = '1.0.0', d = 'web'; const t = (new Date).getTime(); return { sign: b(t, e), client: r, product: i, appVersion: l, vendor: d, pointParam: s, mysticTime: t, keyfrom: u } } console.log(f()) ~~~ 输出如下,格式正确 <img src="http://xherlock.top/usr/uploads/2022/12/1457250398.png" alt="image-20221224234137615" style="zoom:50%;" style=""> 编写python发送翻译请求 ~~~python import requests import execjs ctx = execjs.compile(open('youdao.js', encoding='utf-8').read()) params = ctx.call('f') data = { 'i': '你好', 'from': 'zh-CHS', 'to': 'en', 'domain': '0', 'dictResult': 'true', 'keyid': 'webfanyi' } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54', 'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=976405377.6815147; OUTFOX_SEARCH_USER_ID=-198948307@211.83.126.235; _ga=GA1.2.1162596953.1667349221; search-popup-show=12-2', 'Referer': 'https://fanyi.youdao.com/' } data.update(params) results = requests.post('https://dict.youdao.com/webtranslate', data=data, headers=headers) print(results.text) ~~~ 发现返回结果被加密,说明前端做了解密处理,需要找到解密函数 ![image-20221225110003120.png](http://xherlock.top/usr/uploads/2022/12/2837328362.png) 从上一断点继续运行,很快就发现密文到明文的转换过程,可以看到下图蓝框中o接收了decode后的数据,并赋给a变量,而a变量正是解密后的数据,因此得出结论tn["a"].decodeData是关键解密函数 ![image-20221225110325162.png](http://xherlock.top/usr/uploads/2022/12/1240268966.png) 在这个函数上打断点后再次提交翻译输入,进入函数 ![image-20221225110843997.png](http://xherlock.top/usr/uploads/2022/12/2131987513.png) 复制该函数下来到js文件中测试 ![image-20221225111301360.png](http://xherlock.top/usr/uploads/2022/12/3241235010.png) ![image-20221225111237743.png](http://xherlock.top/usr/uploads/2022/12/296280898.png) 查询alloc函数发现属于Buffer下的方法,m函数也是c.a(Crypto)下的方法,直接替换为crypto 再次运行js,密文已经被解密 ![image-20221225111611881.png](http://xherlock.top/usr/uploads/2022/12/348459036.png) 运行python时发现始终报错,说是gbk编码问题 ![image-20221225112812183.png](http://xherlock.top/usr/uploads/2022/12/1810399365.png) **解决方法**:导入execjs前加入如下代码即可 ~~~python import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding="utf-8") ~~~ 最终效果图: ![image-20221225114102436.png](http://xherlock.top/usr/uploads/2022/12/448716846.png) 完整代码: youdao.py ~~~python import requests import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding="utf-8") import execjs translate_words = input('请输入要翻译的内容:') ctx = execjs.compile(open('youdao.js', encoding='utf-8').read()) params = ctx.call('f') data = { 'i': translate_words, 'from': 'AUTO', 'to': 'AUTO', 'domain': '0', 'dictResult': 'true', 'keyid': 'webfanyi' } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54', 'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=976405377.6815147; OUTFOX_SEARCH_USER_ID=-198948307@211.83.126.235; _ga=GA1.2.1162596953.1667349221; search-popup-show=12-2', 'Referer': 'https://fanyi.youdao.com/' } data.update(params) results = requests.post('https://dict.youdao.com/webtranslate', data=data, headers=headers) fanyi = eval(ctx.call('A', results.text)) print(fanyi['translateResult'][0][0]['tgt']) ~~~ youdao.js ~~~js const crypto = require('crypto'); const r = "fanyideskweb", i = "webfanyi"; function m(e) { return crypto.createHash("md5").update(e).digest() } function p(e) { return crypto.createHash("md5").update(e.toString()).digest("hex") } function b(e, t) { return p(`client=${r}&mysticTime=${e}&product=${i}&key=${t}`) } function f() { const e = 'fsdsogkndfokasodnaso', s = 'client,mysticTime,product', u = 'fanyi.web', l = '1.0.0', d = 'web'; const t = (new Date).getTime(); return { sign: b(t, e), client: r, product: i, appVersion: l, vendor: d, pointParam: s, mysticTime: t, keyfrom: u } } A = (t,o,n)=>{ o = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl" n = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4" if (!t) return null; const a = Buffer.alloc(16, m(o)) , r = Buffer.alloc(16, m(n)) , i = crypto.createDecipheriv("aes-128-cbc", a, r); let s = i.update(t, "base64", "utf-8"); return s += i.final("utf-8"), s } ~~~ 最后修改:2022 年 12 月 29 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 4 如果觉得我的文章对你有用,请随意赞赏
2 条评论
博主你好,请问怎么知道的alloc函数属于Buffer下的方法, 我进入之后发现是其他的方法,一直补充所缺的方法,后面把e.alloc 改为Buffer.alloc 就可以了, 那Buffer这个是哪里来的呢
很抱歉,最近忙于科研没有及时看博客留言。这里js逆向其实不需要太多js相关知识,通常这些网站作者不会去写一大堆实现方法,而是调用函数库。如果接触过C语言的话可以知道alloc大概是申请地址空间的函数,去百度/谷歌搜下“js alloc”就可以看到很多结果显示Buffer.alloc(),就直接调用就好了