Ast实战:反混淆解析中等难度ob混淆网站
https://obfuscator.io/

一、混淆demo生成

二、混淆demo生成

三、混淆demo整理

demo.js
//TODO  这里对混淆demo进行了手动调整顺序操作,为了便于阅读,进行了格式化处理操作function _0x3b9f() {var _0x2f0b48 = ['y29UC29Szq', 'C2vHCMnO', 'C3bSAxq', 'ChjVDg90ExbL', 'zhv4tu8', 'se5jvNq', 'mty0Cu1lCMDZ', 'Dg9tDhjPBMC', 'BKrtDfq', 'BMLAAwO', 'mtu0odG5mwrKzxPkBG', 'AfP4wLK', 'q2LhrLO', 'EhPLrxK', 'r1rjAuu', 'EgXjA3y', 'uwnqCvK', 'mJG2ntaYreDtEgTA', 'x19WCM90B19F', 'y1ryzMC', 'vMzOv20', 'mvbAtu1mzG', 'quTOChO', 'rMXOqNm', 'nZCXmJy5meLsyMX6vW', 'vgLjzMm', 'CM4GDgHPCYiPka', 'zeLxzMi', 'twHkAgS', 'odu3nMHuvMHLzq', 'rwzKEhe', 'Bg9N', 'ELLpCvC', 'yMLUza', 'wu9Lv08', 'BxrnCNi', 'CxvPr1m', 'mtK1odu4tg9rEKLO', 'zuXstfa', 'zxHJzxb0Aw9U', 'D2fYBG', 'mhWXFdr8mNWZ', 'E30Uy29UC3rYDq', 'ndmYnty0m3fsAwzrrq', 'zxjYB3i', 'DhjHy2u', 'qLHmtKG', 'AuPmAgS', 'DKfPDMO', 'ntK0ndvfsMjbB3K', 'nxW0Fdj8mxWZFa', 'kcGOlISPkYKRkq', 'D2XlDKu', 'yxbWBhK', 'mte4m2jRtgrjBq', 'CLHovM4', 'y29UC3rYDwn0BW', 'EgXHrhu', 'sgvSBg8Gv29YBa', 'BMn0Aw9UkcKG', 'qLjNyLa', 'v3vYsfK', 'sNvusKu', 'suTOBhu', 'y3rVCIGICMv0Dq', 'mNWXFdb8nhWZFa'];_0x3b9f = function () {return _0x2f0b48;};return _0x3b9f();
}
(function (_0x44be41, _0x16882c) {function _0x4a44c1(_0x5126c6, _0x19c97d, _0x2631aa, _0x1095e3) {return _0x1a4b(_0x1095e3 - -0x389, _0x19c97d);}var _0x2bb8e7 = _0x44be41();function _0x27767a(_0x270fbf, _0x11ecaf, _0x579cec, _0x13a99c) {return _0x1a4b(_0x270fbf - -0xfc, _0x579cec);}while (!![]) {try {var _0x20ba40 = -parseInt(_0x4a44c1(-0x272, -0x27a, -0x265, -0x263)) / (-0x1 * -0x189e + -0xa5 + -0x17f8) * (-parseInt(_0x4a44c1(-0x25e, -0x271, -0x27b, -0x267)) / (-0x1523 + 0x2 * 0xd8a + 0x1 * -0x5ef)) + parseInt(_0x27767a(0x1f, 0x21, 0x26, 0x1e)) / (0x3 * -0x62f + 0x1364 + 0xd4 * -0x1) + parseInt(_0x4a44c1(-0x278, -0x273, -0x260, -0x272)) / (0x1841 + 0x752 * 0x4 + -0x3 * 0x11d7) * (-parseInt(_0x4a44c1(-0x293, -0x276, -0x288, -0x289)) / (0x1e7 * -0x7 + -0x212d + 0x2e83)) + parseInt(_0x27767a(0x3a, 0x22, 0x23, 0x2d)) / (0x1a9 * -0x9 + -0x1 * -0xcd3 + 0x2 * 0x112) + parseInt(_0x27767a(0x9, 0x25, -0xf, 0x19)) / (-0xb30 + -0x2186 + 0x2cbd) * (-parseInt(_0x27767a(0x32, 0x29, 0x46, 0x4c)) / (-0x1f16 + -0xa2 + -0x2 * -0xfe0)) + -parseInt(_0x27767a(0x40, 0x36, 0x50, 0x44)) / (-0x1859 + 0x455 * 0x4 + 0x70e) + parseInt(_0x4a44c1(-0x27f, -0x244, -0x25d, -0x260)) / (-0x1 * 0xbef + -0xdfa * -0x2 + 0x1 * -0xffb);if (_0x20ba40 === _0x16882c) break; else _0x2bb8e7['push'](_0x2bb8e7['shift']());} catch (_0x38f79d) {_0x2bb8e7['push'](_0x2bb8e7['shift']());}}
}(_0x3b9f, -0x314a + 0x61e8 + 0x49aca));
function _0x1a4b(_0x1ff7f0, _0x131d9a) {var _0x3e0d69 = _0x3b9f();return _0x1a4b = function (_0x44cee0, _0x4d885f) {_0x44cee0 = _0x44cee0 - (0x1 * -0x1b1c + -0x5be + 0x21d7);var _0xeb9081 = _0x3e0d69[_0x44cee0];if (_0x1a4b['FvZmJG'] === undefined) {var _0x5503a2 = function (_0xf0e451) {var _0x3c638b = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x3a215e = '', _0x5e8955 = '', _0x50ceaf = _0x3a215e + _0x5503a2;for (var _0x48609a = 0x23d6 + -0x1 * -0x214f + 0x1f * -0x23b, _0x179431, _0x48f725, _0x59423a = -0x1 * 0x607 + 0x285 * -0x5 + -0x20 * -0x95; _0x48f725 = _0xf0e451['charAt'](_0x59423a++); ~_0x48f725 && (_0x179431 = _0x48609a % (0x1bd3 + -0x5c1 + -0x75a * 0x3) ? _0x179431 * (0x1 * -0x1812 + 0x4ec + 0x2 * 0x9b3) + _0x48f725 : _0x48f725, _0x48609a++ % (-0xf78 + -0x4e * 0x3d + 0x2212)) ? _0x3a215e += _0x50ceaf['charCodeAt'](_0x59423a + (0x26ac + 0x72 * 0x39 + -0x4004)) - (0x1e53 * -0x1 + -0xc37 + 0x884 * 0x5) !== 0x1f9e + 0x4 * 0x739 + -0x3c82 ? String['fromCharCode'](-0x230b * -0x1 + -0x270b + 0x4ff * 0x1 & _0x179431 >> (-(-0x3a * 0x8f + 0x11d4 + 0xe94) * _0x48609a & -0x1a53 + 0x9 * 0x2c9 + -0x1 * -0x148)) : _0x48609a : 0x543 + 0x9c * -0x34 + 0x8cf * 0x3) {_0x48f725 = _0x3c638b['indexOf'](_0x48f725);}for (var _0x42c1c2 = 0x178b + -0x231a + 0xb8f, _0x292508 = _0x3a215e['length']; _0x42c1c2 < _0x292508; _0x42c1c2++) {_0x5e8955 += '%' + ('00' + _0x3a215e['charCodeAt'](_0x42c1c2)['toString'](-0x1 * -0x1a17 + 0x27 + 0x6 * -0x45d))['slice'](-(-0x51c + 0xa12 + -0x4f4));}return decodeURIComponent(_0x5e8955);};_0x1a4b['xKAOex'] = _0x5503a2, _0x1ff7f0 = arguments, _0x1a4b['FvZmJG'] = !![];}var _0x533832 = _0x3e0d69[-0x1a93 + 0xa3e + 0x1055], _0x563229 = _0x44cee0 + _0x533832,_0x33fb5e = _0x1ff7f0[_0x563229];if (!_0x33fb5e) {var _0x153b52 = function (_0x4275ed) {this['jloeKJ'] = _0x4275ed, this['LTMphp'] = [0x9 * 0x215 + 0xcc6 * -0x3 + 0x1396, -0x1 * -0xe65 + 0x9a6 + -0x180b, 0x1 * 0x2342 + -0x1c40 + -0x12b * 0x6], this['avhEaf'] = function () {return 'newState';}, this['CmjSbR'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*', this['QsPoCx'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x153b52['prototype']['xAUDvB'] = function () {var _0x26a156 = new RegExp(this['CmjSbR'] + this['QsPoCx']),_0x3872ae = _0x26a156['test'](this['avhEaf']['toString']()) ? --this['LTMphp'][-0x2af + -0x15b + 0x40b] : --this['LTMphp'][-0x246a + 0x82 * 0x2e + 0xd0e];return this['rZQkIl'](_0x3872ae);}, _0x153b52['prototype']['rZQkIl'] = function (_0x482e39) {if (!Boolean(~_0x482e39)) return _0x482e39;return this['HecVJE'](this['jloeKJ']);}, _0x153b52['prototype']['HecVJE'] = function (_0x386c39) {for (var _0x5e442f = 0x5c2 * -0x5 + -0x2 * 0x4c1 + 0x264c, _0x2106d6 = this['LTMphp']['length']; _0x5e442f < _0x2106d6; _0x5e442f++) {this['LTMphp']['push'](Math['round'](Math['random']())), _0x2106d6 = this['LTMphp']['length'];}return _0x386c39(this['LTMphp'][-0x1 * 0x251 + -0x498 + -0x1 * -0x6e9]);}, new _0x153b52(_0x1a4b)['xAUDvB'](), _0xeb9081 = _0x1a4b['xKAOex'](_0xeb9081), _0x1ff7f0[_0x563229] = _0xeb9081;} else _0xeb9081 = _0x33fb5e;return _0xeb9081;}, _0x1a4b(_0x1ff7f0, _0x131d9a);
}
function hi() {var _0x3cf8b3 = {'GTIiE': function (_0x1e685a, _0x4de1a0) {return _0x1e685a(_0x4de1a0);},'VfhWm': _0x3cc66f(0x4d8, 0x49d, 0x4ba, 0x4ab) + _0x3cc66f(0x49b, 0x47b, 0x48e, 0x4a6) + _0x3cc66f(0x4b0, 0x490, 0x4aa, 0x499) + '\x20)','WurHY': _0x3cc66f(0x49f, 0x4d4, 0x4b8, 0x49e),'HNIVt': 'info','IKhlu': _0x1c1ba8(0x26d, 0x29c, 0x2a3, 0x285),'MhJhk': _0x1c1ba8(0x283, 0x263, 0x285, 0x280),'xlaDu': 'table','Efdxq': _0x3cc66f(0x4a8, 0x4b2, 0x4bd, 0x4a9),'FlhBs': function (_0x59e95b, _0x5a2f06) {return _0x59e95b === _0x5a2f06;},'QcPqY': _0x3cc66f(0x46c, 0x462, 0x482, 0x48d),'vAivj': _0x1c1ba8(0x258, 0x256, 0x246, 0x24a) + '+$','nDStT': _0x3cc66f(0x47b, 0x481, 0x480, 0x499) + '0','LHxvU': _0x3cc66f(0x48d, 0x4a8, 0x49f, 0x47f),'eaBot': _0x1c1ba8(0x293, 0x28b, 0x29a, 0x27c),'cTXfg': function (_0x55201e, _0x353ea5) {return _0x55201e + _0x353ea5;},'JuTJE': function (_0x2dea49) {return _0x2dea49();},'uGlBj': _0x1c1ba8(0x276, 0x28f, 0x289, 0x278),'ktZGJ': function (_0x4cdb37, _0x29eb33) {return _0x4cdb37 < _0x29eb33;},'ksGMS': function (_0x3652df, _0x400262, _0xc74ae) {return _0x3652df(_0x400262, _0xc74ae);},'YOeWO': function (_0x149814) {return _0x149814();},'AKhpz': function (_0x3d52c8) {return _0x3d52c8();},'xzeEy': _0x3cc66f(0x4a6, 0x494, 0x488, 0x46c) + 'd!'}, _0xbe54d9 = function () {var _0x43c2f8 = {'dIWfb': _0x5f3d71(0x24a, 0x235, 0x24c, 0x23e),'duxMO': function (_0x368796, _0x3c7e98) {function _0x3a7fcf(_0xe32883, _0x43903f, _0x5d2da1, _0x270b79) {return _0x5f3d71(_0xe32883 - 0x55, _0x43903f - -0x20d, _0x5d2da1 - 0x15c, _0xe32883);}return _0x3cf8b3[_0x3a7fcf(0x5, 0xd, 0x21, 0x17)](_0x368796, _0x3c7e98);},'TiIfc': _0x3cf8b3[_0x5f3d71(0x208, 0x220, 0x212, 0x204)],'quiGS': function (_0x539c28) {return _0x539c28();},'ocRpV': _0x3cf8b3[_0x5f3d71(0x224, 0x207, 0x223, 0x1ec)],'BXLNH': _0x3cf8b3['HNIVt'],'zYOqW': _0x3cf8b3[_0x2bbc92(0xa7, 0xa4, 0x8b, 0xa4)],'rXNVn': _0x3cf8b3[_0x2bbc92(0xa5, 0xb6, 0xaa, 0xb6)],'niZij': _0x3cf8b3[_0x2bbc92(0x96, 0x75, 0x85, 0x7a)],'hZxZY': _0x3cf8b3[_0x5f3d71(0x21a, 0x22a, 0x218, 0x213)]};function _0x2bbc92(_0x4bf3af, _0x5503fe, _0x69fc2e, _0x58dc47) {return _0x1c1ba8(_0x4bf3af - 0x50, _0x5503fe, _0x69fc2e - 0x16d, _0x69fc2e - -0x1cb);}function _0x5f3d71(_0x18a52d, _0x8c3758, _0x23334d, _0x1a1afe) {return _0x1c1ba8(_0x18a52d - 0xb0, _0x1a1afe, _0x23334d - 0x1dc, _0x8c3758 - -0x4d);}if (_0x3cf8b3[_0x5f3d71(0x239, 0x223, 0x244, 0x219)](_0x3cf8b3[_0x2bbc92(0xb7, 0x90, 0x9e, 0x94)], _0x2bbc92(0x88, 0x62, 0x80, 0x91))) {var _0x4f5216 = !![];return function (_0x1b38cd, _0x368b71) {var _0x40fb1e = {};function _0x3f93cd(_0x46b708, _0x4561b4, _0x1c0477, _0x4feb62) {return _0x5f3d71(_0x46b708 - 0x1f2, _0x4feb62 - 0x23d, _0x1c0477 - 0x87, _0x46b708);}_0x40fb1e[_0x3f93cd(0x483, 0x455, 0x490, 0x46f)] = function (_0xd2c84b, _0x485117) {return _0xd2c84b === _0x485117;}, _0x40fb1e[_0x3f93cd(0x446, 0x437, 0x422, 0x443)] = 'CiGFZ';var _0x1fb335 = _0x40fb1e;function _0x2a0647(_0x2743d1, _0x12f602, _0x23ff46, _0xbc6365) {return _0x5f3d71(_0x2743d1 - 0x45, _0x23ff46 - -0x1d8, _0x23ff46 - 0x81, _0xbc6365);}var _0x502b34 = _0x4f5216 ? function () {function _0xa85ac9(_0x14f4c1, _0x2ac490, _0x13a9f2, _0x122d91) {return _0x3f93cd(_0x13a9f2, _0x2ac490 - 0x192, _0x13a9f2 - 0x1cf, _0x122d91 - -0x5c6);}function _0x3b1a3f(_0x3ceefb, _0x40f165, _0x115b59, _0x227830) {return _0x2a0647(_0x3ceefb - 0xe6, _0x40f165 - 0xb, _0x227830 - 0x26c, _0x40f165);}if (_0x1fb335['eLRLP'](_0x1fb335[_0x3b1a3f(0x2ab, 0x280, 0x2b9, 0x29a)], _0xa85ac9(-0x189, -0x169, -0x18e, -0x171))) {if (_0x368b71) {var _0xdd1069 = _0x368b71[_0xa85ac9(-0x171, -0x173, -0x1a2, -0x18a)](_0x1b38cd, arguments);return _0x368b71 = null, _0xdd1069;}} else _0x3cbd80 = _0x4cc43b;} : function () {};return _0x4f5216 = ![], _0x502b34;};} else {var _0x94758 = _0x43c2f8[_0x5f3d71(0x228, 0x227, 0x23b, 0x233)][_0x2bbc92(0x95, 0x83, 0x90, 0x98)]('|'),_0x4f1a1b = 0x1789 + -0x2607 + 0xe * 0x109;while (!![]) {switch (_0x94758[_0x4f1a1b++]) {case'0':var _0x5e4868;continue;case'1':try {var _0x55e0c2 = nLrTxa[_0x2bbc92(0xa9, 0x97, 0x92, 0x9e)](_0x5a707d, 'return\x20(fu' + _0x5f3d71(0x204, 0x205, 0x211, 0x1fb) + nLrTxa[_0x2bbc92(0xaa, 0x9d, 0xa7, 0xc8)] + ');');_0x5e4868 = nLrTxa[_0x5f3d71(0x239, 0x230, 0x216, 0x240)](_0x55e0c2);} catch (_0x2fc85e) {_0x5e4868 = _0x41422b;}continue;case'2':var _0x3ce37c = [_0x5f3d71(0x210, 0x22b, 0x23f, 0x224), nLrTxa['ocRpV'], nLrTxa[_0x5f3d71(0x200, 0x1f8, 0x1ee, 0x210)], nLrTxa[_0x5f3d71(0x214, 0x22c, 0x23a, 0x24d)], nLrTxa[_0x2bbc92(0x7a, 0x6d, 0x83, 0x90)], nLrTxa[_0x5f3d71(0x203, 0x215, 0x213, 0x222)], nLrTxa[_0x5f3d71(0x21c, 0x217, 0x20c, 0x230)]];continue;case'3':for (var _0x1147e4 = -0x1157 + 0x2142 + -0xfeb; _0x1147e4 < _0x3ce37c['length']; _0x1147e4++) {var _0x63be3e = (_0x5f3d71(0x22a, 0x20b, 0x20d, 0x21e) + '5')[_0x2bbc92(0xa9, 0x80, 0x90, 0x90)]('|'),_0x20cc43 = -0x1984 + -0x1 * 0x4a6 + 0x1e2a;while (!![]) {switch (_0x63be3e[_0x20cc43++]) {case'0':var _0x13a106 = _0x5c074b[_0x1e142b] || _0x2d5b76;continue;case'1':var _0x1e142b = _0x3ce37c[_0x1147e4];continue;case'2':var _0x2d5b76 = _0x3b76b9['constructo' + 'r'][_0x2bbc92(0x9d, 0xa5, 0x91, 0xb1)][_0x5f3d71(0x21c, 0x22d, 0x220, 0x246)](_0x3fc66d);continue;case'3':_0x2d5b76[_0x5f3d71(0x234, 0x213, 0x203, 0x210)] = _0x13a106['toString'][_0x5f3d71(0x21b, 0x22d, 0x20f, 0x218)](_0x13a106);continue;case'4':_0x2d5b76['__proto__'] = _0x2f6a05[_0x5f3d71(0x22e, 0x22d, 0x212, 0x21a)](_0x3c5a99);continue;case'5':_0x5c074b[_0x1e142b] = _0x2d5b76;continue;}break;}}continue;case'4':var _0x5c074b = _0x5e4868[_0x5f3d71(0x202, 0x20c, 0x20b, 0x226)] = _0x5e4868['console'] || {};continue;}break;}}}(), _0x5427d6 = _0x3cf8b3['ksGMS'](_0xbe54d9, this, function () {function _0x1fcc8f(_0x265d4d, _0x2b9c12, _0x18e029, _0x3be322) {return _0x3cc66f(_0x2b9c12, _0x2b9c12 - 0x5, _0x18e029 - -0x411, _0x3be322 - 0x13c);}function _0xf64544(_0x3a76c4, _0x212cc6, _0x553e56, _0x449f1b) {return _0x3cc66f(_0x212cc6, _0x212cc6 - 0x34, _0x553e56 - -0x160, _0x449f1b - 0x139);}return _0x5427d6[_0xf64544(0x32d, 0x357, 0x337, 0x31e)]()[_0xf64544(0x33b, 0x324, 0x331, 0x312)](_0x3cf8b3[_0xf64544(0x314, 0x33f, 0x31e, 0x334)])[_0xf64544(0x318, 0x31e, 0x337, 0x352)]()['constructo' + 'r'](_0x5427d6)[_0xf64544(0x32a, 0x33b, 0x331, 0x329)](_0x1fcc8f(0x55, 0x62, 0x70, 0x54) + '+$');});function _0x3cc66f(_0x147110, _0x58a972, _0x43b4b0, _0x2ad44a) {return _0x1a4b(_0x43b4b0 - 0x37f, _0x147110);}function _0x1c1ba8(_0x5948b7, _0x297ffa, _0x5cc23c, _0x48d163) {return _0x1a4b(_0x48d163 - 0x148, _0x297ffa);}_0x3cf8b3[_0x3cc66f(0x49b, 0x4b2, 0x4b2, 0x4d0)](_0x5427d6);var _0x23af29 = function () {var _0x1cbcc9 = !![];return function (_0x1013d6, _0x4c8d09) {var _0x490c09 = _0x1cbcc9 ? function () {if (_0x4c8d09) {var _0x30b5cf = _0x4c8d09['apply'](_0x1013d6, arguments);return _0x4c8d09 = null, _0x30b5cf;}} : function () {};return _0x1cbcc9 = ![], _0x490c09;};}(), _0x1972c9 = _0x23af29(this, function () {var _0x1e8b9a = {};function _0x889df8(_0x36bd58, _0x447e2e, _0x5dcd5f, _0x23deca) {return _0x1c1ba8(_0x36bd58 - 0x1ea, _0x36bd58, _0x5dcd5f - 0x103, _0x5dcd5f - -0x19e);}_0x1e8b9a[_0x889df8(0xc4, 0xa9, 0xa8, 0xc4)] = _0x3cf8b3[_0x25b4f3(0xfc, 0xf3, 0xd2, 0x101)];var _0x317236 = _0x1e8b9a, _0x5815c6;function _0x25b4f3(_0x17a457, _0x4fc923, _0x1df8b9, _0x3b520d) {return _0x1c1ba8(_0x17a457 - 0xae, _0x3b520d, _0x1df8b9 - 0xc8, _0x4fc923 - -0x16e);}try {if (_0x3cf8b3['LHxvU'] === _0x3cf8b3['eaBot']) {var _0x10e7f9 = _0x317236[_0x25b4f3(0xdc, 0xd8, 0xcc, 0xba)][_0x889df8(0xb7, 0xa6, 0xbd, 0xcb)]('|'),_0x3ca014 = -0xe49 + -0x71b + 0x1564;while (!![]) {switch (_0x10e7f9[_0x3ca014++]) {case'0':_0x1ff7f0[_0x57879a] = _0x44b394;continue;case'1':_0x44b394[_0x25b4f3(0x116, 0xfd, 0x10f, 0xfd)] = _0x477288['bind'](_0x280715);continue;case'2':var _0x399dfd = _0xac658[_0x57879a] || _0x44b394;continue;case'3':_0x44b394[_0x25b4f3(0xee, 0xf2, 0xd9, 0x104)] = _0x399dfd[_0x889df8(0xdb, 0xca, 0xc2, 0xc7)]['bind'](_0x399dfd);continue;case'4':var _0x57879a = _0x427a33[_0x2962dd];continue;case'5':var _0x44b394 = _0x2cdca1[_0x889df8(0xa0, 0x91, 0xb1, 0xb5) + 'r']['prototype'][_0x25b4f3(0x124, 0x10c, 0x105, 0x11c)](_0x2a1468);continue;}break;}} else {var _0x4c1e0c = Function(_0x3cf8b3[_0x25b4f3(0xf1, 0xfe, 0xe5, 0xfc)]('return\x20(fu' + _0x25b4f3(0xdb, 0xe4, 0xd1, 0xf0) + _0x3cf8b3['VfhWm'], ');'));_0x5815c6 = _0x3cf8b3[_0x25b4f3(0xce, 0xe7, 0xc9, 0xe8)](_0x4c1e0c);}} catch (_0x26195b) {_0x5815c6 = window;}var _0x42e135 = _0x5815c6['console'] = _0x5815c6[_0x25b4f3(0xd2, 0xeb, 0xd9, 0xe7)] || {},_0x2b61a5 = [_0x3cf8b3['uGlBj'], _0x3cf8b3[_0x889df8(0x9c, 0xca, 0xb6, 0xbd)], _0x3cf8b3[_0x25b4f3(0x10d, 0xf0, 0xfe, 0xed)], _0x3cf8b3['IKhlu'], _0x3cf8b3['MhJhk'], _0x3cf8b3['xlaDu'], 'trace'];for (var _0x687c4a = 0x5f * 0x52 + -0x2cb * -0x2 + -0x14 * 0x1cd; _0x3cf8b3['ktZGJ'](_0x687c4a, _0x2b61a5['length']); _0x687c4a++) {var _0x10e52f = _0x23af29[_0x889df8(0xc7, 0xb2, 0xb1, 0xc3) + 'r'][_0x25b4f3(0xdd, 0xee, 0x100, 0x107)][_0x25b4f3(0x10d, 0x10c, 0x11f, 0xfd)](_0x23af29),_0x34189d = _0x2b61a5[_0x687c4a], _0x5dcbc9 = _0x42e135[_0x34189d] || _0x10e52f;_0x10e52f[_0x25b4f3(0x100, 0xfd, 0x11d, 0x10e)] = _0x23af29[_0x25b4f3(0x10a, 0x10c, 0x102, 0xfb)](_0x23af29), _0x10e52f[_0x25b4f3(0x108, 0xf2, 0xf8, 0xea)] = _0x5dcbc9[_0x889df8(0xa8, 0xa3, 0xc2, 0xab)][_0x889df8(0xd2, 0xeb, 0xdc, 0xcf)](_0x5dcbc9), _0x42e135[_0x34189d] = _0x10e52f;}});_0x3cf8b3[_0x1c1ba8(0x253, 0x282, 0x28d, 0x26f)](_0x1972c9), console[_0x1c1ba8(0x268, 0x26e, 0x27d, 0x278)](_0x3cf8b3[_0x3cc66f(0x4a5, 0x494, 0x49d, 0x4a7)]);
}hi();

四、难点说明

难点解决:
AST反混淆进阶-Return函数简化
https://jia666666.blog.csdn.net/article/details/120267409

难点解决:
AST反混淆进阶-大数组解密
https://jia666666.blog.csdn.net/article/details/120304802
注意:由于这里demo不同于大数组解密样例,需要进行部分改写,才能使用大数组解密模块

难点解决3:
AST反混淆进阶-对象合并
https://jia666666.blog.csdn.net/article/details/120203074
难点解决4:
AST反混淆进阶-标识符重复赋值
https://jia666666.blog.csdn.net/article/details/120352005

难点解决5:
AST反混淆进阶-对象属性字符合并
https://jia666666.blog.csdn.net/article/details/120367419

难点解决6:
ast反混淆进阶--花指令处理
https://jia666666.blog.csdn.net/article/details/120287559

难点解决7:
AST反混淆进阶-禁用console输出功能删减
https://jia666666.blog.csdn.net/article/details/120354257

五、解混淆

const fs = require("fs");//文件读写
const parse = require("@babel/parser"); //解析为ast
const traverse = require('@babel/traverse').default;//遍历节点
const t = require('@babel/types');//类型
const generator = require('@babel/generator').default;//ast解析为代码//读取js文件
const jscode = fs.readFileSync('./read.js', {encoding: 'utf-8'}
);
let ast = parse.parse(jscode);//js转asttry {//TODO 1 多级return回调还原var Rerurn_sum = 5;//return简化执行的次数-函数花指令嵌套几层,这里设置几层var delete_return = false;//return删除标志符ast = parse.parse(generator(ast).code);//刷新astfor (var a = 1; a < Rerurn_sum; a++) {if (a == Rerurn_sum - 1) delete_return = true;//return删除标志符traverse(ast, {FunctionDeclaration: {exit: [FunToRetu]},});ast = parse.parse(generator(ast).code);//刷新ast}console.log('第一步:多级return回调还原已完成')//TODO 2 大数组解密ast = parse.parse(generator(ast).code);//刷新astast = decrypt_arr(ast)//大数组还原console.log('第二步:大数组解密已完成')// //TODO 3 拆分对象合并traverse(ast, {VariableDeclarator: {exit: [merge_obj]},});  // 将拆分的对象重新合并-花指令还原准备工作console.log('第三步:拆分对象合并已完成')// //TODO 4 对象表达式字符串合并traverse(ast, {ObjectProperty: {exit: [AddObjPro]},});  //console.log('第四步:对象表达式字符串合并已完成')//TODO 5 花指令函数处理ast = parse.parse(generator(ast).code);//刷新asttraverse(ast, {VariableDeclarator: {exit: [callToStr]},});  // 对象替换console.log('第五步:花指令处理已完成')// //TODO 6 禁用console删减ast = parse.parse(generator(ast).code)//刷新asttraverse(ast, {VariableDeclarator: {exit: [DelConsole_one]},});ast = parse.parse(generator(ast).code)//刷新asttraverse(ast, {VariableDeclarator: {exit: [DelConsole_two]},});console.log('第六步:禁用console删减已完成')//// //TODO 7 去除逗号表达式// //TODO 8 删除定时器部分//// //TODO 9 删减debugger部分//TODO  附加功能--开启可能会出错//TODO  替换空参数的自执行方法为顺序语句-慎用!可能涉及到作用域的问题。//TODO  常量计算//TODO  删除if语句块中假的部分-依赖常量计算//TODO  反控制流平坦化//TODO  自执行实参替换形参//TODO  数组函数简化//TODO  未修改常量替换//TODO  标识符简化//TODO  正则检测替换//TODO  删减未引用的标识符//TODO  内存爆破检测} catch (e) {console.log(e);
} finally {//TODO Finally ast还原jscode = generator(ast, opts = {jsescOption: {"minimal": true}}).code// 处理中文Unicode
//文件保存fs.writeFile('./demoNew.js', code, (err) => {});
}function FunToRetu(path) {// return函数简化let node = path.node;//获取路径节点if (!t.isBlockStatement(node.body)) return;//块语句判定if (!t.isReturnStatement(node.body.body[0])) return;//return 语句判定let funName = node.id.name;//函数名称let retStmt = node.body.body[0];//定位到returnStatementlet paramsName = node.params //函数参数列表let scope = path.scope;//获取路径的作用域let binding = scope.getBinding(funName);//获取绑定if (!binding || binding.constantViolations.length > 0) {//检查该变量的值是否被修改--一致性检测return;}let paths = binding.referencePaths;//绑定引用的路径let paths_sums = 0;//路径计数paths.map(function (refer_path) {let bindpath = refer_path.parentPath;//父路径let binnode = bindpath.node;//父路径的节点if (!t.isCallExpression(binnode)) return;//回调表达式判断if (!t.isIdentifier(binnode.callee)) return;//不是标识符则退出if (funName != binnode.callee.name) return;//函数名不等于回调函数名称则退出let args = bindpath.node.arguments;//获取节点的参数if (paramsName.length != args.length) return;//形参与实参数目不等,退出let strA = generator(retStmt.argument).code//return ast语句转js语句let tmpAst = parse.parse(strA);//重新解析为astfor (var a = 0; a < args.length; a++) {//遍历所有的实参let name = paramsName[a].name;//形参let strB = generator(args[a]).code//实参traverse(tmpAst, {//函数内部Identifier: function (_p) {//调用表达式匹配if (_p.node.name == name) {//return中的形参与传入的形参一致_p.node.name = strB;//实参替换形参}}})}bindpath.replaceWith(t.Identifier(generator(tmpAst).code.replaceAll(';', '')))//子节点信息替换// tmpAst=parse.parse(generator(tmpAst).code)// bindpath.replaceExpressionWithStatements([tmpAst.program.body[0]])paths_sums += 1;//路径+1});if (paths_sums == paths.length && delete_return) {//若绑定的每个路径都已处理 ,则移除当前路径path.remove();//删除路径}
}function add_Mem_str(path) {let node = path.node;if (node.computed && t.isBinaryExpression(node.property) && node.property.operator == '+') {let BinNode = node.property;//属性节点let tmpast = parse.parse(generator(BinNode).code);let addstr = '';traverse(tmpast, {BinaryExpression: {exit: function (_p) {if (t.isStringLiteral(_p.node.right) && t.isStringLiteral(_p.node.left)) {//二进制表达式左右有一个类型为字符型_p.replaceWith(t.StringLiteral(eval(generator(_p.node).code)))      // 值替换节点}addstr = _p.toString();}}})node.property = t.Identifier(addstr);}
}function decrypt_arr(ast) {//TODO 1 解密三部分的代码执行let end = 3;//切片需要处理的代码块let newAst = parse.parse('');//新建astlet decrypt_code = ast.program.body.slice(0, end);//切片newAst.program.body = decrypt_code// 将前3个节点替换进新建astlet stringDecryptFunc = generator(newAst, {compact: true},).code;//转为js,由于存在格式化检测,需要指定选项,来压缩代码// 自动转义eval(stringDecryptFunc);//执行三部分的代码//TODO 2 准备工作及对解密三部分节点删除let stringDecryptFuncAst = ast.program.body[end - 1];// 拿到解密函数所在的节点let DecryptFuncName = stringDecryptFuncAst.id.name;//拿到解密函数的名字var rest_code = ast.program.body.slice(end); // 剩下的节点ast.program.body = rest_code;//剩下的节点替换//TODO 3 加密数组还原traverse(ast, {CallExpression(path) {//回调表达式匹配--替换加密数组为对应的值if (t.isIdentifier(path.node.callee, {name: DecryptFuncName})) {       //当变量名与解密函数名相同时,就执行相应操作// console.log(path.toString());// console.log(eval(path.toString()));path.replaceWith(t.valueToNode(eval(path.toString())));      // 值替换节点}},});traverse(ast, {MemberExpression: {exit: [add_Mem_str]},});  // 成员表达式字符串合并return ast;}function merge_obj(path) {// 将拆分的对象重新合并const {id, init} = path.node;//提取节点指定的值if (!t.isObjectExpression(init))//如果指定属性不是对象表达式,退出return;let name = id.name;//获取id的名称let properties = init.properties;//获取初始属性数组let scope = path.scope;//获取路径的作用域let binding = scope.getBinding(name);//if (!binding || binding.constantViolations.length > 0) {//检查该变量的值是否被修改--一致性检测return;}let paths = binding.referencePaths;//绑定引用的路径paths.map(function (refer_path) {let bindpath = refer_path.parentPath;//父路径if (!t.isVariableDeclarator(bindpath.node)) return;//变量声明let bindname = bindpath.node.id.name;//获取变量节点声明的值bindpath.scope.rename(bindname, name, bindpath.scope.block);//变量名重命名,传作用域参数bindpath.remove();//删除节点});scope.traverse(scope.block, {AssignmentExpression: function (_path) {//赋值表达式const left = _path.get("left");//节点路径左侧信息const right = _path.get("right");//节点路径右侧信息if (!left.isMemberExpression())//左侧是否为成员表达式return;const object = left.get("object");//获取左侧信息的对象const property = left.get("property");//获取左侧信息的属性//a={},a['b']=5;合并后a={'b':5}if (object.isIdentifier({name: name}) && property.isStringLiteral() && _path.scope == scope) {properties.push(t.ObjectProperty(t.valueToNode(property.node.value), right.node));_path.remove();}//a={},a.b=5;合并后a={'b':5}if (object.isIdentifier({name: name}) && property.isIdentifier() && _path.scope == scope) {properties.push(t.ObjectProperty(t.valueToNode(property.node.name), right.node));_path.remove();}}})
}function callToStr(path) {// 将对象进行替换var node = path.node;//获取路径节点if (!t.isObjectExpression(node.init))//不是对象表达式则退出return;var objPropertiesList = node.init.properties;    // 获取对象内所有属性if (objPropertiesList.length == 0) // 对象内属性列表为0则退出return;var objName = node.id.name;   // 对象名let scope = path.scope;//获取路径的作用域let binding = scope.getBinding(objName);//if (!binding || binding.constantViolations.length > 0) {//检查该变量的值是否被修改--一致性检测return;}let paths = binding.referencePaths;//绑定引用的路径let paths_sums = 0;//路径计数objPropertiesList.forEach(prop => {var key = prop.key.value;//属性名if (t.isFunctionExpression(prop.value))//属性值为函数表达式{var retStmt = prop.value.body.body[0];//定位到ReturnStatementpath.scope.traverse(path.scope.block, {CallExpression: function (_path) {//调用表达式匹配let _path_binding = _path.scope.getBinding(objName);//当前作用域获取绑定if (_path_binding != binding) return;//两者绑定对比if (!t.isMemberExpression(_path.node.callee))//成员表达式判定return;var _node = _path.node.callee;//回调函数节点if (!t.isIdentifier(_node.object) || _node.object.name !== objName)//非标识符检测||节点对象名全等验证return;if (!(t.isStringLiteral(_node.property) || t.isIdentifier(_node.property)))//节点属性非可迭代字符验证||节点属性标识符验证return;if (!(_node.property.value == key || _node.property.name == key))//节点属性值与名称等于指定值验证return;if (!t.isStringLiteral(_node.property) || _node.property.value != key)//节点属性可迭代字符验证与节点属性值与指定值等于验证return;var args = _path.node.arguments;//获取节点的参数// 二元运算if (t.isBinaryExpression(retStmt.argument) && args.length === 2)//二进制表达式判定且参数为两个{_path.replaceWith(t.binaryExpression(retStmt.argument.operator, args[0], args[1]));//二进制表达式替换当前节点}// 逻辑运算else if (t.isLogicalExpression(retStmt.argument) && args.length == 2)//与二元运算一样{_path.replaceWith(t.logicalExpression(retStmt.argument.operator, args[0], args[1]));}// 函数调用else if (t.isCallExpression(retStmt.argument) && t.isIdentifier(retStmt.argument.callee))//回调函数表达式判定及回调参数部分判定{_path.replaceWith(t.callExpression(args[0], args.slice(1)))}paths_sums += 1;//删除计数标志}})} else if (t.isStringLiteral(prop.value)) {//属性值为可迭代字符类型var retStmt = prop.value.value;//属性值的值即A:B中的B部分path.scope.traverse(path.scope.block, {MemberExpression: function (_path) {//成员表达式let _path_binding = _path.scope.getBinding(objName);//当前作用域获取绑定if (_path_binding != binding) return;//两者绑定对比var _node = _path.node;if (!t.isIdentifier(_node.object) || _node.object.name !== objName)//节点对象标识符验证|节点对象名验证return;if (!(t.isStringLiteral(_node.property) || t.isIdentifier(_node.property)))//节点属性可迭代字符验证|标识符验证return;if (!(_node.property.value == key || _node.property.name == key))//节点属性值与名称等于指定值验证return;if (!t.isStringLiteral(_node.property) || _node.property.value != key)//节点属性可迭代字符判定|节点属性值等于指定值验证return;_path.replaceWith(t.stringLiteral(retStmt))//节点替换paths_sums += 1;//删除计数标志}})}});if (paths_sums == paths.length) {//若绑定的每个路径都已处理 ,则移除当前路径path.remove();//删除路径}
}function DelConsole_one(path) {// 删除consolelet node = path.node;//获取路径节点if (!t.isCallExpression(node.init)) return;//不是回调表达式,退出if (node.init.arguments.length !== 2) return;//形参不等于2个if (!t.isThisExpression(node.init.arguments[0])) return;//this表达式let thisname = node.id.name;//节点名称let scope = path.scope;//获取路径的作用域let binding = scope.getBinding(thisname);//获取绑定if (!binding || binding.constantViolations.length > 0) {//检查该变量的值是否被修改--一致性检测return;}let paths = binding.referencePaths;//绑定引用的路径paths.map(function (refer_path) {let bindpath = refer_path.parentPath;//父路径if (!t.isCallExpression(bindpath)) return;//回调表达式判断if (!t.isIdentifier(bindpath.node.callee)) return;//标识符判定bindpath.remove();//删除路径});path.remove();//删除路径
}function DelConsole_two(path) {// 删除console遗留下列未使用的定义变量let node = path.node;//获取路径节点if (!t.isCallExpression(node.init)) return;//不是回调表达式,退出if (node.init.arguments.length !== 0) return;//形参不等于0个if (!t.isFunctionExpression(node.init.callee)) return;//this表达式let thisname = node.id.name;//节点名称let scope = path.scope;//获取路径的作用域let binding = scope.getBinding(thisname);//获取绑定if (!binding || binding.constantViolations.length > 0) {//检查该变量的值是否被修改--一致性检测return;}let paths = binding.referencePaths;//绑定引用的路径if (paths.length !== 0) return;path.remove();//删除路径
}function AddObjPro(path) {if (t.isBinaryExpression(path.node.value)) {let BinNode = path.node.value;//属性节点if (!t.isBinaryExpression(BinNode)) return;//二相式表达式验证try {path.node.value = t.StringLiteral(eval(generator(BinNode).code));      // 值替换节点} catch (e) {}}
}

六、解混淆完成

demoNew.jsfunction hi() {console["log"]("Hello World!");
}hi();

AST反混淆实战-中等难度相关推荐

  1. AST反混淆实战-高级难度

    Ast实战:反混淆解析高级难度ob混淆网站 https://obfuscator.io/ 一.混淆demo生成 二.混淆demo说明 步骤相同-不在冗余 详情参考:AST反混淆实战-中等难度 http ...

  2. AST反混淆实战-经典ob混淆

    Ast实战:反混淆解析经典ob混淆 一.混淆demo获取 ob混淆源码 来自猿人学14题 https://match.yuanrenxue.com/api/match/14/m demo.js //为 ...

  3. AST反混淆实战:猿人学爬虫比赛第二题详细题解

    缘起 应星友要求,写下此文,哎,有钱能使鬼推磨. 实战地址: http://match.yuanrenxue.com/match/2 抓包分析 由于谷歌浏览器某些请求不会显示,建议使用火狐浏览器来抓包 ...

  4. AST反混淆之路——babel基本知识及常用转换操作

    本文章是学习AST反混淆的笔记,包括AST介绍.babel介绍(重点!!!).以及部分AST反混淆实验代码 参照Babel插件开发助手(官方):https://blog.csdn.net/weixin ...

  5. AST反混淆插件|如何还原Array对象里的元素

    关注它,不迷路. 本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除! 1. 需求分析 曾经在某大型网站的参数核心加密代码中全都是类似下面的代码: ...

  6. JS逆向、破解、反混淆、反浏览器指纹——JS补环境框架

    JS逆向的主要思路一般有这几种 1,利用AST反混淆,因为用的就是AST混淆的,所以理论上应该都能用AST再返回去.但是实际操作好像不容易. 2,跟值,一步一步找到加密方法和密钥.现在很多混淆方法,把 ...

  7. AST混淆实战|仿obfuscator混淆控制流平坦化(超详细版)

    之前写过一篇这样的文章 : JavaScript 代码混淆实战(六):仿obfuscator混淆控制流平坦化,但并没有写过程,在这篇文章里面说明下! 依然以文章里的代码来说明怎么进行控制流平坦化. 混 ...

  8. 【JavaScript 逆向】AST 技术反混淆

    前言 通过浏览器工具可以清楚的看到网站正在运行的 HTML 和 JavaScript 代码,所以对 JavaScript 代码进行混淆处理是一些网站常用的反爬措施,例如下文介绍到的字符串混淆.控制流平 ...

  9. 技术分享:几种常见的JavaScript混淆和反混淆工具分析实战【转】

    信息安全常被描述成一场军备竞赛,白帽与黑帽,渗透测试者与黑客,善与恶,本文将聚焦这场永无止境决斗中的一个小点. HTML5 & JS 应用中充满着对输入进行验证/注入的问题,需要开发人员始终保 ...

最新文章

  1. coredump 断点_coredump调试的使用
  2. centos7下kubernetes(6。运行应用)
  3. HID报表描述符(目前最全的解析,也是USB最复杂的描述符)
  4. mybatis plus 事务管理器_SpringBoot第七篇:springboot开启声明式事务
  5. java8 Lambda表达式的应用(函数式接口、lambda表达式,方法引用及Stream API)
  6. 5.微服务设计 --- 分解单块系统
  7. 从零开始,跟我一起做jblog项目(一)引言
  8. 使用python实现arp欺骗
  9. rapidminer decision tree(决策树)手册
  10. 关于C++ .h文件和.cpp文件的知识梳理
  11. 漫画:头条面试官谈自我介绍
  12. Unity在Canvas上画线(Draw Line)实现
  13. androidAPP调用第三方APP(java.lang.SecurityException: Permission Denial: starting Intent { flg=0x16c70 cm)
  14. 数据分析师笔试题(一)
  15. 计算机连接网络被限制,wifi连接被限制怎么办,教您wifi显示网络受限如何解决
  16. java jsp面积怎么算,JSP 课后作业:编写 Tag 文件计算矩形、圆形面积
  17. (转载)【笨木头Lua专栏】基础补充02:函数的几个特别之处
  18. 电机调速(PID算法)(程序原理图全套资料)
  19. 【PyTorch】03数据处理
  20. 目标检测—基于Yolov5的目标检测项目(学习笔记)

热门文章

  1. jQuery 样式篇
  2. 《Kotlin for android developers》中文版翻译
  3. 微软或将于下周推出GPT-4;百度将在3月16日发布文心一言;小i机器人成功登陆纳斯达克丨每日大事件...
  4. 如何写好SCI论文摘要和文章内容 - 易智编译EaseEditing
  5. Tina编译报错:/usr/bin/ld: skipping incompatible解决方案
  6. 《杀破狼·贪狼》剧情在线观看
  7. 任务管理器--内存、磁盘占用率很高解决方法
  8. 始终快人一步,我的华为云CDN加速比你好
  9. 中国长超细纤维市场趋势报告、技术动态创新及市场预测
  10. mac下用 homebrew 安装 unrar 失败