一、前言

彩云小译网页版进行抓包分析,将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逆向解密返回值的更多相关文章

  1. [善用佳软]Chrome插件之彩云小译

    最近公众号新推出个栏目[善用佳软],旨在和大家分享各种小插件和制作开源小软件. 最近在浏览外网时,发现一个贼好用的翻译神器---[彩云小译],在网页端就可以快速的对照翻译出来,经过试用发现无论是速度还 ...

  2. 网络爬虫之记一次js逆向解密经历

    1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...

  3. Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)

    Selenium 获取 JavaScript 返回值非常简单,只需要在 js 脚本中将需要返回的数据 return 就可以,然后通过方法返回 js 的执行结果,方法源码如下所示: /** * Get ...

  4. JS异步函数 返回值

    1.  js 异步的几种情况 : 1.1 异步操作由浏览器内核的 webcore 来执行: onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任 ...

  5. CoreJava_Collection接口add有一个返回值!

        今天讨论与朋友小知识,我发现很多人不知道collection接口定义add方法返回的值,我们所有的工作很多年Java职工.不熟悉的公共接口,使自己成为在细节上的麻烦.一个小采访这让我想起,当我 ...

  6. java基础之抽象类与接口的形式参数和返回值

    抽象类与接口形式参数和返回值问题 1.形参问题 /* 1.形式参数: 基本类型(太简单,不是我今天要讲解的) 引用类型 (1)类名:(匿名对象的时候其实我们已经讲过了) 需要的是该类的对象 (2)抽象 ...

  7. JS模态窗口返回值兼容问题解决方案

    因系统要兼容原IE已使用的关闭方法,经调试测得,需对window.dialogArguments进行再较验,不然易出问题. function OKEnd(vals) { if (vals == nul ...

  8. js的函数返回值

    今天从跟公司牛人那学到的~避免以后忘了赶快记录下来 平时JS的function的返回值可以是一个数值,也可以是一个对象({name:abc,age:123}),更可以是一个函数(这里我是第一次听说), ...

  9. WebView调用js方法获取返回值的完美解决方案

    在Android项目中我们或多或少会涉及到与js交互的问题,这其中WebView是必须掌握的控件,今天主要说说我们通过WebView调用js方法,然后如何很好的获取返回值.这里我总结了三种方式,大家可 ...

  10. 接口API测试和返回值JSON解析的插件

    火狐插件1.   HttpRequest作用:接口API测试例子:http://192.168.10.61:8080/ZHCS/user/loginApp.do?phone=admin&pwd ...

随机推荐

  1. C++ 简易消息循环

    前言 本文将向大家介绍如何使用 C++ 的标准库实现一个异步和并发编程中都非常重要的编程模式:消息循环(Event Loop).尽管市面上存在不少库也提供了同样的功能,但有时候出于一些原因,我们并不想 ...

  2. ESP8266+ MQTT+SG90(舵机) platformio

    ESP8266 + MQTT + SG90(舵机) platformio 连线 ESP8266 MG90S(舵机) GND 棕色 VCC 红色 模拟引脚 橙色 源代码 https://gitee.co ...

  3. Trie树练习题

    Trie树练习题 T1 「一本通 2.3 例 2」The XOR Largest Pair 在给定的 \(N\) 个整数\(A_1,A_2,...A_N\)中选出两个进行异或运算,得到的结果最大是多少 ...

  4. 关于MySQL表设计,测试人员可以关注哪些点

    测试人员关注数据库表设计是"测试左移"的一种手段,可以把有关数据库的潜在bug消灭在系统测试之前,从而提高交付效率. 以MySQL为例,QA可从以下方面对数据库表设计做测试的左移: ...

  5. php 安装扩展 event

    本地环境php8.1,然后我想安装event扩展,找了找资料,直接一句话 sudo pecl install event 然后执行的过程中提示这些 configure.ac:165: the top ...

  6. Http状态码502常见原因及排错思路

    Http状态码502常见原因及排错思路 502表示Bad Gateway.当Nginx返回502错误时,通常表示Nginx作为代理服务器无法从上游服务器(如:我们的后端服务器地址)获取有效的响应.导致 ...

  7. SpringMVC-Mybatis-Maven项目整合

    上次不知道为什么,把写好的系列文章都搞成一样了.结果,五篇文章,都变成了最后一篇文章. 悲剧,好吧,只好重新写了. 这系列文章写的是SpringMVC-Mybatis-Maven项目整合.说白了,其实 ...

  8. golang项目之Makefile

    01  介绍 Go 提供一个名为go的命令,该命令可自动下载.构建.安装和测试 Go 包和命令. Go 提供go命令,官方的目的是为了不需要编写 Makefile,而是能够仅使用 Go 源代码本身中的 ...

  9. LonEle 操作的 SQL Server 数据库(msde2000)由 20180418 版更新至 20190328 版(非官方)

    Shanghai Mitsubishi Elevator Co., Ltd(上海三菱电梯有限公司) 的 Comprehensive Elevator Monitoring System (电梯综合监控 ...

  10. xtrabackup脚本

    xtrabackup是MySQL的一种物理备份工具,相对于mysqldump,备份和还原速度更快 , 我写了一份可以进行备份 + 还原的脚本 #!bin/bash all_bak_path=" ...