最近老同学在搞app的渗透测试,在提交数据的时候,发现抓到的数据包都是经过加密的的。接着反手甩给我两个实现的js文件。“帮忙找一下aes加密的key和iv值”,有活干了,有活干了!
提示:以下是本篇文章正文内容
aes属于对称加密算法,解密与加密都使用同一密钥,也称为但密钥加密算法
AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密
代码如下:
var r = require("./aes.js"), t = a;
!function (r, t) {
for (var e = a, n = s(); ;) try {
if (484953 === -parseInt(e(358)) / 1 + -parseInt(e(353)) / 2 * (parseInt(e(357)) / 3) + -parseInt(e(360)) / 4 + -parseInt(e(361)) / 5 + -parseInt(e(355)) / 6 + parseInt(e(349)) / 7 + parseInt(e(356)) / 8) break;
n.push(n.shift());
} catch (r) {
n.push(n.shift());
}
}();
var e = (r = require(t(350)))[t(352)].Utf8[t(359)](t(354) + t(351)), n = r[t(352)].Utf8.parse(t(354) + t(351));
function a(r, t) {
var e = s();
return (a = function (r, t) {
return e[r -= 349];
})(r, t);
}
function s() {
var r = ["060708", "enc", "4gvWuDt", "0102030405", "5378064oDbRIP", "18034816mbibaH", "1362843FfkXtE", "432180CsAsqb", "parse", "456368SYwkrf", "1930445LzbczB", "6775076tiaYah", "./aes.js"];
return (s = function () {
return r;
})();
}
module.exports.Decrypt = function (t) {
var a = r.enc.Hex.parse(t), s = r.enc.Base64.stringify(a);
console.log(a);
console.log(s);
return r.AES.decrypt(s, e, {
iv: n,
mode: r.mode.CBC,
padding: r.pad.Pkcs7
}).toString(r.enc.Utf8).toString();
}, module.exports.Encrypt = function (t) {
var a = r.enc.Utf8.parse(t);
console.log(a);
return r.AES.encrypt(a, e, {
iv: n,
mode: r.mode.CBC,
padding: r.pad.Pkcs7
}).ciphertext.toString().toUpperCase();
};
由于aes.js中代码太长了,这里这放出一部分
代码如下:
var t, e, r = r || function(t, e) {
var r = {}, i = r.lib = {}, n = function() {}, s = i.Base = {
extend: function(t) {
n.prototype = this;
var e = new n();
return t && e.mixIn(t), e.hasOwnProperty("init") || (e.init = function() {
e.$super.init.apply(this, arguments);
}), e.init.prototype = e, e.$super = this, e;
},
create: function() {
var t = this.extend();
return t.init.apply(t, arguments), t;
},
init: function() {},
mixIn: function(t) {
for (var e in t) t.hasOwnProperty(e) && (this[e] = t[e]);
t.hasOwnProperty("toString") && (this.toString = t.toString);
},
clone: function() {
return this.init.prototype.extend(this);
}
}, o = i.WordArray = s.extend({
init: function(t, e) {
t = this.words = t || [], this.sigBytes = null != e ? e : 4 * t.length;
},
toString: function(t) {
return (t || a).stringify(this);
},
concat: function(t) {
var e = this.words, r = t.words, i = this.sigBytes;
if (t = t.sigBytes, this.clamp(), i % 4) for (var n = 0; n < t; n++) e[i + n >>> 2] |= (r[n >>> 2] >>> 24 - n % 4 * 8 & 255) << 24 - (i + n) % 4 * 8; else if (65535 < r.length) for (n = 0; n < t; n += 4) e[i + n >>> 2] = r[n >>> 2]; else e.push.apply(e, r);
return this.sigBytes += t, this;
},
clamp: function() {
var e = this.words, r = this.sigBytes;
e[r >>> 2] &= 4294967295 << 32 - r % 4 * 8, e.length = t.ceil(r / 4);
},
clone: function() {
var t = s.clone.call(this);
return t.words = this.words.slice(0), t;
},
random: function(e) {
for (var r = [], i = 0; i < e; i += 4) r.push(4294967296 * t.random() | 0);
return new o.init(r, e);
}
}), c = r.enc = {}, a = c.Hex = {
stringify: function(t) {
var e = t.words;
t = t.sigBytes;
for (var r = [], i = 0; i < t; i++) {
var n = e[i >>> 2] >>> 24 - i % 4 * 8 & 255;
r.push((n >>> 4).toString(16)), r.push((15 & n).toString(16));
}
return r.join("");
},
parse: function(t) {
for (var e = t.length, r = [], i = 0; i < e; i += 2) r[i >>> 3] |= parseInt(t.substr(i, 2), 16) << 24 - i % 8 * 4;
return new o.init(r, e / 2);
}
}, f = c.Latin1 = {
stringify: function(t) {
var e = t.words;
t = t.sigBytes;
for (var r = [], i = 0; i < t; i++) r.push(String.fromCharCode(e[i >>> 2] >>> 24 - i % 4 * 8 & 255));
return r.join("");
},
parse: function(t) {
for (var e = t.length, r = [], i = 0; i < e; i++) r[i >>> 2] |= (255 & t.charCodeAt(i)) << 24 - i % 4 * 8;
return new o.init(r, e);
}
}, h = c.Utf8 = {
stringify: function(t) {
try {
return decodeURIComponent(escape(f.stringify(t)));
} catch (t) {
throw Error("Malformed UTF-8 data");
}
},.............
................
...................
在上面的两个js文件中通过简单的分析后,得出util.js文件主要是进行调用aes加密的,而aes.js文件是实现aes加密的过程。
在分析中,可以看到直接调用中 n 赋值给了iv,也就是aes的偏移参数值。了解过aes加密或者解密的同学们众所周知util.js文中的AES.encrypt(a,e,{…}) 参数e的位置就是密钥参数位置,所以e是密钥。
因此,我第一想到的是能不能在调用aes加密过程中把密钥“e”与“n”直接打印出来,结果如下图所示,出来的是一串列表数组形式的数据值。所以这也不是真正的key与iv值,通过了解应该某种函数解密转换得到的。
既然是通过某种函数解密转换得到的,那中间肯定会有明文的key与iv值出现过,只需要跟踪到没加密之前的明文就能知道了。
1.在util.js文件的16行中对e,n进行了赋值:
var e = (r = require(t(350)))[t(352)].Utf8[t(359)](t(354) + t(351)), n = r[t(352)].Utf8.parse(t(354) + t(351));
2.其中的初始r数组值是:
var r = ["060708", "enc", "4gvWuDt", "0102030405", "5378064oDbRIP", "18034816mbibaH", "1362843FfkXtE", "432180CsAsqb", "parse", "456368SYwkrf", "1930445LzbczB", "6775076tiaYah", "./aes.js"];
3.在开头文件中:var r = require("./aes.js"), t = a;//t=a;而a是一个函数
function a(r, t) {
var e = s();
return (a = function (r, t) {
return e[r -= 349];
})(r, t);
}
4.在e,n赋值生成之前还执行了这一段代码,调试分析过程发现是对原始数组r进行了多次的重新组合。
最终得到新的组合
//新的组合:r=["6775076tiaYah","./aes.js","060708","enc","4gvWuDt","0102030405","5378064oDbRIP","18034816mbibaH","1362843FfkXtE","432180CsAsqb","parse","456368SYwkrf","1930445LzbczB",]
!function (r, t) {
for (var e = a, n = s(); ;) try { //进行多次循环组合s()的r数组,得到新的组合r =["6775076tiaYah","./aes.js","060708","enc","4gvWuDt","0102030405","5378064oDbRIP","18034816mbibaH","1362843FfkXtE","432180CsAsqb","parse","456368SYwkrf","1930445LzbczB",]
if (484953 === -parseInt(e(358)) / 1 + -parseInt(e(353)) / 2 * (parseInt(e(357)) / 3) + -parseInt(e(360)) / 4 + -parseInt(e(361)) / 5 + -parseInt(e(355)) / 6 + parseInt(e(349)) / 7 + parseInt(e(356)) / 8) break;
n.push(n.shift());
} catch (r) {
n.push(n.shift());
}
}();
5.这里赋值得到未加密的e,n值, "0102030405060708" 作为参数值 执行require("./aes.js").enc.Utf8.parse() 函数进行了转换。
所以到这一步很明显了,"0102030405060708" 就是明文key与iv值
//e = (r=require(./aes.js))[enc].Utf8[parse]('0102030405' + '060708'), r=require("./aes.js").enc.Utf8.parse('0102030405060708')
var e = (r = require(t(350)))[t(352)].Utf8[t(359)](t(354) + t(351)), n = r[t(352)].Utf8.parse(t(354) + t(351));
在分析过程中,我们可以根据要观察的变量或者值,一步一步的跟随变量生成之前在代码执行中进行了那些操作,便可很快的得到我们想要的信息