【python 逆向分析某有道翻译】分析有道翻译公开的密文内容,webpack类型,全程扣代码,最后实现接口调用翻译,仅供学习参考

server/2024/12/27 17:23:56/

文章日期:2024.12.24

使用工具:Python,Node.js

逆向类型:webpack类型

本章知识:sign模拟生成,密文的解密(webpack),全程扣代码,仅供学习参考

文章难度:低等(没难度)

文章全程已做去敏处理!!!  【需要做的可联系我】 

AES解密处理(直接解密即可)(crypto-js.js 标准算法):​​​​​​在线AES加解密工具

仅供学习!!仅供测试!!仅供参考!!

声明:本文逆向的所有内容文件仅供学习,从网站扣的代码不会公开,但博主自己写的代码内容将会公开在文章最底部,望谅解!!!

先看成品图,效果就是这个样子,可以直接翻译,支持多种不同语言(没有试过高并发)

给大家提前讲一下,比较简单的内容我将会快速讲解,不会很细,小白可能会不懂,不懂只能去看我之前的逆向文章,或者留言都可以,有志向的人,一起学习发展。

1、打开某某网站(使用文章开头的AES在线工具解密):

OI1Y7IeHDHWVFvw4Yo05CnrGO+zxG4b5OFpdZvnuG2WEWj/TsHjdLb2bzhvR/PvI

2、【sign】我们打开页面后随便输入中文进行翻译,然后找到刻意的接口,我们打开看一下,没想到一上来就有个sign,而且返回的数据还是密文

3、【sign】别着急,我们把这个接口的请求先转移到python文件内,然后经过我不断的测试,发现他的cookie必须要加【OUTFOX_SEARCH_USER_ID】参数,而且这个参数是通过服务器返回的,而且有效期为20年,我决定直接生成,我从来没见过一个cookie有效期为20年的,纯扯淡,他一定不是在服务器存储着,所以我们直接随机生成即可

其次是载荷data里【from】【to】这两个参数我就不多介绍了,看注释即可。

剩下的就是sign和一个时间戳,直接全局搜索

4、【sign】全局搜索接口的链接路径,发现搜索到了两个,直接点进去都打上断点,然后再次触发翻译

5、【sign】断住了,看图说话,直接跟进去。

6、【sign】跟进来后发现了sign,而且加密方法就在头上。这就不用多说了,口算就能知道是md5加密。

7、【sign】直接用 python 模拟出来,标准的MD5,就不用讲太多了

8、【密钥】接下来看一下那个密钥,这个也不用多说,他是另一个请求返回的,而且这个请求里也有一个sign,用的也是md5加密,只是加密的内容有点不一样,直接看结果吧,没什么难度

9、【代码整理】我将代码进一步整合,方便下一步的调试

10、【解密密文】接下来重点来了,解密返回的密文,本次全程扣代码,文章结尾我将会附上模拟解密的代码,并非扣下来的代码,供大家参考学习

注意:文章结尾的代码并非官网扣下来的,放心测试学习!!!

11、遇到这种密文解密其实也没多难,我接下来用两种方法帮大家找到这个加密位置。

12、【找加密位置1】我们找到返回密文的接口,复制一下链接路径,然后ctrl+shift+f全局搜索,搜索到后,对第二个打上断点,第一个不用打断点,因为第一个很明显,他的链接路径和我要找到不一样,直接排除

13、【找加密位置1】我们打上断点后,随便输入内容使其触发翻译,然后会自动断住,这时候我们就一步一步跟进

14、【找加密位置1】大约跟进了5次左右,看到了一个加密方法,虽然目前没有看到密文在此处解密,但我的职业素养告诉我,“有疑问?直接打上断点好了”,记住,做逆向,只要看到疑似加解密的位置,直接打断点就好,这是找解密位置或加密位置的一种方法。我们直接打上断点,然会放开运行

14、【找加密位置2】使用HOOK大法(配合油猴插件会更方便好用),将HOOK代码直接在控制台执行,然会再次输入内容触发翻译,你会发现断住了(HOOK代码在文章结尾)

