首页 > 编程语言 >JavaScript逆向之有道翻译加解密全过程解析

JavaScript逆向之有道翻译加解密全过程解析

时间:2024-03-11 14:59:33浏览次数:18  
标签:函数 之有 JavaScript 加解密 mysticTime iv key import md5

本篇文章用于解析有道翻译中的加解密全过程

url:https://fanyi.youdao.com/index.html#/

加密

访问网址,输入框中随便输入一个英文单词,查看触发流量包,只看Fetch/XHR类型的。

这里主要关注webtranslate的这条,请求参数和响应数据都是有加密的,主要了解其的加解密逻辑。


根据url定位法,全局搜索webtranslate关键词,对应的就只有一个。

打断点,这里打断点要注意,由于是想要知道加解密逻辑,所以应该在里url最接近的地方打断点。

在输入框中在输入一旦内容,触发断点。

只有两个函数,一个是Object,一个是E,其中Object是原生代码,肯定不是加密逻辑,定位E函数的具体实现。


在该函数的第一行打上断点,让程序运行到这里。

流量包的传参中只有signmysticTime两个参数的值不知道是怎么得来的,所以在该函数只需要关注这两个参数值的生成即可。sign: k(o, e)mysticTime: o,其中o是时间戳,那么mysticTime就是时间戳;要想搞清楚sign的生成就得知道k函数的实现,定位,打断点,运行到这里。

k函数调用了j函数,还得知道j函数的实现。

j函数就是一个计算md5值的函数,那么k函数就是对client=${u}&mysticTime=${e}&product=${d}&key=${t}这样的一个字符串计算md5值。输出一下。

其中只有mysticTime这个变量会改变,key是个定值,整个的加密逻辑就非常清晰了。
python代码如下:

点击查看代码
import requests
from hashlib import md5
import time

url = "https://dict.youdao.com/webtranslate"
word = input("请输入一个单词:")
tm = str(int(time.time() * 1000))
str_temp = f"client=fanyideskweb&mysticTime={tm}&product=webfanyi&key=fsdsogkndfokasodnaso"
obj = md5()
obj.update(str_temp.encode("utf-8"))
sign = obj.hexdigest()
data = {
    "i": word,
    "from": "auto",
    "to": "",
    "dictResult": "true",
    "keyid": "webfanyi",
    "sign": sign,
    "client": "fanyideskweb",
    "product": "webfanyi",
    "appVersion": "1.0.0",
    "vendor": "web",
    "pointParam": "client,mysticTime,product",
    "mysticTime": tm,
    "keyfrom": "fanyi.web",
    "mid": "1", "screen": "1",
    "model": "1",
    "network": "wifi",
    "abtest": "0",
    "yduuid": "abcdefg",
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 "
                  "Safari/537.36", "Referer": "https://fanyi.youdao.com/",
    "Cookie": "OUTFOX_SEARCH_USER_ID_NCOO=xxxxx; OUTFOX_SEARCH_USER_ID=xxxxxx", }

session = requests.session()
resp = session.post(url, data=data, headers=headers)
print(resp.text)

运行结果如下:

解密

由于跟webtranslate相关的只有如下的这一行代码,所以解密逻辑肯定也在这行代码中。

在讲解下面的步骤之前,先介绍一个箭头函数。

点击查看代码
// JavaScript
var mm = () => {
    return 123;
};

//箭头函数如果没有大括号,那么直接返回内容
var kk = () => 456789;
console.log(mm());      // 123
console.log(kk());      // 456789

从这个代码中可以看出箭头函数有两种写法,一个是通过大括号和return来返回值,一个是直接在箭头函数背后写上返回值。再看T = (e,t)=>Object(a["d"])("https://dict.youdao.com/webtranslate", Object(n["a"])(Object(n["a"])({}, e), E(t)), { headers: { "Content-Type": "application/x-www-form-urlencoded" } })这行代码,就是箭头函数的第二种写法,箭头函数背后的整体就是返回的内容,输出看一下。

是个Promise对象,所以就得知道这个Promise对象返回给了谁,这时候就可以看调用栈了。

Qo调用了T,说明Promise对象是返回到Qo中的,定位到Qo

在这段代码中,可以很容易的看到一个关键词decodeData,不用想这肯定就是解密逻辑了,定位一下。

打断点,运行到这里。

就可以看到是个AES加密了,CBC模式,下面只需要知道key和iv即可。看下createDecipheriv函数的实现。

从这里就可以知道a就是key,i是iv,看下ai的生成。a = e.alloc(16, y(o))e.alloc(16, y(n)),先看y函数的实现。

就是一个计算md5值的过程。输出一下e.alloc(16, y(o))的结果,发现跟计算md5后的结果一样,所以就可以简单的认为是个md5值计算即可。


