对混淆和反混淆逻辑模糊的同学有福了,本帖用最小示例带您手动反混淆JS代码。
所使用混淆平台为:https://www.jshaman.com/#introduction
原始代码:
function get_copyright(){
var domain = "jshaman.com";
var from_year = 2017;
var copyright = "(c)" + from_year + "-" + (new Date).getFullYear() + "," + domain;
return copyright;
}
console.log(get_copyright());
配置:
混淆后:
(function(_0x508f77, _0x3b2241) {
function _0x21eb9c(_0x5b8863, _0x39b9e0, _0x4703d1, _0x453f0d, _0x51dc6e) {
return _0x19df(_0x4703d1 - -0xf9, _0x39b9e0);
}
function _0x18c136(_0xc6797f, _0x23008c, _0x25cbac, _0x54cfbf, _0x324d61) {
return _0x19df(_0x324d61 - 0x295, _0x25cbac);
}
function _0x17681a(_0x13a39b, _0x4046a8, _0x2a7d00, _0xbf2e0e, _0x43aa6c) {
return _0x19df(_0x2a7d00 - -0x39d, _0x4046a8);
}
function _0xadfed3(_0x5a5c36, _0x57cd4c, _0x44f723, _0x6ab621, _0x145065) {
return _0x19df(_0x5a5c36 - -0x27c, _0x57cd4c);
}
function _0x476c38(_0xc946d0, _0x2036c0, _0x173ee9, _0x1c4658, _0x30228a) {
return _0x19df(_0x2036c0 - -0xa, _0xc946d0);
}
var _0x2366ec = _0x508f77();
while (!![]) {
try {
var _0x5da386 = -parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) / 0x1 * (-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) / 0x2) + -parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276)) / 0x3 * (-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6)) / 0x4) + parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b)) / 0x5 * (parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f)) / 0x6) + parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b)) / 0x7 * (-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f)) / 0x8) + parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8)) / 0x9 * (-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393)) / 0xa) + -parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3)) / 0xb + -parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa)) / 0xc * (-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271)) / 0xd);
console.log("====",_0x5da386)
if (_0x5da386 === _0x3b2241) {
break;
} else {
_0x2366ec["\u0070\u0075\u0073\u0068"](_0x2366ec["\u0073\u0068\u0069\u0066\u0074"]());
}
} catch (_0x120a63) {
_0x2366ec["\u0070\u0075\u0073\u0068"](_0x2366ec["\u0073\u0068\u0069\u0066\u0074"]());
}
}
})(_0x3c9d, 0x88e36);
function _0x3c9d() {
var _0x33510f = ["BTOYMO21".split("").reverse().join(""), "DmfQga424793".split("").reverse().join(""), "raeYlluFteg".split("").reverse().join(""), "iPcMLb65217191".split("").reverse().join(""), "TQAlJe5505212".split("").reverse().join(""), "\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061", "MMFQnC4220922".split("").reverse().join(""), "gol".split("").reverse().join(""), "moc.namahsj".split("").reverse().join(""), "OxzDOt02674".split("").reverse().join(""), "\u0033\u0057\u006a\u0073\u006e\u0063\u0061", "ZKRjdl22801801".split("").reverse().join(""), "\u0031\u004f\u0074\u0071\u0067\u0059\u0043", '6FOXfjJ', '(c)', "\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059", '28fPQEME'];
_0x3c9d = function() {
return _0x33510f;
};
return _0x3c9d();
}
function get_copyright() {
var _0x22144a = 0x9 + 0x9; //
var _0x1dc57f = _0x8b116c(0x342, 0x338, 0x33f, 0x33e, 0x33e);
_0x22144a = 0x7;
var _0x4d307c = 0xd23be ^ 0xd245f;
var _0x43bc8e = 0x6 + 0x0;
var _0x4abe00 = _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) + _0x4d307c + '-' + new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() + "\u002c" + _0x1dc57f;
function _0x4f9ad4(_0x2728c9, _0x511937, _0x40fe1b, _0x3d5085, _0x1545e4) {
return _0x19df(_0x2728c9 - -0x328, _0x1545e4);
}
_0x43bc8e = 0x4 + 0x6;
function _0x8b116c(_0x130462, _0x3025c3, _0x4c564e, _0x5b4fdb, _0x5c1daa) {
return _0x19df(_0x4c564e - 0x335, _0x5b4fdb);
}
return _0x4abe00;
}
function _0x19df(_0x332160, _0x3c9d18) {
var _0x19df6f = _0x3c9d();
_0x19df = function(_0x47744e, _0x3b5735) {
_0x47744e = _0x47744e - 0x0;
var _0x1042d7 = _0x19df6f[_0x47744e];
return _0x1042d7;
};
return _0x19df(_0x332160, _0x3c9d18);
}
console["\u006c\u006f\u0067"](get_copyright());
手工反混淆挑战:
//第一步:解析 _0x3c9d 方法
//step1.1: "BTOYMO21".split("").reverse().join("")结果为 12OMYOTB
//step1.2: "DmfQga424793".split("").reverse().join("")结果为 397424agQfmD
//step1.3: "raeYlluFteg".split("").reverse().join("") 结果为getFullYear
//step1.4: 19171256bLMcPi
//step1.5: 2125055eJlAQT
//step1.6: 1800Rtaqca
//step1.7: 2290224CnQFMM
//step1.8: log
//step1.9: jshaman.com
//step1.10: 47620tODzxO
//step1.11: 3Wjsnca
//step1.12: 10810822ldjRKZ
//step1.13: 1OtqgYC
//step1.14: 6FOXfjJ
//step1.15: (c)
//step1.16: 444658RDWjgY
//step1.17: 28fPQEME
function _0x3c9d() {
var _0x33510f = ["BTOYMO21".split("").reverse().join(""),
"DmfQga424793".split("").reverse().join(""),
"raeYlluFteg".split("").reverse().join(""),
"iPcMLb65217191".split("").reverse().join(""),
"TQAlJe5505212".split("").reverse().join(""),
"\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061",
"MMFQnC4220922".split("").reverse().join(""),
"gol".split("").reverse().join(""),
"moc.namahsj".split("").reverse().join(""),
"OxzDOt02674".split("").reverse().join(""),
"\u0033\u0057\u006a\u0073\u006e\u0063\u0061",
"ZKRjdl22801801".split("").reverse().join(""),
"\u0031\u004f\u0074\u0071\u0067\u0059\u0043",
'6FOXfjJ',
'(c)',
"\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059",
'28fPQEME'];
_0x3c9d = function() {
return _0x33510f;
};
return _0x3c9d();
}
// 第二步:解析_0x19df 方法(***猜测就是传递一个数组序号,获取对应字符串***)
//step2.1: _0x3b5735 这个变量就属于僵尸代码,仅仅声明,未使用
//step2.2: _0x332160 是有意义的值
function _0x19df(_0x332160, _0x3c9d18) {
var _0x19df6f = _0x3c9d();
_0x19df = function(_0x47744e, _0x3b5735) {
_0x47744e = _0x47744e - 0x0;
var _0x1042d7 = _0x19df6f[_0x47744e];
return _0x1042d7;
};
return _0x19df(_0x332160, _0x3c9d18);
}
// 第三步:去除僵尸代码误导
//step3.1: _0x8b116c 这个方法入参是5个,但根据_0x19df可知,有用的只有第三个值。
//step3.2: _0x1dc57f => 0x33f-0x335 => 十进制的数字10, => '3Wjsnca'
//step3.3: _0x4d307c => 0xd23be ^ 0xd245f => 2017
//step3.4: _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) => -0x318 - (-0x328) => 16 => '28fPQEME'
//step3.5: 这样最终输出,明显不对,但有一定规律,'3Wjsnca'向前移2是想要的'jshaman.com';'28fPQEME'向前移2是想要的'(c)',开启第四步的探索。
function get_copyright() {
//清理 var _0x22144a = 0x9 + 0x9; //
var _0x1dc57f = _0x8b116c(0x342, 0x338, 0x33f, 0x33e, 0x33e);
//清理 _0x22144a = 0x7;
var _0x4d307c = 0xd23be ^ 0xd245f;
//清理 var _0x43bc8e = 0x6 + 0x0;
var _0x4abe00 = _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) + _0x4d307c + '-' + new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() + "\u002c" + _0x1dc57f;
function _0x4f9ad4(_0x2728c9, _0x511937, _0x40fe1b, _0x3d5085, _0x1545e4) {
return _0x19df(_0x2728c9 - -0x328, _0x1545e4);
}
//清理 _0x43bc8e = 0x4 + 0x6;
function _0x8b116c(_0x130462, _0x3025c3, _0x4c564e, _0x5b4fdb, _0x5c1daa) {
return _0x19df(_0x4c564e - 0x335, _0x5b4fdb);
}
return _0x4abe00;
}
//第四步:这个匿名函数的探索
//step4.1: 0x88e36 => 十进制的560694
//step4.2: -parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) => -parseInt(_0x19df(-0x38f - (-0x39d))) => -parseInt(_0x19df(-2)) => NAN
//step4.3: -parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) => -parseInt(_0x19df(-0x27c - (-0x27c))) => -parseInt(_0x19df(0)) => -parseInt('12OMYOTB') => -12,第三位是字母o,而非数字0.
/step4.4: 计算太过于麻烦,用程序代替,结果在下方。
(function(_0x508f77, _0x3b2241) {
function _0x21eb9c(_0x5b8863, _0x39b9e0, _0x4703d1, _0x453f0d, _0x51dc6e) {
return _0x19df(_0x4703d1 - -0xf9, _0x39b9e0);
}
function _0x18c136(_0xc6797f, _0x23008c, _0x25cbac, _0x54cfbf, _0x324d61) {
return _0x19df(_0x324d61 - 0x295, _0x25cbac);
}
function _0x17681a(_0x13a39b, _0x4046a8, _0x2a7d00, _0xbf2e0e, _0x43aa6c) {
return _0x19df(_0x2a7d00 - -0x39d, _0x4046a8);
}
function _0xadfed3(_0x5a5c36, _0x57cd4c, _0x44f723, _0x6ab621, _0x145065) {
return _0x19df(_0x5a5c36 - -0x27c, _0x57cd4c);
}
function _0x476c38(_0xc946d0, _0x2036c0, _0x173ee9, _0x1c4658, _0x30228a) {
return _0x19df(_0x2036c0 - -0xa, _0xc946d0);
}
var _0x2366ec = _0x508f77();
while (!![]) {
try {
var _0x5da386 =
-parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)) / 0x1
* (-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)) / 0x2)
+ -parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276)) / 0x3
* (-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6)) / 0x4)
+ parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b)) / 0x5
* (parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f)) / 0x6)
+ parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b)) / 0x7
* (-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f)) / 0x8)
+ parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8)) / 0x9
* (-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393)) / 0xa)
+ -parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3)) / 0xb
+ -parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa)) / 0xc
* (-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271)) / 0xd);
console.log(-parseInt(_0x17681a(-0x397, -0x38b, -0x38f, -0x396, -0x390)));
console.log(-parseInt(_0xadfed3(-0x27c, -0x281, -0x280, -0x283, -0x281)));
console.log(-parseInt(_0xadfed3(-0x270, -0x271, -0x26f, -0x267, -0x276)));
console.log((-parseInt(_0x21eb9c(-0xeb, -0xec, -0xf1, -0xf6, -0xf6))));
console.log(parseInt(_0x18c136(0x29e, 0x2a1, 0x2a4, 0x2a1, 0x29b)));
console.log(parseInt(_0x17681a(-0x392, -0x38b, -0x38e, -0x392, -0x38f)));
console.log(parseInt(_0xadfed3(-0x27b, -0x282, -0x27d, -0x275, -0x27b)));
console.log(-parseInt(_0xadfed3(-0x279, -0x27e, -0x281, -0x27a, -0x27f)));
console.log(parseInt(_0x21eb9c(-0xf5, -0xe9, -0xf2, -0xed, -0xf8)));
console.log(-parseInt(_0x17681a(-0x399, -0x39b, -0x392, -0x391, -0x393)));
console.log(-parseInt(_0x476c38(-0x2, 0x3, 0x0, -0x3, -0x3)));
console.log(-parseInt(_0x21eb9c(-0xfc, -0xfe, -0xf7, -0xfb, -0xfa)));
console.log(-parseInt(_0xadfed3(-0x277, -0x27f, -0x27f, -0x277, -0x271)));
console.log(_0x5da386);
console.log(_0x3b2241);
console.log(_0x5da386 === _0x3b2241);
if (_0x5da386 === _0x3b2241) {
break;
} else {
_0x2366ec["push"](_0x2366ec["shift"]());
}
} catch (_0x120a63) {
_0x2366ec["push"](_0x2366ec["shift"]());
}
}
})(_0x3c9d, 0x88e36);
以下是console.log()的输出:
VM59:72 false
VM59:56 NaN
VM59:57 -10810822
VM59:58 -2290224
VM59:59 NaN
VM59:60 12
VM59:61 47620
VM59:62 1
VM59:63 NaN
VM59:64 397424
VM59:65 -1800
VM59:66 NaN
VM59:67 -6
VM59:68 -28
VM59:70 NaN
VM59:71 560694
VM59:72 false
VM59:56 -47620
VM59:57 -1
VM59:58 NaN
VM59:59 -19171256
VM59:60 397424
VM59:61 3
VM59:62 6
VM59:63 -444658
VM59:64 NaN
VM59:65 -2290224
VM59:66 NaN
VM59:67 NaN
VM59:68 -12
VM59:70 NaN
VM59:71 560694
VM59:72 false
VM59:56 -3
VM59:57 -6
VM59:58 NaN
VM59:59 -2125055
VM59:60 NaN
VM59:61 10810822
VM59:62 NaN
VM59:63 -28
VM59:64 19171256
VM59:65 NaN
VM59:66 -47620
VM59:67 -444658
VM59:68 -397424
VM59:70 NaN
VM59:71 560694
VM59:72 false
VM59:56 -10810822
VM59:57 NaN
VM59:58 -47620
VM59:59 -1800
VM59:60 19171256
VM59:61 1
VM59:62 444658
VM59:63 -12
VM59:64 2125055
VM59:65 NaN
VM59:66 -3
VM59:67 -28
VM59:68 NaN
VM59:70 NaN
VM59:71 560694
VM59:72 false
VM59:56 -1
VM59:57 -444658
VM59:58 -3
VM59:59 -2290224
VM59:60 2125055
VM59:61 6
VM59:62 28
VM59:63 -397424
VM59:64 1800
VM59:65 -47620
VM59:66 -10810822
VM59:67 -12
VM59:68 -19171256
VM59:70 560694
VM59:71 560694
VM59:72 true
由日志可见,滚动了16遍
当前的的数组顺序应该为:
//0: 28fPQEME
//1: "BTOYMO21".split("").reverse().join("")结果为 12OMYOTB
//2: "DmfQga424793".split("").reverse().join("")结果为 397424agQfmD
//3: "raeYlluFteg".split("").reverse().join("") 结果为getFullYear
//4: 19171256bLMcPi
//5: 2125055eJlAQT
//6: 1800Rtaqca
//7: 2290224CnQFMM
//8: log
//9: jshaman.com
//10: 47620tODzxO
//11: 3Wjsnca
//12: 10810822ldjRKZ
//13: 1OtqgYC
//14: 6FOXfjJ
//15: (c)
//16: 444658RDWjgY
function _0x3c9d() {
var _0x33510f = [
'28fPQEME'
"BTOYMO21".split("").reverse().join(""),
"DmfQga424793".split("").reverse().join(""),
"raeYlluFteg".split("").reverse().join(""),
"iPcMLb65217191".split("").reverse().join(""),
"TQAlJe5505212".split("").reverse().join(""),
"\u0031\u0038\u0030\u0030\u0052\u0074\u0061\u0071\u0063\u0061",
"MMFQnC4220922".split("").reverse().join(""),
"gol".split("").reverse().join(""),
"moc.namahsj".split("").reverse().join(""),
"OxzDOt02674".split("").reverse().join(""),
"\u0033\u0057\u006a\u0073\u006e\u0063\u0061",
"ZKRjdl22801801".split("").reverse().join(""),
"\u0031\u004f\u0074\u0071\u0067\u0059\u0043",
'6FOXfjJ',
'(c)',
"\u0034\u0034\u0034\u0036\u0035\u0038\u0052\u0044\u0057\u006a\u0067\u0059",
];
_0x3c9d = function() {
return _0x33510f;
};
return _0x3c9d();
}
//此时我们回看第三步:
//step3.1: _0x8b116c 这个方法入参是5个,但根据_0x19df可知,有用的只有第三个值。
//step3.2: _0x1dc57f => 0x33f-0x335 => 十进制的数字10, => 这里是 'jshaman.com' 而不是 '3Wjsnca'
//step3.3: _0x4d307c => 0xd23be ^ 0xd245f => 2017
//step3.4: _0x4f9ad4(-0x318, -0x316, -0x317, -0x320, -0x317) => -0x318 - (-0x328) => 16 => 这里是'(c)'而不是'28fPQEME'
//step3.5: 这样最终输出,明显不对,但有一定规律,'3Wjsnca'向前移2是想要的'jshaman.com';'28fPQEME'向前移2是想要的'(c)',开启第四步的探索。
//new Date()["\u0067\u0065\u0074\u0046\u0075\u006c\u006c\u0059\u0065\u0061\u0072"]() => new Date()["getFullYear"]()
// 那最终结果就是:
function get_copyright() {
var _0x4abe00 = '(c)' + 2017 + '-' + 2024 + "," + 'jshaman.com';
return _0x4abe00;
}
这是console.log最终输出。
以上,我们简单了解了一下,JS反混淆的处理方式。
JS混淆代码,绝对是可以反混淆的,JS混淆很大程度是增加copy成本。并不绝对安全。