1、【JS 逆向百例】有道翻译接口参数逆向

2023-10-10 00:20

本文主要是介绍1、【JS 逆向百例】有道翻译接口参数逆向,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【JS 逆向百例】有道翻译接口参数逆向

1、逆向目标

  • 目标:有道翻译接口参数
  • 主页:https://fanyi.youdao.com/
  • 接口:https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
  • 逆向参数:

​ Form Data:

  • salt: 16261583727540

  • sign: 151e4b19b07ae410e0e1861a6706d30c

  • bv: 5b3e307b66a6c075d525ed231dcc8dcd

2、逆向过程

​ 抓包分析

我们在有道翻译页面随便输入文字,可以看到没有刷新页面,翻译结果就出来了,由此可以推断是 Ajax 加载的,打开开发者工具,选择 XHR 过滤 Ajax 请求,可以看到有一条 URL 为 https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule 的 POST 请求,当我们输入“测试”的时候,他返回的数据类似于如下结构:

{"translateResult": [[{"tgt": "test","src": "测试"}]],"errorCode": 0,"type": "zh-CHS2en","smartResult": {"entries": ["", "[试验] test\r\n", "measurement\r\n"],"type": 1}
}
  • translateResult 是翻译的结果,smartResult 是智能推荐的其他翻译,那么这个 URL 就是我们需要的翻译接口了。

  • 由于是 POST 请求,我们观察它的 Form Data:

    • i:待翻译的字符串;
    • from:待翻译的语言;
    • to:目标语言;
    • lts:时间戳;
    • smartresultclientdoctypeversionkeyfrom:固定值;
    • action:实时翻译 FY_BY_REALTlME、手动点击翻译 FY_BY_CLICKBUTTION
    • saltsignbv 的值每次会改变,需要进一步分析。

在这里插入图片描述

参数逆向

  • saltsignbv 三个加密参数,全局搜索任意一个,搜索结果比较多,依次对比,可以发现 fanyi.min.js 文件第 8969 行左右开始,Form Data 所有的参数都齐全了,埋下断点调试一下,可以看到所有数据和最终结果一致,加密的四个参数都在 r 当中取值,跟踪 r,往上找可以看到 r = v.generateSaltSign(n);,其中 n 是输入的待翻译的字符串:

- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uafU8lsy-1652412833162)(1、【JS 逆向百例】有道翻译接口参数逆向/image-20220513104655765.png)]

  • 继续跟进 generateSaltSign 函数,点击跳转到 r 函数,这里可以看到关键的加密代码:

  • 在这里插入图片描述

  • var r = function(e) {var t = n.md5(navigator.appVersion), r = "" + (new Date).getTime(), i = r + parseInt(10 * Math.random(), 10);return {ts: r,bv: t,salt: i,sign: n.md5("fanyideskweb" + e + i + "Y2FYu%TNSbMCxc3t2u^XT")}
    };
    
  • 分析这段关键加密代码:

    • navigator.appVersion 就是 UserAgent
    • bv 的值由 UserAgent 经过 MD5 加密得到
    • ts 的值为 13 位时间戳
    • salt 的值由 ts 的值加上一个 0-9 的随机整数得到
    • sign 的值由待翻译的字符串、salt 的值和另外两个固定的字符串组成,再由 MD5 加密得到最终结果
  • 这个过程比较简单,可以直接使用 Python 来复现:

  • import time
    import random
    import hashlibquery = "待翻译字符串"
    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"lts = str(int(time.time() * 1000))                                # 以毫秒为单位的 13 位时间戳
    salt = lts + str(random.randint(0, 9))                            # 13 位时间戳+随机数字,生成 salt 值
    sign = "fanyideskweb" + query + salt + "Y2FYu%TNSbMCxc3t2u^XT"    # 拼接字符串组成 sign
    sign = hashlib.md5(sign.encode()).hexdigest()                     # 将 sign 进行 MD5 加密,生成最终 sign 值
    bv = hashlib.md5(user_agent.encode()).hexdigest()                 # 对 UA 进行 MD5 加密,生成 bv 值
    
  • 或者直接引用 JS,使用 nodejs 里面的加密模块 CryptoJS 来进行 MD5 加密,改写 JS 如下:

  • // 引用 crypto-js 加密模块
    var CryptoJS = require('crypto-js')function getEncryptedParams(data, ua) {var bv = CryptoJS.MD5(ua).toString(), lts = "" + (new Date).getTime(), salt = lts + parseInt(10 * Math.random(), 10)var sign = CryptoJS.MD5('fanyideskweb'+data+salt+']BjuETDhU)zqSxf-=B#7m').toString()return {bv: bv, lts: lts, salt: salt, sign: sign}
    }
    