HOOK原理:首先我们要知道他解密密文要做什么事情,像这种一般都是字典传输,那么他在解密内容后,一定会执行【JSON.parse】,将字符串的字典转为格式化后的字典,如果他不执行转换,那他就读取不了内容,所以我们用这个HOOK代码进行拦截,相当于这个HOOK代码就是中间商,你所做的事情要经过这个中间商后,这个中间商在觉定是拦截还是放行,这个中间商把别人替代了,所以你不得不经过他,这就是大概的HOOK的原理(有些场景的HOOK需要搭配油猴)

15、【找加密位置2】我们一边放行一遍观察他的内容参数,才走了几步就看到了解密后的密文数据,我们在堆栈里看他上一步的操作,看看都干了什么,点击上一个堆栈,嘿,成功找到加密位置。

16、【解密密文】接下来我们开始解密,我们将他的解密函数在控制台运行,他会自动暴露源函数,这时我们点进去

17、【解密密文】点击进来后,可以看到他解密的方法,我们直接转移到本地js文件内,然会尝试运行看缺少什么,发现缺少【l】函数,我们直接去源代码里找

18、【解密密文】找到了,直接看图,直接复制到文件内,然后再次运行,发现缺少a函数,我们直接去找

19、【解密密文】我们对当时找到的参数位置的a打上断点,然后刷新页面,会发现断住了,然后我们控制台输出一下,然后点击进去,会发现他是一个webpack加载器文件,直接把当前js全部复制到js内

20、【解密密文】复制到了本地js文件内,运行后发现缺少两个环境,我直接补上了,就不细讲了。然后我看出来这个加载器的主函数是a,所以直接把他的主运行函数导出全局,让外部可以访问,既然a已经被导出为jzq了,那么下面的两个函数也有修改一下,都改为jzq即可,然后再次运行看看缺少什么

21、【解密密文】运行发现报错了,找到报错的行,然后打印一下他运行什么导致的报错,打印结果发现他缺少方法,加载器没有找到这个方法,无法调用,那我们直接去找

22、【解密密文】我们回到浏览器控制台,运行一下图片里的函数,然后随便打开任意字段,点击链接进到加载器的函数里

23、【解密密文】进来后,我们直接搜索缺少的方法,找到后,直接放入到本地js里,可以让加载器读取,但要注意了,看下面第二张图,你的加载器需要修改一下代码,否则他不会读取你导入的方法

24、【解密密文】这次运行成功了,他已经能正常读取到91565了,但他缺少另一个方法,我们继续去搜索,一种重复这种方法。由于太多,我就不一个一个尝试了,我直接把全部都复制过来

25、【解密密文】我把所有的都复制过来,运行后发现没有问题了,成功解密了。一般情况不要无脑全部复制,这会导致卡顿,具体怎么复制还是根据大家的个人习惯

26、【全部代码整理】直接看成品

注意:没有用扣下来的代码做解密是因为文件量太大,而且扣代码是教程并不是一定要用扣下来的代码,要懂得变通

【AES-128-CBC.js】 js文件,用于解密,扣下来的代码不能用于公开,只能给大家展示模拟出来的源代码

