文章目录

  • 前言
  • 一、AES算法介绍
  • 二、js文件代码
  • 1、util.js文件
  • 2、aes.js文件
  • 三、代码分析
  • 1.分析加密调用及过程
  • 2. 分析e(key),n(iv)生成的过程
  • 总结



前言

最近老同学在搞app的渗透测试,在提交数据的时候,发现抓到的数据包都是经过加密的的。接着反手甩给我两个实现的js文件。“帮忙找一下aes加密的key和iv值”,有活干了,有活干了!


提示:以下是本篇文章正文内容

一、AES算法介绍

aes属于对称加密算法,解密与加密都使用同一密钥,也称为但密钥加密算法
AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密

二、js文件代码

1、util.js文件

代码如下:

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();
};

2、aes.js文件

由于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加密的过程。

1.分析加密调用及过程

在分析中,可以看到直接调用中 n 赋值给了iv,也就是aes的偏移参数值。了解过aes加密或者解密的同学们众所周知util.js文中的AES.encrypt(a,e,{…}) 参数e的位置就是密钥参数位置,所以e是密钥。

因此,我第一想到的是能不能在调用aes加密过程中把密钥“e”与“n”直接打印出来,结果如下图所示,出来的是一串列表数组形式的数据值。所以这也不是真正的key与iv值,通过了解应该某种函数解密转换得到的。

IOS对入参进行AES加密 aes加密iv_赋值

IOS对入参进行AES加密 aes加密iv_前端_02

2. 分析e(key),n(iv)生成的过程

既然是通过某种函数解密转换得到的,那中间肯定会有明文的key与iv值出现过,只需要跟踪到没加密之前的明文就能知道了。

IOS对入参进行AES加密 aes加密iv_IOS对入参进行AES加密_03

分析过程:

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));

IOS对入参进行AES加密 aes加密iv_前端_04

到此结束

总结

在分析过程中,我们可以根据要观察的变量或者值,一步一步的跟随变量生成之前在代码执行中进行了那些操作,便可很快的得到我们想要的信息