3、完整代码

  • youdao_encrypt.js

  • 获取加密参数 saltsignbv

  • // 引用 crypto-js 加密模块
    var CryptoJS = require('crypto-js')function getEncryptedParams(data, ua) {var bv = CryptoJS.MD5(ua).toString(),lts = "" + (new Date).getTime(),salt = lts + parseInt(10 * Math.random(), 10)var sign = CryptoJS.MD5('fanyideskweb' + data + salt + ']BjuETDhU)zqSxf-=B#7m').toString()return { bv: bv, lts: lts, salt: salt, sign: sign }
    }// var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    // var data = "测试"
    // console.log(getEncryptedParams(data, ua));
    

youdaofanyi.py

  • #!/usr/bin/env python3
    # -*- coding: utf-8 -*-import time
    import random
    import hashlibimport execjs
    import requeststranslate_url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'def get_translation_result(parameters):headers = {'User-Agent': user_agent,'Host': 'fanyi.youdao.com','Origin': 'https://fanyi.youdao.com','Referer': 'https://fanyi.youdao.com/','X-Requested-With': 'XMLHttpRequest','sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"','Cookie': 'OUTFOX_SEARCH_USER_ID="-1848382357@10.169.0.84"; ___rl__test__cookies=1625907853887; OUTFOX_SEARCH_USER_ID_NCOO=132978720.55854891'}response = requests.post(url=translate_url, headers=headers, data=parameters)result = response.json()['translateResult'][0][0]['tgt']return resultdef get_parameters_by_python(query, translate_from, translate_to):lts = str(int(time.time() * 1000))                                # 以毫秒为单位的 13 位时间戳salt = lts + str(random.randint(0, 9))                            # 13 位时间戳+随机数字,生成 salt 值sign = "fanyideskweb" + query + salt + "Y2FYu%TNSbMCxc3t2u^XT"    # 拼接字符串组成 signsign = hashlib.md5(sign.encode()).hexdigest()                     # 将 sign 进行 MD5 加密,生成最终 sign 值bv = hashlib.md5(user_agent.encode()).hexdigest()                 # 对 UA 进行 MD5 加密,生成 bv 值parameters = {'i': query,'from': translate_from,'to': translate_to,'smartresult': 'dict','client': 'fanyideskweb','salt': salt,'sign': sign,'lts': lts,'bv': bv,'doctype': 'json','version': '2.1','keyfrom': 'fanyi.web','action': 'FY_BY_REALTlME'}return parametersdef get_parameters_by_javascript(query, translate_from, translate_to):with open('youdao_encrypt.js', 'r', encoding='utf-8') as f:youdao_js = f.read()params = execjs.compile(youdao_js).call('get_params', query, user_agent)    # 通过 JavaScript 代码获取各个参数bv = hashlib.md5(user_agent.encode()).hexdigest()                           # 对 UA 进行 MD5 加密,生成 bv 值parameters = {'i': query,'from': translate_from,'to': translate_to,'smartresult': 'dict','client': 'fanyideskweb','salt': params['salt'],'sign': params['sign'],'lts': params['lts'],'bv': bv,'doctype': 'json','version': '2.1','keyfrom': 'fanyi.web','action': 'FY_BY_REALTlME'}return parametersdef main():query = input('请输入要翻译的文字:')# 原始语言,目标语言,默认自动处理translate_from = translate_to = 'AUTO'# 通过 Python 获取加密参数或者通过 JavaScript 获取参数,二选一param = get_parameters_by_python(query, translate_from, translate_to)# param = get_parameters_by_javascript(query, translate_from, translate_to)result = get_translation_result(param)print('翻译的结果为:', result)if __name__ == '__main__':main()
    

执行结果:
在这里插入图片描述

这篇关于1、【JS 逆向百例】有道翻译接口参数逆向的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/176617

相关文章

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

SpringBoot+Redis防止接口重复提交问题

《SpringBoot+Redis防止接口重复提交问题》:本文主要介绍SpringBoot+Redis防止接口重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录前言实现思路代码示例测试总结前言在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。例

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Java中的Closeable接口及常见问题

《Java中的Closeable接口及常见问题》Closeable是Java中的一个标记接口,用于表示可以被关闭的对象,它定义了一个标准的方法来释放对象占用的系统资源,下面给大家介绍Java中的Clo... 目录1. Closeable接口概述2. 主要用途3. 实现类4. 使用方法5. 实现自定义Clos

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

java对接第三方接口的三种实现方式

《java对接第三方接口的三种实现方式》:本文主要介绍java对接第三方接口的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录HttpURLConnection调用方法CloseableHttpClient调用RestTemplate调用总结在日常工作

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

一文详解PostgreSQL复制参数

《一文详解PostgreSQL复制参数》PostgreSQL作为一款功能强大的开源关系型数据库,其复制功能对于构建高可用性系统至关重要,本文给大家详细介绍了PostgreSQL的复制参数,需要的朋友可... 目录一、复制参数基础概念二、核心复制参数深度解析1. max_wal_seChina编程nders:WAL