不知道为什么好像网上 js 逆向都属以有道翻译为例子,以前认为 js 逆向很难,但是现在还是要学习。
参考:https://mp.weixin.qq.com/s/a-ORkG5XGSAP_-6GNilBbQ
编译IDA:pycharm 社区版
python版本:python3.7.4
用到的库:requests、time、hashlib、random
1、找到响应
用浏览器打开有道的在线翻译,按下F12并在框中输入任意中文来观察其网页变化。
可以看到在 http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
中找到翻译的响应内容
2、分析请求
这是一个 POST 请求,且表单参数很多
修改要翻译的内容,可以看到每次改变的只有 i、salt、sign、ts、bv,其他的都没有改变
但其实改变翻译语言还可以看到 from、to、action 的改变,以下是全部解释
'i': #输入内容
'from': #原始语言
'to': #翻译语言
'smartresult': #结果类型(固定)
'client': #监听器(固定)
'salt': #加密
'sign': #加密
'ts': #时间戳
'bv': #浏览器User-Agent
'doctype': #json类型
'version': #版本
'keyfrom': #请求来源(固定)
'action': #方式(有实时FY_BY_REALTlME、换语言lan-select、手动点击FY_BY_CLICKBUTTION)
3、js 逆向
一般现在很多都是 js 就可以处理的,所以这些就可以分析 js 来破解参数规则
打开调试器,查找到 fanyi.min.js
,ctrl+F 查找 i、salt、sign、ts、bv
其中之一,一般选单词数比较长的,因为不会交叉覆盖好找。
找到 Ajax 异步提交 data 表单,继续查找,找到他们之间的逻辑
下面就是数据如何处理得到 data 表单的
ts 就是 r 当前时间的时间戳
bv 就是 t 对浏览器 UA 进行 MD5 加密
salt 就是 i 时间戳加上随机时间
sign 就是字符串加入要翻译的内容、i 进行MD5 加密
ts = str(int(time.time()))
salt = str(int(time.time()) + random.random() * 10 + 10)
sign = 'fanyideskweb' + word + salt + 'n%A-rKaT5fb[Gy?;N5@Tj'
sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
bv = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0'
bv = hashlib.md5(bv.encode('utf-8')).hexdigest()
4、最后POST提交表单即可
可以直接使用
# !/usr/bin/python
# -*- coding: utf-8 -*-
# @Time : 2019/12/19 13:05
# @Author : ljf
# @File : youdao.py
import requests
import time
import hashlib
import random
class youdao_crawl:
def __init__(self):
"""
初始化内容
"""
self.url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0',
'Referer': 'http://fanyi.youdao.com/',
'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; [email protected]; OUTFOX_SEARCH_USER_ID_NCOO=62105739.76007765; JSESSIONID=aaaNhy9FAvO3l7Ye5HC8w; ___rl__test__cookies=1576732583589'
}
self.data = {
'i': None,
'from': 'AUTO',
'to': 'AUTO',
'smartresult': 'dict',
'client': 'fanyideskweb',
'salt': None,
'sign': None,
'ts': None,
'bv': None,
'doctype': 'json',
'version': '2.1',
'keyfrom': 'fanyi.web',
'action': 'FY_BY_REALTlME'
}
# def language(self, original, translate):
# """
# Args:
# original: 原始语言
# translate: 翻译语言
# Returns: 无
# """
# type = {
# 'AUTO': 'AUTO',
# '中文': 'zh-CHS',
# '英语': 'en',
# '日语': 'ja',
# '韩语': 'ko',
# '法语': 'fr',
# '德语': 'de',
# '俄语': 'ru',
# '西班牙语': 'es',
# '葡萄牙语': 'pt',
# '意大利语': 'it',
# '越南语': 'vi',
# '印尼语': 'id',
# '阿拉伯语': 'ar',
# }
# self.data['from'] = type[original]
# self.data['to'] = type[translate]
def translate(self, word):
"""
Args:
word: 要翻译的内容
Returns: 无
"""
ts = str(int(time.time()))
salt = str(int(time.time()) + random.random() * 10 + 10)
sign = 'fanyideskweb' + word + salt + 'n%A-rKaT5fb[Gy?;N5@Tj'
sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
bv = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0'
bv = hashlib.md5(bv.encode('utf-8')).hexdigest()
self.data['i'] = word
self.data['salt'] = salt
self.data['sign'] = sign
self.data['ts'] = ts
self.data['bv'] = bv
# def run(self, original, translate, word):
# youdao.language(original,translate)
def run(self, word):
"""
Args:
word: 要翻译的内容
Returns: 翻译后的内容
"""
youdao.translate(word)
re = requests.post(self.url, headers=self.headers, data=self.data)
return re.json()['translateResult'][0][0].get('tgt')
if __name__ == '__main__':
youdao = youdao_crawl()
while True:
content = input("请输入您需要翻译的内容:")
if content == "q":
break
trans = youdao.run(content)
print(trans)
因为是默认的缘故,所以中文都会翻译成英语,其它语言都会翻译成中文
1、疑惑
不知道为什么这些应该都有时效性,每次刷新内置参数都不一样,但是现在还可以,难道是这些参数是固定的只是每次给的都不一样
2、选择语言
选择语言也不麻烦,但是影响代码长度,所以一般默认自动读取就可以了
3、action
换语言:lan-select
实时:FY_BY_REALTlME
手动点击:FY_BY_CLICKBUTTION
4、其它
其他的参数,跟进版本应该没问题