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

news/2024/12/28 4:50:58/

文章日期: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/news/1558695.html

相关文章

39.1 用最近1天的内存平均使用率等出业务资源利用率报表

本节重点介绍 : 纵向聚合VS横向聚合用最近1天的内存平均使用率等出业务资源利用率报表 为了降低成本合理配置资源 纵向聚合VS横向聚合 普通的聚合函数是纵向聚合 普通的聚合函数是纵向聚合,也就是多个series进行聚合如求机器的平均cpu user态利用率 avg(rate(…

概率论基础知识点公式汇总

1 概率论的基本概念 1.1 随机事件 样本空间 S S S:将随机实验所有可能的记过组成的集合称为样本空间。样本点:样本空间的每个结果称为样本点。随机试验、随机事件 E E E、基本事件、必然事件、不可能事件、对立事件 A A ‾ A\overline{A} AA、古典概型…

设计模式01:创建型设计模式之单例、简单工厂的使用情景及其基础Demo

一、单例模式 1.情景 连接字符串管理 2.好处 代码简洁:可全局访问连接字符串。性能优化:一个程序一个连接实例,避免反复创建对象(连接)和销毁对象(连接)。线程安全:连接对象不会…

Halcon例程代码解读:安全环检测(附源码|图像下载链接)

安全环检测核心思路与代码详解 项目目标 本项目的目标是检测图像中的安全环位置和方向。通过形状匹配技术,从一张模型图像中提取安全环的特征,并在后续图像中识别多个实例,完成检测和方向标定。 实现思路 安全环检测分为以下核心步骤&…

GitCode 光引计划投稿|智能制造一体化低代码平台 Skyeye云

随着智能制造行业的快速发展,企业对全面、高效的管理解决方案的需求日益迫切。然而,传统的开发模式往往依赖于特定的硬件平台,且开发过程繁琐、成本高。为了打破这一瓶颈,Skyeye云应运而生,它采用先进的低代码开发模式…

CSS系列(31)-- Backdrop Filter详解

前端技术探索系列:CSS Backdrop Filter详解 🎨 致读者:探索现代UI效果的艺术 👋 前端开发者们, 今天我们将深入探讨 CSS Backdrop Filter,这个强大的背景处理特性。 基础效果 🚀 模糊效果 …

C#-调用C++接口

一.静态&动态装载DLL C中接口通过编译为DLL对外提供调用,C#需要将DLL加载至本应用才可实现C接口调用. 1.静态装载 C#应用程序在编译为可执行exe时将外部DLL装载至本应用中,例如在CSC编译指令中添加相关参数可实现DLL引用. csc /reference:user32.dll /out:HelloWorld.exe 2…

Python使用requests_html库爬取掌阅书籍(附完整源码及使用说明)

教程概述 本教程先是幽络源初步教学分析掌阅书籍的网络结构,最后提供完整的爬取源码与使用说明,并展示结果,切记勿将本教程内容肆意非法使用。 原文链接:Python使用requests_html库爬取掌阅书籍(附完整源码及使用说明…