抓包流程
搜索全部包定位js文件如下:
js中定位关键字如下:
输入傻狗搜索,找到了网络响应的数据加载到断点所在数据
输入需要翻译的数据后,响应数据被加载到断点位置,通过断点内的函数运行,我们可用获取到了结果json
const a = tt["a"].decodeData(o, za["a"].state.text.decodeKey, za["a"].state.text.decodeIv)
这一行代码运行结束后,我们获取到a为最后需要的结果,同时参数o为待解密的响应结果,za[“a”].state.text.decodeKey,
za[“a”].state.text.decodeIv 为固定字符串。
查看解密之后的数据如下:
关键的解密函数为tt[“a”].decodeData
在断点处,我们选择tt[“a”].decodeData*函数,点击来源位置,进入函数定义的js代码处。
函数定义代码如下:
函数定义代码:
V = (t,o,n)=>{
if (!t)
return null;
const a = e.alloc(16, j(o))
, c = e.alloc(16, j(n))
, i = r.a.createDecipheriv("aes-128-cbc", a, c);
let s = i.update(t, "base64", "utf-8");
return s += i.final("utf-8"),
s
}
根据函数内的关键字,我猜测数据是由aes解密的,需要的解密密钥和填充为上面固定的字符串。
![在这里插入图片描述](https://img-blog.csdnimg.cn/fa5b3dd5f327428d8e269396e825c3ec.png
上面的t,o,n都为已知的数据
我们使用在线的AES测试一下
解密失败,这里解密失败的原因可能是输入的key和填充有问题。
我们抓包的断点位置,输入的解密数组a,c与在线测试的通过字符串转换的数组不一致。
我们定位a,c生成的方法,输出a,c,查看他们到底是什么?
在 JavaScript 内,上面提供的 JSON 结构表示一个包含字节数据的 Buffer 对象。该对象的属性 type 表示数据类型为 “Buffer”,而属性 data 包含了实际的字节数据。
要在 JavaScript 中定义一个类似的 Buffer 对象 a,可以按照以下方式进行:
const a = Buffer.from([8, 20, 157, 167, 60, 89, 206, 98, 85, 91, 1, 233, 47, 52, 232, 56]);
创建一个名为 a 的 Buffer 对象,其中包含与提供的字节数据相同的字节值。可以通过这种方式重写解密过程,直接用于解密,不需要函数上面的
const a = e.alloc(16, j(o))
, c = e.alloc(16, j(n))
根据以上的思路,我重写了解密函数如下:
// 响应结果解密,nodejs版本
const crypto = require('crypto');
function youdaoAesDecrypt(data_to_decrypy){
// 假设 a 和 c 是 16 字节的 Buffer,t 是 Base64 编码的密文
const a = Buffer.from([8, 20, 157, 167, 60, 89, 206, 98, 85, 91, 1, 233, 47, 52, 232, 56]);
const c = Buffer.from([
210,
187,
27,
253,
232,
59,
56,
195,
68,
54,
99,
87,
183,
156,
174,
28
]);
// 创建解密器
const decipher = crypto.createDecipheriv("aes-128-cbc", a, c);
// 解密 Base64 编码的密文 t,输出为 UTF-8 编码的明文 s
let s = decipher.update(data_to_decrypy, "base64", "utf-8");
s += decipher.final("utf-8");
return s
};
const t = 'Z21kD9ZK1ke6ugku2ccWuwRmpItPkRr5XcmzOgAKD0GcaHTZL9kyNKkN2aYY6yiOzZfdN-5c7PrKP9hcDVlpmVY5ADRIOHQ1z0Xgq87U89X1E9keibqZiFlJGoBKo3ammj0kDfzS0BYOFrPdmoMot5FGqXPmGpoNmGC1BSt8hvSKL37_g_DVloKqsDBquM8W';
result = youdaoAesDecrypt(t);
console.log(result);
运行以上代码,结果如下:
解密函数内有以下代码,通过给定的密钥与填充,我们获取到了a,c两个buffer对象用于解密。
const a = e.alloc(16, j(o))
, c = e.alloc(16, j(n))
再次调试,我们定位j函数与e.alloc函数的运行结果。
function j(e) {
return r.a.createHash("md5").update(e).digest()
}
这个代码运行过后,是将e加密为了一个buffer对象,用于解密的数据。
const md5Hash = crypto.createHash('md5').update(key).digest().slice(0, 16);
const ivBuffer = crypto.createHash('md5').update(iv).digest().slice(0, 16);
以下为改造后的解密函数,使用密钥与填充:
const crypto = require('crypto');
function aesDecrypt(key, iv, encryptedData) {
// 将密钥进行 MD5 哈希,并取前 16 个字节作为密钥
const md5Hash = crypto.createHash('md5').update(key).digest().slice(0, 16);
const ivBuffer = crypto.createHash('md5').update(iv).digest().slice(0, 16);
// 创建解密器
const decipher = crypto.createDecipheriv('aes-128-cbc', md5Hash, ivBuffer);
// 使用 base64 编码的密文进行解密
let decryptedData = decipher.update(encryptedData, 'base64', 'utf-8');
decryptedData += decipher.final('utf-8');
return decryptedData;
}
// 使用示例
const key = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl";
const iv = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4";
const encryptedData = "Z21kD9ZK1ke6ugku2ccWuwRmpItPkRr5XcmzOgAKD0GcaHTZL9kyNKkN2aYY6yiOzZfdN-5c7PrKP9hcDVlpmVY5ADRIOHQ1z0Xgq87U89X1E9keibqZiFlJGoBKo3ammj0kDfzS0BYOFrPdmoMot5FGqXPmGpoNmGC1BSt8hvSKL37_g_DVloKqsDBquM8W";
const decryptedData = aesDecrypt(key, iv, encryptedData);
console.log("origin data",encryptedData)
console.log("result==>",decryptedData);
运行过后,结果正常。