【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 ...
随机推荐
- C++ 简易消息循环
前言 本文将向大家介绍如何使用 C++ 的标准库实现一个异步和并发编程中都非常重要的编程模式:消息循环(Event Loop).尽管市面上存在不少库也提供了同样的功能,但有时候出于一些原因,我们并不想 ...
- ESP8266+ MQTT+SG90(舵机) platformio
ESP8266 + MQTT + SG90(舵机) platformio 连线 ESP8266 MG90S(舵机) GND 棕色 VCC 红色 模拟引脚 橙色 源代码 https://gitee.co ...
- Trie树练习题
Trie树练习题 T1 「一本通 2.3 例 2」The XOR Largest Pair 在给定的 \(N\) 个整数\(A_1,A_2,...A_N\)中选出两个进行异或运算,得到的结果最大是多少 ...
- 关于MySQL表设计,测试人员可以关注哪些点
测试人员关注数据库表设计是"测试左移"的一种手段,可以把有关数据库的潜在bug消灭在系统测试之前,从而提高交付效率. 以MySQL为例,QA可从以下方面对数据库表设计做测试的左移: ...
- php 安装扩展 event
本地环境php8.1,然后我想安装event扩展,找了找资料,直接一句话 sudo pecl install event 然后执行的过程中提示这些 configure.ac:165: the top ...
- Http状态码502常见原因及排错思路
Http状态码502常见原因及排错思路 502表示Bad Gateway.当Nginx返回502错误时,通常表示Nginx作为代理服务器无法从上游服务器(如:我们的后端服务器地址)获取有效的响应.导致 ...
- SpringMVC-Mybatis-Maven项目整合
上次不知道为什么,把写好的系列文章都搞成一样了.结果,五篇文章,都变成了最后一篇文章. 悲剧,好吧,只好重新写了. 这系列文章写的是SpringMVC-Mybatis-Maven项目整合.说白了,其实 ...
- golang项目之Makefile
01 介绍 Go 提供一个名为go的命令,该命令可自动下载.构建.安装和测试 Go 包和命令. Go 提供go命令,官方的目的是为了不需要编写 Makefile,而是能够仅使用 Go 源代码本身中的 ...
- LonEle 操作的 SQL Server 数据库(msde2000)由 20180418 版更新至 20190328 版(非官方)
Shanghai Mitsubishi Elevator Co., Ltd(上海三菱电梯有限公司) 的 Comprehensive Elevator Monitoring System (电梯综合监控 ...
- xtrabackup脚本
xtrabackup是MySQL的一种物理备份工具,相对于mysqldump,备份和还原速度更快 , 我写了一份可以进行备份 + 还原的脚本 #!bin/bash all_bak_path=" ...