【Go】彩云小译翻译接口js逆向解密返回值
一、前言
对彩云小译网页版进行抓包分析,将js算法代码转换成go代码,使用go发送http请求编写一个翻译小工具。
主要实现:
- 翻译(解密翻译结果)
- 单词字典查询
- 生成JWT(保持有效期)
二、抓包
打开网页按F12调出开发人员工具,再切换到网络选项卡,在输入框里输入内容开始抓包,会抓到两个接口,translator为翻译接口,dict为查询字典的接口。

在 translator接口的响应里面,发现并没有找到翻译的结果??其实 target就是翻译结果,只是进行了加密,需要对其进行解密才能得到翻译结果。
{
"isdict": 1,
"confidence": 1.21429,
"target": "5Y2t5nJ9",
"rc": 0
}
三、分析
我们先对 translator响应的 target进行逆向分析
我们接着通过上一步抓包抓到的接口,在发起程序选项卡中找到对应的调用点

这个很明显就是调用翻译接口的地方,我们点击右边蓝色的js文件,查看源代码

这里我们很容易就看到了我们要找到target,这里应该是已经请求完接口的返回数据了,dh为请求函数,获取到target并且赋值给了变量o,接着是一个三元表达式,通过typeof来判断o的类型是否为string,我们知道其实target就是一串字符串,所以只需要看问号后面的表达式了,问号后面也是一个赋值操作,我们直接下一个断点,再到页面中进行翻译操作

已经断下来了,我们看到o确实是target密文,我们把鼠标悬浮到Zs函数上,点击蓝色的链接跳转到对应的代码

可以看到Zs首先是调用了一下vh函数,并且把target传入进去,进行一些字符串操作后返回给了变量t,我们直接把vh函数代码抠下来,这段代码是可以直接运行的
function vh(e) {
const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
, i = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
, a = n=>t.indexOf(n)
, o = n=>a(n) > -1 ? i[a(n)] : n;
return e.split("").map(o).join("")
}
再调用Ah函数来解密,我们看到在Ah函数中调用了oh.decode()函数,decode很明显是解密了,我们跟之前的操作一样,进入到decode函数中查看代码

decode就是N函数,我们发现N函数中又调用了几个函数嵌套,我们按照上一步的方法,把使用到的函数全部抠下来
const vh = (e)=>{
const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
, i = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
, a = n=>t.indexOf(n)
, o = n=>a(n) > -1 ? i[a(n)] : n;
return e.split("").map(o).join("")
}
const b = function(I) {
switch (I.length) {
case 4:
var U = (7 & I.charCodeAt(0)) << 18 | (63 & I.charCodeAt(1)) << 12 | (63 & I.charCodeAt(2)) << 6 | 63 & I.charCodeAt(3)
, F = U - 65536;
return String.fromCharCode((F >>> 10) + 55296) + String.fromCharCode((F & 1023) + 56320);
case 3:
return String.fromCharCode((15 & I.charCodeAt(0)) << 12 | (63 & I.charCodeAt(1)) << 6 | 63 & I.charCodeAt(2));
default:
return String.fromCharCode((31 & I.charCodeAt(0)) << 6 | 63 & I.charCodeAt(1))
}
}
const w = function(I) {
const y = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g
return I.replace(y, b)
}
const E = function(I) {
return window.atob(I)
}
const C = function(I) {
return w(E(I))
}
const k = function(I) {
return String(I).replace(/[-_]/g, function(U) {
return U == "-" ? "+" : "/"
}).replace(/[^A-Za-z0-9\+\/]/g, "")
}
const N = function(I) {
return C(k(I))
}
抠下来之后运行发现报错,找不到o,我们通过下断点,然后在控制台输入出o,发现o就是内置函数 fromCharCode,因此我们只需要把o替换成 String.fromCharCode就行

我们尝试运行一下代码,发现可以成功解密,那就代表我们找的解密算法是对的,那么我们如何在go中使用呢?go中应该也有像python中的execjs那样直接调用js脚本的,但是我们这次不是用那种方法,我们下面把js代码转换成go代码
四、转换
将js算法转换成go代码,并且进行简化代码
package main
import (
"encoding/base64"
"fmt"
)
// 将字母表中的字母替换为另一个字母表中的字母
func substituteAlphabet(input string) string {
alphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
substitution := "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
findIndex := func(n byte) int {
for index, b := range alphabet {
if byte(b) == n {
return index
}
}
return -1
}
substitute := func(n byte) byte {
if findIndex(n) > -1 {
return substitution[findIndex(n)]
}
return n
}
result := ""
for _, c := range input {
result += string(substitute(byte(c)))
}
return result
}
// 从字符串中删除双字节字符
func removeDoubleByte(input string) string {
bytes := []byte(input)
for i := 0; i < len(bytes); i++ {
if bytes[i] == 194 && i+1 < len(bytes) && bytes[i+1] >= 128 && bytes[i+1] <= 191 {
bytes[i] = bytes[i+1]
bytes[i+1] = 0
}
}
return string(bytes)
}
// 对输入的字符串进行base64解码
func decodeBase64(input string) string {
decoded, err := base64.StdEncoding.DecodeString(input)
if err != nil {
panic(err)
}
return removeDoubleByte(string(decoded))
}
func main() {
code := substituteAlphabet("5Y2t5nJ977lZ5YvJ55JZ77lO")
text := decodeBase64(code)
fmt.Println(text)
}

五、请求
我们再次对网页进行抓包,然后在开发者工具中右键对应接口,复制curl

