ob混淆过的代码有那些特征?
特征一: 大数组 + 移位自执行函数 + 解密字符串函数。
下面的代码是一个之前我在官网上混淆的一个例子:
可以看到,大数组为变量 _0x33fc,移位自执行函数体比较大,其实化简后有效的就这么点:
(function(_0x40b128, _0x10e158) {
var _0x1c0044 = function(_0x1cab6b) {
while (--_0x1cab6b) {
_0x40b128['push'](_0x40b128['shift']());
}
}
_0x21186e = function(_0x44fcdc, _0x2309cd) {
_0x44fcdc(++_0x2309cd);
}
;
_0x21186e(_0x1c0044, _0x10e158);
}(_0x33fc, -0xa25 + 0x1436 * -0x1 + 0x1f96));
具体的化简过程可以参考我的这篇文章: JS逆向时碰到了恶心的死代码怎么办?手把手教你解决!
而解密函数是 _0x14b7,因为后面有很多地方会调用这个函数。
特征二: 定义的Object,其key和value很有规律
var _0x22e4cc = {};
_0x22e4cc["_0x2e7dd3"] = function(_0x16ad58, _0x5d4167) {
return _0x16ad58 === _0x5d4167;
};
_0x22e4cc['_0x1b1554'] = "string";
_0x22e4cc["_0x2ab7a2"] = function(_0x120b76, _0x5482f3) {
return _0x120b76 !== _0x5482f3;
};
_0x22e4cc["_0x16d15a"] = function(_0x35fd52, _0xb88db7) {
return _0x35fd52 + _0xb88db7;
};
_0x22e4cc["_0x267303"] = function(_0x516608, _0x46e9cb) {
return _0x516608 / _0x46e9cb;
};
_0x22e4cc["_0x179f12"] = 'length';
_0x22e4cc["_0x4f8e92"] = function(_0xafceb, _0x3c43b9) {
return _0xafceb % _0x3c43b9;
}
;
_0x22e4cc["_0x3fba04"] = function(_0x3c0262, _0x3c50b7) {
return _0x3c0262 + _0x3c50b7;
}
;
_0x22e4cc["_0x158e00"] = "debu";
_0x22e4cc["_0x1203cd"] = "action";
_0x22e4cc["_0x50462a"] = "gger";
_0x22e4cc["_0x3e6826"] = "stateObject";
_0x22e4cc["_0x3fcd8d"] = function(_0x2c50a6, _0x24e706) {
return _0x2c50a6(_0x24e706);
};
上面代码所示的Object变量为 _0x22e4cc,其key值长度是一样的,而它对应的value要么是字符串,要么是函数,其返回结构也是非常简单。
特征三: while + switch 组合
var _0x5ee804 = '4|5|3|0|2|1'['split']('|')
, _0x572cee = 0;
while (!![]) {
switch (_0x5ee804[_0x572cee++]) {
case '0':
_0xdedd5["__proto__"] = _0x2f44f0['bind'](_0x2f44f0);
continue;
case '1':
_0x39a3d5[_0x359747] = _0xdedd5;
continue;
case '2':
_0xdedd5['toString'] = _0x1941e5["toString"]["bind"](_0x1941e5);
continue;
case '3':
var _0x1941e5 = _0x39a3d5[_0x359747] || _0xdedd5;
continue;
case '4':
var _0xdedd5 = _0x2f44f0["constructor"]['prototype']["bind"](_0x2f44f0);
continue;
case '5':
var _0x359747 = _0x195f0c[_0x301b17];
continue;
}
break;
}
看到这个特征,相信大部分人都看到过,一个很简单的控制流平坦化,而且,ob混淆的控制流平坦化基本都是这样,还没见过不一样的。哪天要是在case语句中修改case值,就不好弄咯。
特征四: 一些干扰调试的垃圾代码
如:
setInterval(function () {
_0x5dcd51();
}, 4000);
function _0x5dcd51(_0x712948) {
function _0x441fc1(_0x2aae3c) {
if (typeof _0x2aae3c === "string") return function (_0x1430b6) {}["constructor"]("while (true) {}")["apply"]('counter');else ('' + _0x2aae3c / _0x2aae3c)["length"] !== 1 || _0x2aae3c % 20 === 0 ? function () {
return true;
}['constructor']("debugger")["call"]("action") : function () {
return false;
}["constructor"]("debugger")['apply']("stateObject");
_0x441fc1(++_0x2aae3c);
}
try {
if (_0x712948) return _0x441fc1;else _0x441fc1(0);
} catch (_0x219393) {}
}
也有类似这样的:
var _0x4bea14 = _0x46c669(this, function() {
function _0x139538() {
var _0x1664a7;
try {
_0x1664a7 = Function("return (function() {}.constructor(\"return this\")( ));")();
} catch (_0x1d7d81) {
_0x1664a7 = window;
}
return _0x1664a7;
}
var _0x1f8e02 = _0x139538();
var _0x4fd052 = _0x1f8e02["console"] = _0x1f8e02["console"] || {};
var _0x1d2e26 = ["log", "warn", "info", "error", "exception", "table", "trace"];
for (var _0x3f35ef = 0; _0x3f35ef < _0x1d2e26["length"]; _0x3f35ef++) {
var _0x4cca25 = _0x46c669["constructor"]["prototype"]["bind"](_0x46c669);
var _0x11486c = _0x1d2e26[_0x3f35ef];
var _0x29f6cb = _0x4fd052[_0x11486c] || _0x4cca25;
_0x4cca25["__proto__"] = _0x46c669["bind"](_0x46c669);
_0x4cca25["toString"] = _0x29f6cb["toString"]["bind"](_0x29f6cb);
_0x4fd052[_0x11486c] = _0x4cca25;
}
});
_0x4bea14();
这些代码是干扰或者阻扰你进行调试的,对加密参数来说,没有什么用,我一般都是直接删除。
ob混淆的代码特征基本上就是这些,而最新版的ob混淆,也只是第一个略有修改,大数组变成了一个函数,其他的基本没变。
欢迎关注本人微信公众号,学习更多AST相关知识。