运维开发网

【JS逆向】破解DeepL和有道翻译加密策略

运维开发网 https://www.qedev.com 2021-01-07 12:53 出处:51CTO 作者:mb5ff2f2ed7d163
现在有很多翻译软件能够同时提供多个网站的翻译结果,比如非常好用的copytranslator:copytranslator其实它们也是调用了这些翻译网站的API,下面选择DeepL翻译和有道翻译来尝试破解。DeepL翻译网址:https://www.deepl.com/translatorDeepLy翻译宣称是全世界最好的机器翻译。DeepL先随便翻译一个句子:摸鱼确实快乐尝试一下在开发中工具中获
现在有很多翻译软件能够同时提供多个网站的翻译结果,比如非常好用的copytranslator

【JS逆向】破解DeepL和有道翻译加密策略

copytranslator其实它们也是调用了这些翻译网站的API,下面选择DeepL翻译有道翻译来尝试破解。

DeepL翻译

网址:https://www.deepl.com/translatorDeepLy翻译宣称是全世界最好的机器翻译。

【JS逆向】破解DeepL和有道翻译加密策略

DeepL先随便翻译一个句子:

【JS逆向】破解DeepL和有道翻译加密策略

摸鱼确实快乐尝试一下在开发中工具中获取它翻译的API:https://www2.deepl.com/jsonrpc,提交的参数为:

【JS逆向】破解DeepL和有道翻译加密策略

Request Payload可以看出每个参数都有很明确的含义,并没有加密的参数。id这个参数经过我的测试,随便填一个数都可以。

import time

import random

import requests

def deepl_translator(sentence):

    sentence = '"' + sentence + '"'

    u_sentence = sentence.encode("unicode_escape").decode()

    data = '{"jsonrpc":"2.0","method": "LMT_handle_jobs","params":{"jobs":[{"kind":"default","raw_en_sentence":' + sentence + ',"raw_en_context_before":[],"raw_en_context_after":[],"preferred_num_beams":4,"quality":"fast"}],"lang":{"user_preferred_langs":["EN","ZH"],"source_lang_user_selected":"auto","target_lang":"EN"},"priority":-1,"commonJobParams":{},"timestamp":' + str(

        int(time.time() * 10000)) + '},"id":' + str(

            random.randint(1, 100000000)) + '}'

    r = requests.post('https://www2.deepl.com/jsonrpc',

                      headers={'content-type': 'application/json'},

                      data=data.encode())

    return r.json()['result']['translations'][0]['beams']

  

print(deepl_translator('摸鱼就开心'))

# 输出:

# [{'postprocessed_sentence': "I'm happy when I touch the fish.", 'num_symbols': 12},

#  {'postprocessed_sentence': "You'll be happy if you touch the fish.", 'num_symbols': 13},

#  {'postprocessed_sentence': "It's fun to touch fish.", 'num_symbols': 10},

#  {'postprocessed_sentence': "You'll be happy if you touch the fish", 'num_symbols': 12}]

返回的是最佳的四个翻译,num_symbols的含义我不是很确定,猜测是代表置信度。

有道翻译

网址:http://fanyi.youdao.com/在有道翻译中同样翻译“摸鱼很快乐”这句话:

【JS逆向】破解DeepL和有道翻译加密策略

有道翻译

【JS逆向】破解DeepL和有道翻译加密策略

Form Data容易发现fromtosmartresultclientdoctypeversionkeyfromaction 都是固定参数,不用调整。需要获取的参数:

  • i:输入
  • saltlts:很像时间戳,但是位数不同
  • signbv:长度都是32位,很可能是MD5加密以后得到的值

全局搜索salt参数:全局搜索格式化这个js文件后,在文件内再次搜索salt,定位到这里:

【JS逆向】破解DeepL和有道翻译加密策略

定位加密其实看到这里,每个参数生成的逻辑就应该很清晰了,为了讲的更清楚,我们在这里打上一个断点,然后重新翻译一下。

【JS逆向】破解DeepL和有道翻译加密策略

打上断点,仔细观察我们分析一下各个参数生成的逻辑:

  • e为输入的句子
  • navigator.appVersion其实就是User-Agentt为它进行md5加密后的结果

【JS逆向】破解DeepL和有道翻译加密策略

在控制台调试

  • r为当前时间的时间戳

  • ir在末尾加上一个随机整数

  • signei拼接后再分别在前后加上一个固定字符串,再进行md5加密后的结果

然后就能用Python还原整个加密过程了。

import time

import requests

from hashlib import md5

def youdao_translator(sentence):

    

    # 获取参数

    lts = str(int(time.time() * 1000))

    salt = str(int(time.time() * 10000))

    ua = '5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36'

    bv = md5(ua.encode()).hexdigest()

    sign = md5(('fanyideskweb' + sentence + salt + ']BjuETDhU)zqSxf-=B#7m').encode()).hexdigest()

    

    # 创建一个会话来获取cookie

    s = requests.session()

    s.get('http://fanyi.youdao.com')

    

    # headers中必要的三个参数,其他的都不必要

    headers = {

        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36',

        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',

        'Referer': 'http://fanyi.youdao.com/',

    }

    data = {

      'i': sentence,

      'from': 'AUTO',

      'to': 'AUTO',

      'smartresult': 'dict',

      'client': 'fanyideskweb',

      'salt': salt,

      'sign': sign,

      'lts': lts,

      'bv': bv,

      'doctype': 'json',

      'version': '2.1',

      'keyfrom': 'fanyi.web',

      'action': 'FY_BY_REALTlME'

    }

    r = s.post('http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule', headers=headers, data=data)

    return r.json()['translateResult'][0][0]['tgt']

  

  

print(youdao_translator('不想学习'))

# 输出:

# "Don't want to learn"

0

精彩评论

暂无评论...
验证码 换一张
取 消