两者都是16字节,跟AES加密所需要的key和value的大小一样,并且还是个定值,这样就简单了。(如果不能判断是不是个定值,可以多调试一下,看变量的值会不会改变)
python代码如下:

点击查看代码
from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64

def my_md5(data):
    obj2 = md5()
    obj2.update(data.encode("utf-8"))
    ret = obj2.digest()  # 字节
    return ret


t = "Z21kD9ZK1ke6ugku2ccWu-MeDWh3z252xRTQv-wZ6jddVo3tJLe7gIXz4PyxGl73nSfLAADyElSjjvrYdCvEP4pfohVVEX1DxoI0yhm36ytQNvu-WLU94qULZQ72aml6JKK7ArS9fJXAcsG7ufBIE0gd6fbnhFcsGmdXspZe-8whVFbRB_8Fc9JlMHh8DDXnskDhGfEscN_rfi-A-AHB3F9Vets82vIYpkGNaJOft_JA-m5cGEjo-UNRDDpkTz_NIAvo5PbATpkh7PSna2tHcE6Hou9GBtPLB67vjScwplB96-zqZKXJJEzU5HGF0oPDY_weAkXArzXyGLBPXFCnn_IWJDkGD4vqBQQAh2n52f48GD_cb-PSCT_8b-ESsKUI9NJa11XsdaUZxAc8TzrYnXwdcQbtl_kZGKhS6_rCtuNEBouA_lvM2CbS7TTtV2U4zVmJKpp-c6nt3yZePK3Av01GWn1pH_3sZbaPEx8DUjSbdp4i4iK-Mj4p2HPoph67DR7B9MFETYku_28SgP9xsKRRvFH4aHBHESWX4FDbwaU="
o = 'ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl'
n = 'ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4'

key = my_md5(o)
iv = my_md5(n)
t = t.replace("_","/").replace("-","+")  # 由于密文其实采用的是个叫url安全的base64编码,会把"+"和"/"替换成"-"和"_",所以在解密的时候得先还原
aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
ming_bs = aes.decrypt(base64.b64decode(t))
ming_bs = unpad(ming_bs, 16)
print(ming_bs.decode("utf-8"))

运行结果如下:

把加解密的代码整合一下。

点击查看代码
import requests
from hashlib import md5
import time
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64

url = "https://dict.youdao.com/webtranslate"
word = input("请输入一个单词:")
tm = str(int(time.time() * 1000))
str_temp = f"client=fanyideskweb&mysticTime={tm}&product=webfanyi&key=fsdsogkndfokasodnaso"
obj = md5()
obj.update(str_temp.encode("utf-8"))
sign = obj.hexdigest()
data = {
    "i": word,
    "from": "auto",
    "to": "",
    "dictResult": "true",
    "keyid": "webfanyi",
    "sign": sign,
    "client": "fanyideskweb",
    "product": "webfanyi",
    "appVersion": "1.0.0",
    "vendor": "web",
    "pointParam": "client,mysticTime,product",
    "mysticTime": tm,
    "keyfrom": "fanyi.web",
    "mid": "1", "screen": "1",
    "model": "1",
    "network": "wifi",
    "abtest": "0",
    "yduuid": "abcdefg",
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 "
                  "Safari/537.36", "Referer": "https://fanyi.youdao.com/",
    "Cookie": "OUTFOX_SEARCH_USER_ID_NCOO=xxxxxxx; OUTFOX_SEARCH_USER_ID=xxxxxx", }

session = requests.session()
resp = session.post(url, data=data, headers=headers)


def my_md5(data):
    obj2 = md5()
    obj2.update(data.encode("utf-8"))
    ret = obj2.digest()  # 字节
    return ret


t = resp.text
o = 'ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl'
n = 'ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4'

key = my_md5(o)
iv = my_md5(n)
t = t.replace("_","/").replace("-","+")
aes = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
ming_bs = aes.decrypt(base64.b64decode(t))
ming_bs = unpad(ming_bs, 16)
print(ming_bs.decode("utf-8"))

运行结果如下:

补充

想要知道createDecipheriv函数的实现还有另外一种思路,直接百度搜索。

发现它其实是Nodejs中crypto库下的一个函数,所以可以直接调用crypto库来实现。alloc其实也是Nodejs中Buffer库下的,也可以直接调用。

js测试代码如下:

点击查看代码
var crypto = require("crypto");

function y(e) {
    return crypto.createHash("md5").update(e).digest();
}

function jm(t,o,n){
    if (!t)
        return null;
    const a = Buffer.alloc(16, y(o))
      , i = Buffer.alloc(16, y(n))
      , r = crypto.createDecipheriv("aes-128-cbc", a, i);
    let s = r.update(t, "base64", "utf-8");
    return s += r.final("utf-8"),
    s
}

