AST实战|手把手教你还原ob混淆:ob混淆代码特征

ob混淆过的代码有那些特征?

特征一: 大数组 + 移位自执行函数 + 解密字符串函数

下面的代码是一个之前我在官网上混淆的一个例子:

AST实战|手把手教你还原ob混淆:ob混淆代码特征_第1张图片

可以看到,大数组为变量 _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相关知识。

你可能感兴趣的:(字符串,javascript,js,编程语言,python)