javascript">// 导入 crypto 模块
const crypto = require('crypto');
// 安装 express 服务包
// npm install express --save
const express = require('express');const app = express();
app.use(express.json());// AES-128-CBC 解密函数
function aesDecrypt(ciphertext, key, iv) {try {// 创建解密器const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);// 执行解密操作let decrypted = decipher.update(ciphertext, "base64", "utf-8");decrypted += decipher.final('utf8');return decrypted;} catch (error) {console.error('解密失败:', error);}
}function generateMD5Hash(input) {// 创建 MD5 哈希const hash = crypto.createHash('md5');// 更新哈希对象内容hash.update(input);// 输出结果为 Buffer 对象return hash.digest(); // 默认是二进制 Buffer 格式
}app.post('/', (req, res) => {const {text, key, iv} = req.body;decrypt_data = aesDecrypt(text,generateMD5Hash(key),generateMD5Hash(iv))console.log('【解密结果】 - ',decrypt_data)res.status(200).json({code: 1, data: JSON.parse(decrypt_data)});
});// 检测服务是否已打开
app.get('/run', (req, res) => {res.status(200).json({code: 1});
});app.listen(4000, () => {console.log('Node.js 服务监听端口 127.0.0.1:4000');
});

【翻译请求.py】运行此代码前,请先运行js文件,js文件运行后会启动接口,python要调用接口实现解密

python">import json
import random
import requests
import time
import hashlib
import base64# base64 解密
def base64_decode(str):# print(base64.b64decode('MTIz'.encode()))return base64.b64decode(str).decode('utf-8')
# 这个是链接被base64加密了,此步骤只用于去敏,无其他作用
URL = base64_decode('aHR0cHM6Ly9kaWN0LnlvdWRhby5jb20=')class youdao:# MD5 - SHA3_512 加密def md5_encrypt(self, string):''''md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512','blake2b', 'blake2s','sha3_224', 'sha3_256', 'sha3_384', 'sha3_512','shake_128', 'shake_256''''md5 = hashlib.md5()md5.update(string.encode('utf-8'))return md5.hexdigest()# 获取 secretKey / aesKey / aesIvdef obtain_key(self):'''获取 secretKey / aesKey / aesIv'''headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",}url = URL + "/webtranslate/key"# 13位时间戳mysticTime = time.time()# 立马的key是官网固定的sign = self.md5_encrypt(f'client=fanyideskweb&mysticTime={mysticTime}&product=webfanyi&key=asdjnjfenknafdfsdfsd')params = {"keyid": "webfanyi-key-getter","sign": sign,"client": "fanyideskweb","product": "webfanyi","pointParam": "client,mysticTime,product","mysticTime": f"{mysticTime}",}response = requests.get(url, params=params, headers=headers).json()['data']# sign密钥self.secretKey = response['secretKey']# key密钥self.aesKey = response['aesKey']# iv向量self.aesIv = response['aesIv']# 翻译请求 返回密文def translate(self, text, froms, tos):'''执行翻译请求,返回密文'''headers = {"Accept": "application/json, text/plain, */*","Content-Type": "application/x-www-form-urlencoded","Referer": "1","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",}# 13位时间戳mysticTime = time.time()sign = self.md5_encrypt(f'client=fanyideskweb&mysticTime={mysticTime}&product=webfanyi&key={self.secretKey}')# 随机,伪装一下cookies = {"OUTFOX_SEARCH_USER_ID": f"-{random.randint(10000000, 99999999)}@{random.randint(1, 255)}.{random.randint(1, 255)}.{random.randint(1, 255)}.{random.randint(1, 255)}"# 防封,刷新一次可以使用20年有效期}url = URL + "/webtranslate"data = {"i": text,# "from": "en",  # 输入日文  en英文 ja日文  fr法语 zh-CHS中文 de德语 es西班牙语# "to": "zh-CHS",  # 翻译为中文"dictResult": "true","keyid": "webfanyi","sign": sign,"client": "fanyideskweb","product": "webfanyi","appVersion": "1.0.0","vendor": "web","pointParam": "client,mysticTime,product","mysticTime": f"{mysticTime}","keyfrom": "fanyi.web",}if froms:data['from'] = fromsif tos:data['to'] = tosresponse = requests.post(url, headers=headers, cookies=cookies, data=data).textself.ciphertext = response.strip()# AES-128-CBC 解密def decrypt_AES_128_CBC(self):'''AES-128-CBC 解密'''import requestsheaders = {'Content-Type': 'application/json'}data = {"text": self.ciphertext, "key": self.aesKey, "iv": self.aesIv}url = "http://127.0.0.1:4000/"response = requests.post(url, headers=headers, data=json.dumps(data)).json()text = ''if response['code'] == 1:for data_list in response['data']['translateResult']:text += data_list[0]['tgt']print('----- 翻译结果 -----\n' + text + '\n')main = youdao()
# 获取 secretKey / aesKey / aesIv 只需要运行一次即可,经过我的分析,他每天返回的key都不一样
main.obtain_key()
# 发送翻译请求  # 输入日文  en英文 ja日文  fr法语 zh-CHS中文 de德语 es西班牙语
# froms:当前输入的是什么语言  输入None则自动识别
# tos:要翻译为什么语言    输入None则自动识别
main.translate('你是谁,你叫什么名字?\n怎么称呼大哥\n我的名字是哈哈,请叫我哈哈哥', froms=None, tos=None)   # 自动识别 翻译为 英文(默认)
# 解密请求内容
main.decrypt_AES_128_CBC()

【HOOK代码】

javascript">// 【json.parse 解密对象专用  JSON字符串转换为JS对象】
(function () {var parse_ = JSON.parse;JSON.parse = function (arg) {console.log("[J] - 正在执行[*json.parse] -> ", arg);debugger;return parse_(arg);  // 不改变原来的执行逻辑}
})();


http://www.ppmy.cn/server/153673.html

相关文章

消息中间件——rabbitmq,kafka,rocketmq

目录 mq mq解决什么问题 rabbitmq 工作原理 消息路由 如何保证消息不丢失 实现高可用 kafka 能支持这么大吞吐量的原因 如何保证消息不丢失 避免重复消费 如何保证消息顺序消费 数据存储原理 IRS leader选举 rocketmq 为什么不使用zookeeper 分布式事务 mq …

scss配置全局变量报错[sass] Can‘t find stylesheet to import.

路径没有错误,使用别名即可 后又提示Deprecation Warning: Sass import rules are deprecated and will be removed in Dart Sass 3.0.0. 将import改为use 使用时在$前添加全局变量所在文件,即variable.

入侵他人电脑,实现远程控制(待补充)

待补充 在获取他人无线网网络密码后,进一步的操作是实现入侵他人电脑,这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址(通过伪造的网页、伪造的Windows窗口、hook,信…

行业分析---造车新势力之零跑汽车

1 背景 在之前的博客中,笔者撰写了多篇行业分析的文章(科技新能源): 《行业分析---我眼中的Apple Inc.》 《行业分析---马斯克的Tesla》 《行业分析---造车新势力之蔚来汽车》 《行业分析---造车新势力之小鹏汽车》 《行业分析---…

突围边缘:OpenAI开源实时嵌入式API,AI触角延伸至微观世界

当OpenAI宣布开源其名为openai-realtime-embedded-sdk的实时嵌入式API时,整个科技界都为之震惊。这一举动意味着,曾经遥不可及的强大AI能力,如今可以被嵌入到像ESP32这样的微型控制器中,真正地将AI的触角延伸到了物联网和边缘计算…

SpringCloudGateway+Nacos注册与转发Netty+WebSocket

背景 项目中有个拍卖服务是长连接的,需要加入到注册中心中方便统一的管理,并且方便动态扩容。 问题 Nacos没有对长连接的服务注册的支持,需要手动实现把服务注册上线下线,感知服务状态。并需要支持域名转发WebSocket的请求。 …

MTEB文本向量化评估基准:Massive Text Embedding Benchmark

Massive Text Embedding Benchmark 文本向量化评估基准 Bitext mining is the task of finding parallel sentences in two languages. 双语文本挖掘是识别两种语言中语义等价句子对的任务。 Classification is the task of assigning a label to a text. 文本分类是为文本分配…

卷积神经网络入门指南:从原理到实践

目录 1 CNN的发展历史 2 CNN的基本原理 3 CNN核心组件 3.1 卷积操作基础 3.2 卷积层详解 3.3 高级卷积操作 3.3.1 分组卷积(Group Convolution) 3.3.2 深度可分离卷积(Depthwise Separable Convolution): 3.3 池…