var t = 'Z21kD9ZK1ke6ugku2ccWu-MeDWh3z252xRTQv-wZ6jddVo3tJLe7gIXz4PyxGl73nSfLAADyElSjjvrYdCvEP4pfohVVEX1DxoI0yhm36ytQNvu-WLU94qULZQ72aml6cYBVU_O5b4O-ND0rEWbfEEp-CNsPQEwjRV-iM008hyg4psnuxT9hhBXjpzH8uzBxqR9VBh9v2T35qVb4ipPvX70IaGcbG17rvXyras-RWT24bdytS47IgDmQVMfd1cQrTyDVZo1ByopBhc63S3QOKtcY7Aip1m9eLirsRpmecA4zC-0Pn2FSpsOJi3Gw6g2Cy8ryt-pnNGsoO2wf_9lWV4Y7LHqAeQfAMcFERawC1PVDQzouFE2Xvyw20H4XCtJMvcdMgnQgmpo42vaU4Uj6SbNLQbWjrCEXEtcrKu9AVGU03oJeo_Stun9oboBASa5gzP7pecQ8NPIB9xciY5O_jk_QuNG-vZVRdTecK1qSEHMpuSgM5dRMN9iTCD93qAwQYE5qOMCuOfeNnWhUewho3XJfMewpsDstvjSesdXfR5rtrrydSw76xvqQotdSH7J0RAUGjj5Wv-WVxelEFbDYQpPvOWHg3wXOa1pORzELoEG6v8_WR5_5C-buAoAC4d9xa1O76dd1nj1e_NzvdicnBPNj0HSt_APXvtqDzmBLEZUwa9b5_ZhgyJldGwdWHzLwxx8xPM34M_YlW28J8msT5RBMgPv9ahAJSsKQReQD4pboP2cwxWC9yPeloFc68TOLIeSrMvXrT8aJw8S5MpAX0C3-2yN8g0RY80n9QjzsnHIgwXERlrw66hMOHch4DIp-AvbPZl9WTncFPL_A2x-Y4EVkUtvV_JNzDJsVgoITdkekhKHkFmAyMwvKbYvW9-4pFisyOozkh83rko35YZSqDvvIXEWZyWVpGld2SI_xESEP82gtzgrplZzUuVq_WVDegypnD5DZmZsidnHkau-j5FSYwpivm-96QgVDIBuYTjvV9Lv9GatSYyZBCjjx0Xi8I-JuH3x12GITyiXmmn5xjbvpLQSBVly_urZpNy1SnH2XCVrZOOauAy_ZgAByrlGlhzxBuGL_fBd2r6Lv4kERgaD6tnGVlBk2inBiPbW8Sex90bE7g0T5ps6w4_jzVmcmQZ-M2cX7u1y7mlV_vF-puzU81na5nvQIaJmWQn0_9-466JGALXEaW7CHb-BqNZTCdLYJgj6n-DbX9sZs8raeEeJsE3aK1P4YmnUgn6wQHQCYLKmDzTC79KoL-6eCpHe2VD-P48bDfCKLOrqSeLYiWKnZyTAq42h-f9zZtd-fapb4sHO8O0IUF_6DBQ987P9-dvJhghTj8_UIpMjFqBrGDJbnhbGy5Yjn_G1uUtT1usUGwFoBuEJ96r_VPKlxXYjqrgaW3w3ElKr2pEfkKhTKDSLL_inlWGYhTogPsRX8kJubNsZ5V9FcmU2tlGFh5dlDwA-fTTQunsrLt_G40RrK0iWqSvyEjMZi7DqzdeITNK_sk1OlYMguTK6z12P4tzKgV3Ynq6Xo9ToRQE_g9oSH1OEo8mUw7AQ8dNi7FxXjpAJHbfdbKwIjAqUeOfCUJ3UVBMGGR5Um4w80nDvf-gLaxdCePHELy_ev8E-s3K5kADoaE9iFcM5Kz8N_4bfZ_trx6-LufqiDUcT4rNKa42o3pEOUeS9m61MLyRLp2O1YwxypYPNUbl8yK8Q_gTBrTQK3bfo3hs0vDYTpIL1CBLjMNTfip6nv_mE7mZzhOweBpGyoYl1k3kOPSc_0fviR0jdaeYPsaHx-R1V1erV0okwp8kexYr_5FqyFXEnJxGATUoCY5Tc6OfgOh7grXUnVhf2aTG6Uc1ODQk2_h0DkxlFcwUXJf45N3LadYQDs6nN10tiyh6yTL5aZADP1JGgAFAWpXW4GFzIWf4DmjQ3VQKhulLeUEFHOuJgUmzWQtrV831E4EYBVhWAH5050MrhsPbcd1tvYDnvdEOmSi-pUmu7MWoxK95rzfo71bgUHdEbFN3IDSVbYtUYYwegifnjFS17dcyP2q6HTIygor00eEarvj32vWH7TENiqonqGLOuWYcLeRtjRtblY6MAlDvSSxEDeg4cO5PD-MtsgIMvUnGxYUafUp8uAKR1E4LKwA9VLYM5Bl5RMVDLtYyqsUn5zBOZU';
var o = 'ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl';
var n = 'ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4';
let jm1 = jm(t,o,n);
console.log(jm1);

