1.数组类混淆
现象:定义一个数组,然后js代码中用 [ ] 式访问数组成员
处理后:将数组内成员字符串替换到js中
js = """
var arr = ["Date", "getTime"];
console.log(window[arr[0]]()[arr[1]])
"""
import re
js_arr_name = 'arr'
arr = eval(re.findall(js_arr_name + ' = (\[[\s\S]+?\])', js)[0])
be_replaced_arr_set = set(re.findall(js_arr_name + '\[\d+\]', js))
for be_replaced_arr in be_replaced_arr_set:
res = eval(be_replaced_arr)
js = js.replace(be_replaced_arr, '"' + res + '"')
print('{} 替换完成'.format(res))
print('解混淆后:\n', js)
2.函数混淆
混淆的js代码
var _0xa12e = ['appendChild', 'fromCharCode', 'ifLSL', 'undefined', 'mPDrG', 'DWwdv', 'styleSheets', 'addRule', '::before', '.context_kw', '::before{content:\x20\x22', 'cssRules', 'pad', 'clamp', 'sigBytes', 'YEawH', 'yUSXm', 'PwMPi', 'pLCFG', 'ErKUI', 'OtZki', 'prototype', 'endWith', 'test', '8RHz0u9wbbrXYJjUcstWoRU1SmEIvQZQJtdHeU9/KpK/nBtFWIzLveG63e81APFLLiBBbevCCbRPdingQfzOAFPNPBw4UJCsqrDmVXFe6+LK2CSp26aUL4S+AgWjtrByjZqnYm9H3XEWW+gLx763OGfifuNUB8AgXB7/pnNTwoLjeKDrLKzomC+pXHMGYgQJegLVezvshTGgyVrDXfw4eGSVDa3c/FpDtban34QpS3I=', 'enc', 'Latin1', 'parse', 'window', 'location', 'href', '146385F634C9CB00', 'decrypt', 'ZeroPadding', 'toString', 'split', 'length', 'style', 'type', 'setAttribute', 'async', 'getElementsByTagName', 'NOyra', 'fgQCW', 'nCjZv', 'parentNode', 'insertBefore', 'head'];
(function(_0x4db306, _0x3b5c31) {
var _0x24d797 = function(_0x1ebd20) {
while (--_0x1ebd20) {
_0x4db306['push'](_0x4db306['shift']());
}
};
_0x24d797(++_0x3b5c31);
}(_0xa12e, 0xcc));
var _0xea12 = function(_0x56430f, _0x7f6841) {
_0x56430f = _0x56430f - 0x0;
var _0x4f7a0f = _0xa12e[_0x56430f];
return _0x4f7a0f;
};
CryptoJS[_0xea12('0x0')]['ZeroPadding'] = {
'pad': function(_0x1df06f, _0x314b39) {
var _0x2f7121 = {
'YEawH': function _0x304fdc(_0x154e7c, _0x47ce8e) {
return _0x154e7c - _0x47ce8e;
},
'yUSXm': function _0x15667f(_0x2118a7, _0x202af9) {
return _0x2118a7 % _0x202af9;
}
};
var _0x301b79 = _0x314b39 * 0x4;
_0x1df06f[_0xea12('0x1')]();
_0x1df06f[_0xea12('0x2')] += _0x2f7121[_0xea12('0x3')](_0x301b79, _0x2f7121[_0xea12('0x4')](_0x1df06f['sigBytes'], _0x301b79) || _0x301b79);
},
'unpad': function(_0x3994de) {
var _0x542e1d = {
'PwMPi': function _0x13be60(_0x37e2b3, _0x34d2aa) {
return _0x37e2b3 - _0x34d2aa;
},
'byONr': function _0x41eeb1(_0x42220d, _0x40e5bd) {
return _0x42220d & _0x40e5bd;
},
'pLCFG': function _0x562ecb(_0x2581d9, _0x590c51) {
return _0x2581d9 >>> _0x590c51;
},
'FRqnC': function _0x582fef(_0x4c5451, _0x219412) {
return _0x4c5451 - _0x219412;
},
'DwxPM': function _0x13a0d9(_0x3ce2bb, _0x236747) {
return _0x3ce2bb * _0x236747;
},
'ErKUI': function _0x31d02b(_0x42d286, _0x4a8edd) {
return _0x42d286 % _0x4a8edd;
},
'OtZki': function _0x4024cd(_0x163bf9, _0x543826) {
return _0x163bf9 + _0x543826;
}
};
var _0x32bd3a = _0x3994de['words'];
var _0x2a5053 = _0x542e1d[_0xea12('0x5')](_0x3994de[_0xea12('0x2')], 0x1);
while (!_0x542e1d['byONr'](_0x542e1d['pLCFG'](_0x32bd3a[_0x542e1d[_0xea12('0x6')](_0x2a5053, 0x2)], _0x542e1d['FRqnC'](0x18, _0x542e1d['DwxPM'](_0x542e1d[_0xea12('0x7')](_0x2a5053, 0x4), 0x8))), 0xff)) {
_0x2a5053--;
}
_0x3994de[_0xea12('0x2')] = _0x542e1d[_0xea12('0x8')](_0x2a5053, 0x1);
}
};
String[_0xea12('0x9')][_0xea12('0xa')] = function(_0x4ae995) {
var _0x5ac4ca = {
'khqHo': function _0x4168d6(_0x311e85, _0x420e7f) {
return _0x311e85 + _0x420e7f;
}
};
var _0xa42d0b = new RegExp(_0x5ac4ca['khqHo'](_0x4ae995, '$'));
return _0xa42d0b[_0xea12('0xb')](this);
}
;
var data = _0xea12('0xc');
var keywords = CryptoJS[_0xea12('0xd')][_0xea12('0xe')][_0xea12('0xf')]('6B0600CA9BCE5B24');
var iv = '';
try {
if (top[_0xea12('0x10')][_0xea12('0x11')][_0xea12('0x12')] != window[_0xea12('0x11')]['href']) {
top['window'][_0xea12('0x11')]['href'] = window[_0xea12('0x11')][_0xea12('0x12')];
}
iv = CryptoJS['enc'][_0xea12('0xe')]['parse']('6B0600CA9BCE5B24');
} catch (_0x3f6f9e) {
iv = CryptoJS[_0xea12('0xd')][_0xea12('0xe')]['parse'](_0xea12('0x13'));
}
var decrypted = CryptoJS['AES'][_0xea12('0x14')](data, keywords, {
'iv': iv,
'padding': CryptoJS[_0xea12('0x0')][_0xea12('0x15')]
});
var secWords = decrypted[_0xea12('0x16')](CryptoJS['enc']['Utf8'])[_0xea12('0x17')](',');
var words = new Array(secWords[_0xea12('0x18')]);
var n = document['createElement'](_0xea12('0x19'));
n['setAttribute'](_0xea12('0x1a'), 'text/css');
n[_0xea12('0x1b')](_0xea12('0x1c'), !![]);
var jsLast = function() {
var _0x28d7f2 = {
'NOyra': 'head',
'fgQCW': 'link',
'nCjZv': function _0x5de21d(_0x48b6d5, _0x51ba19) {
return _0x48b6d5 > _0x51ba19;
}
};
var _0x4f2f4a = document[_0xea12('0x1d')](_0x28d7f2[_0xea12('0x1e')])[0x0][_0xea12('0x1d')](_0x28d7f2[_0xea12('0x1f')]);
if (_0x4f2f4a && _0x28d7f2[_0xea12('0x20')](_0x4f2f4a[_0xea12('0x18')], 0x0)) {
return _0x4f2f4a[0x0];
} else {
return null;
}
}();
if (jsLast) {
jsLast[_0xea12('0x21')][_0xea12('0x22')](n, jsLast);
} else {
document[_0xea12('0x1d')](_0xea12('0x23'))[0x0][_0xea12('0x24')](n);
}
for (var i = 0x0; i < secWords[_0xea12('0x18')]; i++) {
var _0x5420ee = '3|5|2|4|0|1'[_0xea12('0x17')]('|')
, _0x9ff9d9 = 0x0;
while (!![]) {
switch (_0x5420ee[_0x9ff9d9++]) {
case '0':
_0x423190 = _0x5796d9(_0x423190);
continue;
case '1':
words[i] = String[_0xea12('0x25')](_0x423190);
continue;
case '2':
var _0x5796d9 = function(_0x490c80) {
var _0x1532b6 = {
'ifLSL': function _0x256992(_0x118bb, _0x36aa09) {
return _0x118bb + _0x36aa09;
}
};
return _0x1532b6[_0xea12('0x26')](_0x490c80, 0x3 * +!(typeof document === _0xea12('0x27')));
};
continue;
case '3':
var _0x423190 = secWords[i];
continue;
case '4':
_0x423190 = _0x3e8e1e(_0x423190);
continue;
case '5':
var _0x3e8e1e = function(_0xd024e1) {
var _0x3e40d1 = {
'mPDrG': function _0x411e6f(_0xa8939, _0x278c20) {
return _0xa8939 % _0x278c20;
},
'DWwdv': function _0x1e0293(_0x5b15eb, _0x443876) {
return _0x5b15eb - _0x443876;
}
};
return _0x3e40d1[_0xea12('0x28')](_0xd024e1, 0x2) ? _0x3e40d1[_0xea12('0x29')](_0xd024e1, 0x2) : _0xd024e1 - 0x4;
};
continue;
}
break;
}
}
for (var i = 0x0; i < words[_0xea12('0x18')]; i++) {
try {
document[_0xea12('0x2a')][0x0][_0xea12('0x2b')]('.context_kw' + i + _0xea12('0x2c'), 'content:\x20\x22' + words[i] + '\x22');
} catch (_0x527f83) {
document['styleSheets'][0x0]['insertRule'](_0xea12('0x2d') + i + _0xea12('0x2e') + words[i] + '\x22}', document[_0xea12('0x2a')][0x0][_0xea12('0x2f')][_0xea12('0x18')]);
}
}
1.混淆的代码中先定义了一个数组_0xa12e
var _0xea12 = function(_0x56430f, _0x7f6841) {
_0x56430f = _0x56430f - 0x0;
var _0x4f7a0f = _0xa12e[_0x56430f];
return _0x4f7a0f;
};
2.将数组重新排序
(function(_0x4db306, _0x3b5c31) {
var _0x24d797 = function(_0x1ebd20) {
while (--_0x1ebd20) {
_0x4db306['push'](_0x4db306['shift']());
}
};
_0x24d797(++_0x3b5c31);
}(_0xa12e, 0xcc));
3.定义一个函数用于解混淆,可以看到下面混淆js代码中多处调用这个函数,最终返回一个字符串,我们的目的就是将函数调用处替换为字符串
var _0xea12 = function(_0x56430f, _0x7f6841) {
_0x56430f = _0x56430f - 0x0;
var _0x4f7a0f = _0xa12e[_0x56430f];
return _0x4f7a0f;
};
4.python代码解混淆实现如下:
import re
import execjs
func_js = """
// 直接用重组后的数组替换原来的数组
var _0xa12e = ['pad', 'clamp', 'sigBytes', 'YEawH', 'yUSXm', 'PwMPi', 'pLCFG', 'ErKUI', 'OtZki', 'prototype', 'endWith', 'test', '8RHz0u9wbbrXYJjUcstWoRU1SmEIvQZQJtdHeU9/KpK/nBtFWIzLveG63e81APFLLiBBbevCCbRPdingQfzOAFPNPBw4UJCsqrDmVXFe6+LK2CSp26aUL4S+AgWjtrByjZqnYm9H3XEWW+gLx763OGfifuNUB8AgXB7/pnNTwoLjeKDrLKzomC+pXHMGYgQJegLVezvshTGgyVrDXfw4eGSVDa3c/FpDtban34QpS3I=', 'enc', 'Latin1', 'parse', 'window', 'location', 'href', '146385F634C9CB00', 'decrypt', 'ZeroPadding', 'toString', 'split', 'length', 'style', 'type', 'setAttribute', 'async', 'getElementsByTagName', 'NOyra', 'fgQCW', 'nCjZv', 'parentNode', 'insertBefore', 'head', 'appendChild', 'fromCharCode', 'ifLSL', 'undefined', 'mPDrG', 'DWwdv', 'styleSheets', 'addRule', '::before', '.context_kw', '::before{content: "', 'cssRules']
// 解混淆用到的函数
function _0xea12(_0x56430f, _0x7f6841) {
_0x56430f = _0x56430f - 0x0;
var _0x4f7a0f = _0xa12e[_0x56430f];
return _0x4f7a0f;
};
"""
js_func_name = '_0xea12'
ctx = execjs.compile(func_js)
with open('混淆.js') as f1:
js = f1.read()
be_replaced_func_set = set(re.findall(js_func_name + "\([\s\S]+?\)", js))
for be_replaced_func in be_replaced_func_set:
args_tuple = re.findall("\(([\s\S]+?)\)", be_replaced_func)[0]
args0 = eval(args_tuple.split(',')[0])
res = ctx.call(js_func_name, args0)
js = js.replace(be_replaced_func, "'" + res + "'")
print('{} 替换完成'.format(res))
with open('解混淆后.js', 'w') as f2:
js = f2.write(js)
6.解混淆后的代码如下
CryptoJS['pad']['ZeroPadding'] = {
'pad': function(_0x1df06f, _0x314b39) {
var _0x2f7121 = {
'YEawH': function _0x304fdc(_0x154e7c, _0x47ce8e) {
return _0x154e7c - _0x47ce8e;
},
'yUSXm': function _0x15667f(_0x2118a7, _0x202af9) {
return _0x2118a7 % _0x202af9;
}
};
var _0x301b79 = _0x314b39 * 0x4;
_0x1df06f['clamp']();
_0x1df06f['sigBytes'] += _0x2f7121['YEawH'](_0x301b79, _0x2f7121['yUSXm'](_0x1df06f['sigBytes'], _0x301b79) || _0x301b79);
},
'unpad': function(_0x3994de) {
var _0x542e1d = {
'PwMPi': function _0x13be60(_0x37e2b3, _0x34d2aa) {
return _0x37e2b3 - _0x34d2aa;
},
'byONr': function _0x41eeb1(_0x42220d, _0x40e5bd) {
return _0x42220d & _0x40e5bd;
},
'pLCFG': function _0x562ecb(_0x2581d9, _0x590c51) {
return _0x2581d9 >>> _0x590c51;
},
'FRqnC': function _0x582fef(_0x4c5451, _0x219412) {
return _0x4c5451 - _0x219412;
},
'DwxPM': function _0x13a0d9(_0x3ce2bb, _0x236747) {
return _0x3ce2bb * _0x236747;
},
'ErKUI': function _0x31d02b(_0x42d286, _0x4a8edd) {
return _0x42d286 % _0x4a8edd;
},
'OtZki': function _0x4024cd(_0x163bf9, _0x543826) {
return _0x163bf9 + _0x543826;
}
};
var _0x32bd3a = _0x3994de['words'];
var _0x2a5053 = _0x542e1d['PwMPi'](_0x3994de['sigBytes'], 0x1);
while (!_0x542e1d['byONr'](_0x542e1d['pLCFG'](_0x32bd3a[_0x542e1d['pLCFG'](_0x2a5053, 0x2)], _0x542e1d['FRqnC'](0x18, _0x542e1d['DwxPM'](_0x542e1d['ErKUI'](_0x2a5053, 0x4), 0x8))), 0xff)) {
_0x2a5053--;
}
_0x3994de['sigBytes'] = _0x542e1d['OtZki'](_0x2a5053, 0x1);
}
};
String['prototype']['endWith'] = function(_0x4ae995) {
var _0x5ac4ca = {
'khqHo': function _0x4168d6(_0x311e85, _0x420e7f) {
return _0x311e85 + _0x420e7f;
}
};
var _0xa42d0b = new RegExp(_0x5ac4ca['khqHo'](_0x4ae995, '$'));
return _0xa42d0b['test'](this);
}
;
var data = '8RHz0u9wbbrXYJjUcstWoRU1SmEIvQZQJtdHeU9/KpK/nBtFWIzLveG63e81APFLLiBBbevCCbRPdingQfzOAFPNPBw4UJCsqrDmVXFe6+LK2CSp26aUL4S+AgWjtrByjZqnYm9H3XEWW+gLx763OGfifuNUB8AgXB7/pnNTwoLjeKDrLKzomC+pXHMGYgQJegLVezvshTGgyVrDXfw4eGSVDa3c/FpDtban34QpS3I=';
var keywords = CryptoJS['enc']['Latin1']['parse']('6B0600CA9BCE5B24');
var iv = '';
try {
if (top['window']['location']['href'] != window['location']['href']) {
top['window']['location']['href'] = window['location']['href'];
}
iv = CryptoJS['enc']['Latin1']['parse']('6B0600CA9BCE5B24');
} catch (_0x3f6f9e) {
iv = CryptoJS['enc']['Latin1']['parse']('146385F634C9CB00');
}
var decrypted = CryptoJS['AES']['decrypt'](data, keywords, {
'iv': iv,
'padding': CryptoJS['pad']['ZeroPadding']
});
var secWords = decrypted['toString'](CryptoJS['enc']['Utf8'])['split'](',');
var words = new Array(secWords['length']);
var n = document['createElement']('style');
n['setAttribute']('type', 'text/css');
n['setAttribute']('async', !![]);
var jsLast = function() {
var _0x28d7f2 = {
'NOyra': 'head',
'fgQCW': 'link',
'nCjZv': function _0x5de21d(_0x48b6d5, _0x51ba19) {
return _0x48b6d5 > _0x51ba19;
}
};
var _0x4f2f4a = document['getElementsByTagName'](_0x28d7f2['NOyra'])[0x0]['getElementsByTagName'](_0x28d7f2['fgQCW']);
if (_0x4f2f4a && _0x28d7f2['nCjZv'](_0x4f2f4a['length'], 0x0)) {
return _0x4f2f4a[0x0];
} else {
return null;
}
}();
if (jsLast) {
jsLast['parentNode']['insertBefore'](n, jsLast);
} else {
document['getElementsByTagName']('head')[0x0]['appendChild'](n);
}
for (var i = 0x0; i < secWords['length']; i++) {
var _0x5420ee = '3|5|2|4|0|1'['split']('|')
, _0x9ff9d9 = 0x0;
while (!![]) {
switch (_0x5420ee[_0x9ff9d9++]) {
case '0':
_0x423190 = _0x5796d9(_0x423190);
continue;
case '1':
words[i] = String['fromCharCode'](_0x423190);
continue;
case '2':
var _0x5796d9 = function(_0x490c80) {
var _0x1532b6 = {
'ifLSL': function _0x256992(_0x118bb, _0x36aa09) {
return _0x118bb + _0x36aa09;
}
};
return _0x1532b6['ifLSL'](_0x490c80, 0x3 * +!(typeof document === 'undefined'));
};
continue;
case '3':
var _0x423190 = secWords[i];
continue;
case '4':
_0x423190 = _0x3e8e1e(_0x423190);
continue;
case '5':
var _0x3e8e1e = function(_0xd024e1) {
var _0x3e40d1 = {
'mPDrG': function _0x411e6f(_0xa8939, _0x278c20) {
return _0xa8939 % _0x278c20;
},
'DWwdv': function _0x1e0293(_0x5b15eb, _0x443876) {
return _0x5b15eb - _0x443876;
}
};
return _0x3e40d1['mPDrG'](_0xd024e1, 0x2) ? _0x3e40d1['DWwdv'](_0xd024e1, 0x2) : _0xd024e1 - 0x4;
};
continue;
}
break;
}
}
for (var i = 0x0; i < words['length']; i++) {
try {
document['styleSheets'][0x0]['addRule']('.context_kw' + i + '::before', 'content:\x20\x22' + words[i] + '\x22');
} catch (_0x527f83) {
document['styleSheets'][0x0]['insertRule']('.context_kw' + i + '::before{content: "' + words[i] + '\x22}', document['styleSheets'][0x0]['cssRules']['length']);
}
}
解混淆的代码可以用火狐浏览器的美化源代码把0x0这种16进制字符替换。
_0x3e8e1e 形式的变量名是无法还原的,不过经过上面的步骤代码阅读性明显提升