JS逆向——某道翻译
文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,如有侵权,请联系作者立即删除!
- 目标网站:aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tL2luZGV4Lmh0bWwjLw==
一、定位接口
- 使用Chrome浏览器,打开Network进行抓包
- 输入要翻译的字符串:Hello World !
页面没有重新加载,初步判断是Ajax请求,我们看 Fetch/XHR请求,有两个请求
- 分析接口
经过查看分析,key的请求返回内容中不是我们需要的信息,只剩下webtranslate返回的内容,但是返回的内容是一长串字符串,我们先看一下请求参数,然后再换个要翻译的内容,看看参数有哪些变化。
- 参数对比
两次请求参数对比,发现,只有i、sign、mysticTime三个参数发生了变化
i:要翻译的字符串
sign:加密字符串
mysticTime:1701264377572,13位数字字符串,去掉后三位放入时间戳转换工具,发现就是时间戳
- 寻找sign加密位置
全局搜索sign:(小技巧),搜索的位置打上断点,逐个排除
再次请求,返现断点这个位置暂停,发现mysticTime就是时间戳
进入k(o, e)函数,看一下函数构造
执行会发现,k(o, e)函数右进入了j(e)函数,进行了一些列跟MD5有关的操作,先把这些函数抠出来
在看k(o, e)函数的传参,o是时间戳,e呢?
通过堆栈不难发现t就是e,那这个值怎么生成的(我这里查看了很久都没找到),但是发现不管翻译的内容如何,这t的值是固定,我们可以写死。
所以抠出的JS代码如下图,我们调用输出一下:
var t='fsdsogkndfokasodnaso'; var e=new Date().getTime() function j(e) { return c.a.createHash("md5").update(e.toString()).digest("hex") } function k(e, t) { return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`) } console.log(k(e,t))
ReferenceError: u is not defined u未定义
在继续打上断点看一下
在JavaScript中``反引号为模板字符串,反引号包括的字符串中出现${}是占位符的意思,相当于Python的f'{}'
观察u的值,通过测试发现u的值和d的值也是固定,我们也可以写死
再次运行代码,提示ReferenceError: c is not defined,c未定义,我们看一下内容,明显是MD5加密,使用Python MD5或者Node.js的都行,这里我用Node.js的的,crypto代替c.a
var crypto = require('crypto'); var t='fsdsogkndfokasodnaso'; var u="fanyideskweb" var d="webfanyi" var e=new Date().getTime() function j(e) { return crypto.createHash("md5").update(e.toString()).digest("hex") } function k(e, t) { return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`) } console.log(k(e,t))
再次运行,发现运行成功
对比页面上的加密字符串(防止魔改MD5),发现跟页面上的加密字符串不一致
在进行分析,组成加密字符串的时间戳一直再变动,所以生成的加密字符串不一致,那我们传入跟页面上一样的字符串在本地JS代码中测试一下
这次生成的加密字符串一致了
开始编写程序,请求接口看看返回的内容
JS代码:
var crypto = require('crypto'); var u="fanyideskweb" var d="webfanyi" function j(e) { return crypto.createHash("md5").update(e.toString()).digest("hex") } function return_sign(e, t) { return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`) }
Python代码
import time import execjs import requests def get_sign(t): with open("1.js", "r", encoding='utf-8') as f: read_js = f.read() e = 'fsdsogkndfokasodnaso' sign = execjs.compile(read_js).call('return_sign', t,e) return sign def get_web(str1, t): url = 'https://dict.youdao.com/webtranslate' header = { "Content-Type": "application/x-www-form-urlencoded", "Referer": "https://fanyi.youdao.com/index.html", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36", } cookie={ "OUTFOX_SEARCH_USER_ID_NCOO":"1880472979.5706484", "OUTFOX_SEARCH_USER_ID":"-320001268@240e:3b8:2e6b:8db0:7dde:588a:9908:d4bb" } sign = get_sign(t) data = { "i": str1, "from": "auto", "to": "", "dictResult": "true", "keyid": "webfanyi", "sign": sign, "client": "fanyideskweb", "product": "webfanyi", "appVersion": "1.0.0", "vendor": "web", "pointParam": "client,mysticTime,product", "mysticTime": t, "keyfrom": "fanyi.web", "mid": "1", "screen": "1", "model": "1", "network": "wifi", "abtest": "0", "yduuid": "abcdefg" } resp = requests.post(url, headers=header,cookies=cookie, data=data) print(resp.status_code) print(resp.text) if __name__ == '__main__': str1 = 'Hello Wodeld !' t = time.time() get_web(str1, t)
运行之后发现返回的加密的字符串
在Ajax请求位置返回内容,也就是得到sign值之后,继续跟踪,寻找解密函数,会发执行完这里右侧a中就会出现翻译内容,确定解密函数位置
进入解密函数,看一下执行逻辑,抠出代码
对e.alloc跟踪,你会发现,这里出现Uint8Arry函数,还有一个图标
点击这个图标,然后会弹出以下内容
怎么看着像是内存呀,我们查查Uint8Arry的用法
Uint8Arry:数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
我们用Node.js中Buffer.alloc代替
进入y(o)函数,发现就是MD5函数,我们引入crypto包,代替c.a
运行代码,
运行后报错: 'gbk' codec can't decode byte 0xb7 in position 68: illegal multibyte sequenc
execjs包编码问题在引入前修改一下编码:
import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')
再次运行,得到正确结果
完整1.js代码
var crypto = require('crypto'); var u="fanyideskweb" var d="webfanyi" function j(e) { return crypto.createHash("md5").update(e.toString()).digest("hex") } function return_sign(e, t) { return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`) }
完整2.js代码
var crypto = require('crypto'); function return_text(t, o, n) { if (!t) return null; const a = Buffer.alloc(16, crypto.createHash("md5").update(o).digest()) , i = Buffer.alloc(16, crypto.createHash("md5").update(n).digest()) , r = crypto.createDecipheriv("aes-128-cbc", a, i); let s = r.update(t, "base64", "utf-8"); return s += r.final("utf-8"), s }
完整Python代码
import subprocess from functools import partial subprocess.Popen = partial(subprocess.Popen, encoding='utf-8') import time import execjs import requests def get_sign(t): with open("1.js", "r", encoding='utf-8') as f: read_js = f.read() e = 'fsdsogkndfokasodnaso' sign = execjs.compile(read_js).call('return_sign', t, e) return sign def get_text(str1): with open("2.js", "r", encoding='utf-8') as f: read_js = f.read() o="ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl" n="ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4" str2 = execjs.compile(read_js).call('return_text', str1,o,n) return str2 def get_web(str1, t): url = 'https://dict.youdao.com/webtranslate' header = { "Content-Type": "application/x-www-form-urlencoded", "Referer": "https://fanyi.youdao.com/index.html", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36", } cookie = { "OUTFOX_SEARCH_USER_ID_NCOO": "1880472979.5706484", "OUTFOX_SEARCH_USER_ID": "-320001268@240e:3b8:2e6b:8db0:7dde:588a:9908:d4bb" } sign = get_sign(t) data = { "i": str1, "from": "auto", "to": "", "dictResult": "true", "keyid": "webfanyi", "sign": sign, "client": "fanyideskweb", "product": "webfanyi", "appVersion": "1.0.0", "vendor": "web", "pointParam": "client,mysticTime,product", "mysticTime": t, "keyfrom": "fanyi.web", "mid": "1", "screen": "1", "model": "1", "network": "wifi", "abtest": "0", "yduuid": "abcdefg" } resp = requests.post(url, headers=header, cookies=cookie, data=data) if resp.status_code == 200: str3 = get_text(resp.text) print(str3) if __name__ == '__main__': str1 = 'Hello World !' t = time.time() get_web(str1, t)
End !!!
本文来自博客园,作者:小二哥呀,转载请注明原文链接:https://www.cnblogs.com/toddywang/p/17869565.html