运行结果如下:

标签:函数,之有,JavaScript,加解密,mysticTime,iv,key,import,md5
From: https://www.cnblogs.com/sbhglqy/p/18066054

相关文章

  • [JavaScript] JavaScript的时间与时区
    0序言第1章节,原创,主要关注:JS的时间、时区国际化问题第2章节,主要来自于第1篇参考文献(系对第1章节的基础知识的夯实)1JavaScript时间、时区的国际化(案例)本案例等同于问题:JavaScript从浏览器根据不同时区获取时间的问题假定现在有两台Windows笔记本电脑。Step1设置......
  • JavaScript 打包器esbuild的基础使用
    esbuild是一种类似于webpack的极速JavaScript打包器。esbuild项目主要目标是:开辟一个构建工具性能的新时代,创建一个易用的现代打包器。先安装esbuildnpmiesbuild-g-g代表全局范围检查esbuild的版本esbuild--version命令行构建esbuildsrc\app.jsx--bundle--outfi......
  • JavaScript 常用取整、四舍五入方法汇总
    https://juejin.cn/post/7184257661339172919  2023-01-0314,624阅读2分钟 在JavaScript中,对数值进行四舍五入操作的场景有以下几种:向上取整:ceil向下取整:floor四舍五入:round固定精度:toFixed固定长度:toPrecision取整:parseInt1.向上取整:ceilceil是天花板......
  • javascript匹配文件名相同然后在后面增加数字的正则表达式
    在一个文件列表中constrenameFileName=(fileName:string)=>{console.log("originfilename",fileName)letfileList=getFileList()//获取文件列表,包含了文件名letcount=-1//记录当前包含了几个文件名fileList.forEach(value=>{letfullFil......
  • Blazor笔记-JavaScript Interop(JS互调用)
    更新记录注意:非教程。纯笔记,日常查询用的。需要教程的小伙伴找几本书看看即可哈哈,有Vue基础的话非常快,概念都是通的。非工作需要不建议深入学习Blazor,深入Vue吧,用的多,哈哈。完整目录地址:https://www.cnblogs.com/cqpanda/p/17596348.html点击查看2024年3月7日发布。2023......
  • JavaScript 最新动态:2024 年新功能
    前言随着Web技术的日新月异,JavaScript也在不断地吸收新的特性和技术,以满足日益复杂和多样化的开发需求。在2024年,JavaScript迎来了一系列令人瞩目的新功能,这些功能不仅提升了开发者的效率,也极大地丰富了Web应用的表现力和交互性。在接下来的内容中,我们将逐一介绍这些新......
  • javascript如何循环遍历对象
    在JavaScript中有多种循环遍历对象的方法,下面本篇文章就来给大家介绍一下使用JavaScript循环遍历对象的方法,希望对大家有所帮助。1、使用for循环for循环是js中最常用的一个循环工具,经常用于数组的循环遍历。letarr=[1,2,3];for(leti=0;i<arr.length;i++){co......
  • JavaScript逆向之RSA算法
    RSA算法简介RSA算法属于非对称加密,加密的密钥称为公钥,解密的密钥称为私钥,公钥和私钥不是同一个。公钥是可以放在外面的,给谁都可以;但是私钥不可以放在外面,只能服务器自己保留,如果私钥泄露了,数据安全将有极大的风险。RSA的公钥和私钥是成对的,不能拆开。python中的RSA在python中......
  • js 数组筛选方法使用整理_JavaScript常用数组元素搜索或过滤
    一、常用方案介绍:如果你想找到在符合特定条件的阵列中的所有项目,使用filter。如果你想检查是否至少有一个项目符合特定的条件,请使用find。如果你想检查一个数组包含一个特定的值,请使用includes。如果要在数组中查找特定项目的索引,请使用indexOf 二、js数组筛选方法......
  • 前端基础学习2 | JavaScript
    1、什么是JavaScript相关链接:https://baike.baidu.com/item/JavaScript/321142JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言,是用来控制网页行为的,它使得网页可交互。关于JavaScript有必要知道的事:1)JavaScript和Java是完全不同的语言,不论是概念还是设计,但是基础......