由于粉丝们的强烈邀请,希望出一期适合新手练习的文章;故这期出一篇某道翻译的JS逆向讲解文章。本次记录完整流程如下,供大家交流学习。若文章内容有误,欢迎大家联系我指正!
特别声明:本公众号文章只作为学术研究,不用于其它用途。
目录
① 前言说明
② 网站分析
③ 参数验证
④ 断点调试
⑤ 算法还原
⑥ 思路总结
一、前言说明
今天给大家带来某道翻译的js逆向分析过程讲解,本次讲解主题相对以往来说来说难度系数不大。这也是有粉丝提到,能不能来点简单的网址练手,大家多多阅读!感谢新哥提供的资源内容。
二、网站分析
1、确定网站
打开指定网站地址,输入需要翻译的内容,截图如下:
2、接口分析
通过上面展示的翻译内容love关键字,打开浏览器开发者工具DevTools进行关键字搜索Search,定位内容如下图所示(这一块的流程细节可以查阅前面的文章内容):
3、参数分析
点击Payload参数界面,分析接口参数如下图所示:
请求方式:POST
请求参数分析如下:
salt、Its:时间戳格式,分别为13位、14位。
sign、bv:字符串长度为32位;初步分析为md5加密。
i:需要翻译的内容,变量值。
其他参数:都为固定值。
三、参数验证
将curl代码粘贴到Postman进行发包,如下:
curl 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule' \ -H 'Accept: application/json, text/javascript, */*; q=0.01' \ -H 'Accept-Language: zh-CN,zh;q=0.9' \ -H 'Cache-Control: no-cache' \ -H 'Connection: keep-alive' \ -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \ -H 'Cookie: OUTFOX_SEARCH_USER_ID_NCOO=720430864.4556929; OUTFOX_SEARCH_USER_ID="6724206@10.108.160.17"; _ntes_nnid=e16a3ad8b1d28737dfe71ed836f29839,1618477691016; _ga=GA1.2.677079640.1630767423; fanyi-ad-id=305426; fanyi-ad-closed=1; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcqVoEm5kDwx-C1xU9-x; ___rl__test__cookies=1649230170652' \ -H 'Origin: https://fanyi.youdao.com' \ -H 'Pragma: no-cache' \ -H 'Referer: https://fanyi.youdao.com/' \ -H 'Sec-Fetch-Dest: empty' \ -H 'Sec-Fetch-Mode: cors' \ -H 'Sec-Fetch-Site: same-origin' \ -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36' \ -H 'X-Requested-With: XMLHttpRequest' \ -H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "macOS"' \ --data-raw 'i=love&from=AUTO&to=AUTO&smartresult=dict&client=fanyideskweb&salt=16492301706541&sign=211a244f0b7872ce025e08c9f8a6050b<s=1649230170654&bv=af268bd4f2ded4e3923ec284cbfc70b3&doctype=json&version=2.1&keyfrom=fanyi.web&action=FY_BY_CLICKBUTTION' \ --compressed在参数内容不改变的情况下,该请求返回的response和页面结果一致。随意修改sign参数的值,再进行发包,响应结果如下:
四、断点调试
搜索指定关键字sign字段,搜索结果如下图所示:
点击js代码,打上断点进行刷新页面,进行调试,debug截图如下:
查看该段js代码进行js调试分析:
ts:时间戳,精确到毫秒,长度为13位。
salt:为ts字段 + 一个随机数,长度为14位。
bv:通过Console输出,为浏览器ua进行md5加密的结果,长度32位。
sign:fanyideskweb关键字tsYgy_4c=r#e#4EX^NUGUc5进行md5加密。
求证结果如下图所示:
/*函数的返回值r的结果如下*/{ts: '1649231441159', bv: 'af268bd4f2ded4e3923ec284cbfc70b3', salt: '16492314411598', sign: '79c614227ba72d6901896c30a009155d'}参数一一突破后,接下来进行Python算法还原吧!
五、算法还原
Python代码还原如下:
import requestsfrom hashlib import md5import timedef get_md5(text): sign = md5(text.encode()).hexdigest() return signdef start_requests(word): cookies = { # 'OUTFOX_SEARCH_USER_ID_NCOO': '720430864.4556929', 'OUTFOX_SEARCH_USER_ID': '"6724206"', } headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', # Requests sorts cookies= alphabetically # 'Cookie': 'OUTFOX_SEARCH_USER_ID_NCOO=720430864.4556929; OUTFOX_SEARCH_USER_ID="6724206@10.108.160.17"; _ntes_nnid=e16a3ad8b1d28737dfe71ed836f29839,1618477691016; _ga=GA1.2.677079640.1630767423; JSESSIONID=aaapVewQlzpRkf2XUkK-x; ___rl__test__cookies=1648800665966', 'Origin': 'https://fanyi.xxx.com', 'Pragma': 'no-cache', 'Referer': 'https://fanyi.xxx.com/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest', 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"macOS"', } params = { 'smartresult': [ 'dict', 'rule', ], } bv = get_md5( "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36") lts = str(int(time.time() * 1000)) salt = f"{lts}0" sign_text = f"fanyideskweb{word}\n{salt}Ygy_4c=r#e#4EX^NUGUc5" sign = get_md5(sign_text) data = { 'i': f'{word}\n', 'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': salt, # md5 'sign': sign, # md5 'lts': lts, 'bv': bv, 'doctype': 'json', 'version': '2.1', 'keyfrom': 'fanyi.web', 'action': 'FY_BY_CLICKBUTTION', } response = requests.post('https://fanyi.xxx.com/translate_o', headers=headers, params=params, cookies=cookies, data=data) print(response.text)if __name__ == '__main__': start_requests("强壮的")# 代码执行结果如下{"translateResult":[[{"tgt":"strong","src":"强壮的"}]],"errorCode":0,"type":"zh-CHS2en","smartResult":{"entries":["","strong\r\n","able-bodied\r\n","muscular\r\n"],"type":1}}四、思路总结
确定参数 > 断点调试 > 加密定位 > 算法还原 > 代码测试 > 验证结果 > 完毕
我是TheWeiJun,有着执着的追求,信奉终身成长,不定义自己,热爱技术但不拘泥于技术,爱好分享,喜欢读书和乐于结交朋友,欢迎加我微信与我交朋友。
分享日常学习中关于爬虫、逆向和分析的一些思路,文中若有错误的地方,欢迎大家多多交流指正☀️。