对称加密-AES学习笔记及优师云登录加密参数逆向
介绍
和前面DES加密学习一样,只学习用法及实现以供爬虫逆向所用,不深入原理
AES加密算法是用来取代DES的,同样有一个密钥,用来加密或解密,同时支持以下:
- mode
- CBC
- CFB
- CTR
- CTRGladman
- ECB(唯一无
iv
向量模式) - OFB
- padding
- ZeroPadding
- NoPadding
- AnsiX923
- Iso10126
- Iso97971
- Pkcs7
(以上列表不完全列出)
AES加密密钥长度为AES128、AES192、AES256,即128位、192位、256位,某些库会在长度不够时自动填充
JS实现
同样使用Crypto-Js
库实现,代码与前DES基本一致:
let crypto = require('crypto-js')
function aesEncrypt(aesMsg,aesKey,aesIv){
let key = crypto.enc.Utf8.parse(aesKey),
iv = crypto.enc.Utf8.parse(aesIv),
msg = crypto.enc.Utf8.parse(aesMsg),
encrypted = crypto.AES.encrypt(msg,key,{
iv:iv,
mode:crypto.mode.CBC,
padding:crypto.pad.Pkcs7
})
return encrypted.toString()
}
console.log(aesEncrypt('HELLO WORLD','0123456789abcdef','0123456789abcdef'))
运行结果:
u9CkJDGEw0frLa/SQ51GOg==
解密与之差不多,但要注意小细节
function aesDecrypt(aesMsg,aesKey,aesIv){
let key = crypto.enc.Utf8.parse(aesKey),
iv = crypto.enc.Utf8.parse(aesIv),
encrypted = crypto.AES.decrypt(aesMsg,key,{
iv:iv,
mode:crypto.mode.CBC,
padding:crypto.pad.Pkcs7
})
return encrypted.toString(crypto.enc.Utf8)
}
console.log(aesDecrypt('u9CkJDGEw0frLa/SQ51GOg==','0123456789abcdef','0123456789abcdef'))
运行结果:
HELLO WORLD
实战-优师云
请求表单password
加密
可以走发起程序或者XHR断点,这里选择XHR断点
找寻到这里比较直观的调用,但是password
已是密文
继续寻找
这里/Android|webOS|iPhone|iPod|iPad|BlackBerry|MicroMessenger/i.test(navigator.userAgent)
为false
,那么可以视代码如下:
return false || (a = Object(_["g"])({
data: e,
key: "password.yunjy.y",
param: ["password"]
}))
猜测这块就是加密函数,可以直接复制进控制台调用以下看看:
现在来研究这个函数,跳转至源码:
var u = function(t) {
var e = t.data
, n = t.type
, a = t.param
, r = t.key
, o = JSON.parse(JSON.stringify(e));
return "Base64" === n ? a.forEach((function(t) {
o[t] = btoa(o[t])
}
)) : a.forEach((function(t) {
var e = o[t];
r = i.a.enc.Latin1.parse(r);
var n = r
, a = i.a.AES.encrypt(e, r, {
iv: n,
mode: i.a.mode.CBC,
padding: i.a.pad.ZeroPadding
});
o[t] = a.toString()
}
)),
o
}
注意以下被传入的参数:
{
"data": {
"username": "15312341234",
"password": "asda1348315135153",
"redomStr": ""
},
"key": "password.yunjy.y",
"param": [
"password"
]
}
这里出现了i.a.AES.encrypt()
,老办法,先在在控制台输出看看i.a
,果然是包含了很多加密方法,直接用crypto-js
平替,最终本地代码为:
let crypto = require('crypto-js')
function getData(t) {
var e = t.data
, n = t.type
, a = t.param
, r = t.key
, o = JSON.parse(JSON.stringify(e));
return "Base64" === n ? a.forEach((function(t) {
o[t] = btoa(o[t])
}
)) : a.forEach((function(t) {
var e = o[t];
r = crypto.enc.Latin1.parse(r);
var n = r
, a = crypto.AES.encrypt(e, r, {
iv: n,
mode: crypto.mode.CBC,
padding: crypto.pad.ZeroPadding
});
o[t] = a.toString()
}
)),
o
}
var t = {
"data": {
"username": "15312341234",
"password": "asda1348315135153",
"redomStr": ""
},
"key": "password.yunjy.y",
"param": [
"password"
]
}
console.log(getData(t))
运行结果:
{
username: '15312341234',
password: '2JcH1czr87e1kCAbqlXtyw2b8OGpkw44Sfhhfhbz3Nw=',
redomStr: ''
}
与表单重结果一致,逆向完毕
最后优化下代码:
let crypto = require('crypto-js')
function __getData(t) {
var e = t.data
, n = t.type
, a = t.param
, r = t.key
, o = JSON.parse(JSON.stringify(e));
return "Base64" === n ? a.forEach((function(t) {
o[t] = btoa(o[t])
}
)) : a.forEach((function(t) {
var e = o[t];
r = crypto.enc.Latin1.parse(r);
var n = r
, a = crypto.AES.encrypt(e, r, {
iv: n,
mode: crypto.mode.CBC,
padding: crypto.pad.ZeroPadding
});
o[t] = a.toString()
}
)),
o
}
function getData(account,pswd,redomStr){
return __getData({
"data": {
"username": account,
"password": pswd,
"redomStr": redomStr
},
"key": "password.yunjy.y",
"param": [
"password"
]
})
}