前言
最近有个兄弟通过我的视频号加我,咨询能否将这个dubo游戏游戏开始前就将数据拿到从而进行押注,于是通过抓包工具测试了下,发现数据有时候是明文,有时候确实密文,大致看了下有这几种加密:Md5aes、Md5,参数加密用md5,数据返回加密用Md5aes,本次记录一下分析过程。
登录
通过抓包分析数据,发现数据返回采用Md5aes
请求参数用了某种加密
分析
我们通过上面的抓包知道,密码肯定是用了一种加密方式,但具体是啥,还不清楚,我们通过打断点的形式顺藤摸瓜
通过观察启动资源,锁定一个index.js
点击进去,观察发现有表单提交的数据
继续往下搜索md5()方法
t.prototype.get_md5 = function(t) {
return this.md5(t)
}
继续搜索md5()方法
cc._RF.push(e, “121674IswNGu77LvNvHfpBi”, “md5”)
cc._RF.push 和 cc._RF.pop 是 Cocos Creator 引擎用于跟踪脚本加载顺序和依赖关系的工具函数。这些函数在加载脚本时自动生成,用于维护加载堆栈。
我们通过对该方法进行数据修改,再次运行观察结果
修改
再md5方法下新增代码
t.prototype.md5 = function(t) {
var e = this;
alert('我被执行了');
console.log(t);
console.log(e);
t = this.utf16_to_utf8(t);
console.log('新的密码');
console.log(t);
for (var o = this.porcess_message(t), n = Uint32Array.from([this.A, this.B, this.C, this.D]), a = 0, i = this.split(Array.from(o), 16); a < i.length; a++) {
for (var r = i[a], s = n[0], c = n[1], l = n[2], h = n[3], u = 0; u < 64; u++)
n[(4 - u % 4) % 4] = this.fghi_wrapped(u)(n[(4 - u % 4) % 4], n[(4 - u % 4 + 1) % 4], n[(4 - u % 4 + 2) % 4], n[(4 - u % 4 + 3) % 4], r[this.x_index(u)], this.S[u], this.T(u));
n[0] = s + n[0],
n[1] = c + n[1],
n[2] = l + n[2],
n[3] = h + n[3]
}
return Array.from(n).map(function(t) {
return e.little_endian(t)
}).join("").toLowerCase()
}
保存后刷新重新登陆
可以看到,密码的确是传递过来了
猜测
可能是md5加密
发现数据值一样,请求登录只需要将密码进行md5加密即可
import requests
import hashlib
headers = {
'Accept': '*/*',
'Accept-Language': 'zh,zh-CN;q=0.9',
'Authorization': 'undefined',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Referer': 'http://js88.mrlj.cn/js1/',
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Mobile Safari/537.36',
}
text1='123456'
print(text1)
md=hashlib.md5(text1.encode()) # 创建md5对象
md5pwd=md.hexdigest() # md5加密
print(md5pwd)
params = {
'loginId': '241837',
'loginPwd': md5pwd,
}
response = requests.get('http://js88.mrlj.cn/qw/user/weixin/loginByPwd', params=params, headers=headers, verify=False)
print(response.json())
响应
123456
e10adc3949ba59abbe56e057f20f883e
{‘code’: 200, ‘msg’: ‘正常’, ‘data’: ‘md5AES:w3cqakJcff674yZSTLRgOck0lJ4SiaKjhO9Greq3hOdp+irWmG9nB/tPuvl1BYA2f6tHCIlxVRhippuJn/FVcVOrGk88zoscA9tbnx+mPIC2ynMt8KnPWKGQYKIJekukfktcGOg0JR29GkR6NktoboqIDaVIHMpCcain3bd9Ly/enE03bI5BuM9a+Kn86DXbbdSmUyNCWC0WNNi3Onn/KtJ3W6Tb8r/ujfragdTPPbpuvItSCXIB9kpQDlkSNSINsqTF8VaM8VBOQ2YKnv43ORmypGwPjeZrm+j4BmIhSM2xr+hlf0sJp1k1xtu4XUz4AGypWdESGOHbCGfgSFxpGs34UUxkAN2Dg+U/Y3Nv8hjQnt0UceSb2rfsHhWG3uCPqTnFFI0mV64QSQeyOsPEca80zjUEREXpcnPfR7lSQGdn5yoemu7rXWdsDszdHalIi774B38hY/1Cc+9uHjxvvaRP0+G9OUHgOPV2pwgS7nvlDekFH0E+PFHTZSg5UEm09tluDZeowxShc/MYcoGljdLrfT24Vr755gGHs2PgE8UXRglOQJqAsWazyQZJqz6/hULG40kAT3/PkLzREVMIt3yyGERj2RDzcPk+bJK5d12cWjUf6/c1tFfhJeBx+nKzyP+rFIi6JsaNUKObMwgNC1LiwEY0W3+suXQLcR5FbMa6CURmVzPwIxB4LslDD0OEPqnHHowvVE9ZyhE6ts5Am1KTcvKY7rY8MrAcXO30nHbfupwH5rjrrrf2MdpKcA2PUPnITj7V6TVCmqX24wdTB5pcrZVshvv1cV8zOll54S2tOJrC2GjRKRl1clXvVhokU2Ys22NKMDB5OxUP2ajJea6d98owyPlnpH4MVzxeVnewcK8/ed35YrT8f4nn2TFqe0zsQqqsiC9noScvr/uZV/vxBHYi45LRIjaAzTUhBc8l9IlfknJQnUvnmE2kzNBW’, ‘ok’: True}
解密
function() {
console.log('iv-=======');
function t() {
this.aes_key = "2c4add8f849a7bea",
this.aes_iv = "dc4b73b33e69eaff"
}
return t.prototype.encrypt = function(t) {
console.log('iv2-=======');
var e = CryptoJS.enc.Utf8.parse(this.aes_key)
, o = CryptoJS.enc.Utf8.parse(this.aes_iv)
, n = CryptoJS.AES.encrypt(t, e, {
iv: o,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return CryptoJS.format.OpenSSL.stringify(n)
}
,
t.prototype.decrypt = function(t) {
var e = (t = CryptoJS.format.OpenSSL.parse(t)).ciphertext.toString()
, o = CryptoJS.enc.Hex.parse(e)
, n = CryptoJS.enc.Base64.stringify(o)
, a = CryptoJS.enc.Utf8.parse(this.aes_key)
, i = CryptoJS.enc.Utf8.parse(this.aes_iv);
return CryptoJS.AES.decrypt(n, a, {
iv: i,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8)
}
,
n([i], t)
}());
这段代码是一个 JavaScript 函数,它定义了一个名为 t 的构造函数,并将其实例化后作为匿名函数的返回值。在构造函数 t 中,有两个属性 aes_key 和 aes_iv,它们存储了AES加密算法所需的密钥和初始化向量。
函数中定义了两个方法 encrypt 和 decrypt,用于加密和解密操作。
在 encrypt 方法中,首先将密钥和初始化向量转换为 UTF-8 格式,然后使用 CryptoJS 库中的 AES 加密函数对传入的参数
t 进行加密。加密过程中指定了加密模式为 CBC(Cipher Block Chaining),并使用 PKCS7 填充方式。最后,使用
OpenSSL 格式将加密结果转换为字符串并返回。
在 decrypt 方法中,首先将传入的密文解析为 OpenSSL 格式,然后将其转换为十六进制格式,并再次转换为 Base64
字符串。接着,将密钥和初始化向量转换为 UTF-8 格式,使用 CryptoJS 库中的 AES
解密函数对密文进行解密,解密模式和填充方式与加密时相同。最终将解密结果转换为 UTF-8 格式的字符串并返回。
将js代码复制下来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Encryption/Decryption Example</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>
<body>
<script>
(function() {
function t() {
this.aes_key = "2c4add8f849a7bea";
this.aes_iv = "dc4b73b33e69eaff";
}
t.prototype.encrypt = function(t) {
var e = CryptoJS.enc.Utf8.parse(this.aes_key),
o = CryptoJS.enc.Utf8.parse(this.aes_iv),
n = CryptoJS.AES.encrypt(t, e, {
iv: o,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return CryptoJS.format.OpenSSL.stringify(n);
};
t.prototype.decrypt = function(t) {
var e = (t = CryptoJS.format.OpenSSL.parse(t)).ciphertext.toString(),
o = CryptoJS.enc.Hex.parse(e),
n = CryptoJS.enc.Base64.stringify(o),
a = CryptoJS.enc.Utf8.parse(this.aes_key),
i = CryptoJS.enc.Utf8.parse(this.aes_iv);
return CryptoJS.AES.decrypt(n, a, {
iv: i,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
};
// 示例使用
var cipher = new t();
var plaintext = "{code:200,data}";
var encrypted_text = cipher.encrypt(plaintext);
console.log("Encrypted:", encrypted_text);
var decrypted_text = cipher.decrypt(encrypted_text);
console.log("Decrypted:", decrypted_text);
})();
</script>
</body>
</html>