再到https://curlconverter.com/#go中将curl转换成对应的go代码,生成的代码放到go里面是可以直接运行的
我们需要先请求接口,通过返回的数据拿到target,再使用解密对target进行解密,拿到最终的翻译结果


六、总结
我写完之后发现已经写了220多行了,go的代码量确实比python的要多
加了一个dict字典查询接口,还有生成jwt的接口(可以防止jwt过期)
完整代码已经上传到Github
以上内容仅用于学习研究
【Go】彩云小译翻译接口js逆向解密返回值的更多相关文章
- [善用佳软]Chrome插件之彩云小译
最近公众号新推出个栏目[善用佳软],旨在和大家分享各种小插件和制作开源小软件. 最近在浏览外网时,发现一个贼好用的翻译神器---[彩云小译],在网页端就可以快速的对照翻译出来,经过试用发现无论是速度还 ...
- 网络爬虫之记一次js逆向解密经历
1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...
- Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)
Selenium 获取 JavaScript 返回值非常简单,只需要在 js 脚本中将需要返回的数据 return 就可以,然后通过方法返回 js 的执行结果,方法源码如下所示: /** * Get ...
- JS异步函数 返回值
1. js 异步的几种情况 : 1.1 异步操作由浏览器内核的 webcore 来执行: onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任 ...
- CoreJava_Collection接口add有一个返回值!
今天讨论与朋友小知识,我发现很多人不知道collection接口定义add方法返回的值,我们所有的工作很多年Java职工.不熟悉的公共接口,使自己成为在细节上的麻烦.一个小采访这让我想起,当我 ...
- java基础之抽象类与接口的形式参数和返回值
抽象类与接口形式参数和返回值问题 1.形参问题 /* 1.形式参数: 基本类型(太简单,不是我今天要讲解的) 引用类型 (1)类名:(匿名对象的时候其实我们已经讲过了) 需要的是该类的对象 (2)抽象 ...
- JS模态窗口返回值兼容问题解决方案
因系统要兼容原IE已使用的关闭方法,经调试测得,需对window.dialogArguments进行再较验,不然易出问题. function OKEnd(vals) { if (vals == nul ...
- js的函数返回值
今天从跟公司牛人那学到的~避免以后忘了赶快记录下来 平时JS的function的返回值可以是一个数值,也可以是一个对象({name:abc,age:123}),更可以是一个函数(这里我是第一次听说), ...
- WebView调用js方法获取返回值的完美解决方案
在Android项目中我们或多或少会涉及到与js交互的问题,这其中WebView是必须掌握的控件,今天主要说说我们通过WebView调用js方法,然后如何很好的获取返回值.这里我总结了三种方式,大家可 ...
- 接口API测试和返回值JSON解析的插件
火狐插件1. HttpRequest作用:接口API测试例子:http://192.168.10.61:8080/ZHCS/user/loginApp.do?phone=admin&pwd ...
随机推荐
- 修复一个kubernetes集群
前几天有个朋友把他们的kubernetes集群搞挂了,让我帮忙恢复一下,由于很多现场都没有了,这里提供一下解决思路. 环境问题 该环境有一个master节点,即控制面pod(etcd.schedule ...
- vue中事件总线bus的用法
./util/Bus.js import Bus from 'vue'; let install = function (Vue) { // 设置eventBus Vue.prototype.bus ...
- Vue写一个图片轮播组件【转载】
一.理清思路,理解需求和原理 1. 要写一个什么样的轮播? 在点击右侧箭头时,图片向左滑动到下一张:点击左侧箭头时,图片向右滑到下一张 点击下面的小圆点,滑到对应的图片,相应小圆点的样式也发生改变 要 ...
- 2024 CSP 游记
\(\text{CSP-J}\) 游记 \(\text{Day -INF}\) 初赛免了,没有游记. \(\text{Day 0}\) 有点慌,于是打开了游戏跟 \(\text{zjx,sym}\) ...
- SparkSQL练习:对学生选课成绩进行分析计算
题目内容: 对学生选课成绩进行分析计算 题目要求: (1)该系总共有多少学生: (2)该系共开设来多少门课程: (3)每个学生的总成绩多少: (4)每门课程选修的同学人数: (5)每位同学选修的课程门 ...
- .NET云原生应用实践(五):使用Blazor WebAssembly实现前端页面
本章目标 使用Blazor WebAssembly实现管理"贴纸"页面 集成认证与授权机制 如果你对Blazor WebAssembly的使用不感兴趣,可以跳过本章的阅读.你也可以 ...
- 2.13 新手必读的Linux使用注意事项
通过安装并体验 Linux 系统,读者应该能发现 Linux 与 Windows 的一些不同之处,本节就几个容易让初学者混淆的问题做重点讲解,以便加深读者对 Linux 系统的认识. Linux 严格 ...
- Linux-Centos安装配置
一.安装CentOs CentOS是Linux系统的一个发行版本,还有Ubuntu.Fedora.Debian等. 安装VMware虚拟机 官网地址:https://www.vmware.com/pr ...
- 嵌入式Linux系统构建
参考资料 本篇内容主要参考 韦东山的<嵌入式Linux应用开发完全手册V5.2_IMX6ULL_Pro开发板.pdf> 具体课程见 百问网嵌入式专家-韦东山嵌入式专注于嵌入式课程及硬件研发 ...
- Solr 学习(5) —- Solr查询语法和参数
1.查询地址 建立好solr的索引后,可以通过管理界面进行查询.http://127.0.0.1:8983/solr/admin/form.jsp 要尝试多个查询方法的话,可以进入full inter ...