欢迎光临
我们一直在努力

尝试给一个高级加密的 js 解密

部分代码如下:

解出的文件运行后就会出现内存溢出. 代码如下:

var _0x54115f = {
    'SUOVq': function _0x5ea3b8(_0x3382f6, _0x2982dd) {
        return _0x3382f6 === _0x2982dd;
    },
    'ThiLx': _0x44a2('0x3f3', 'u#2Z'),
    'JJmbY': function _0x509711(_0x4ce407, _0x64d8b4) {
        return _0x4ce407(_0x64d8b4);
    },
    'EfhJL': _0x44a2('0x3f4', '%vSB'),
    'fnWOy': function _0x55b85d(_0x2704be, _0x3ccb99, _0x499ae4, _0x1b2e59) {
        return _0x2704be(_0x3ccb99, _0x499ae4, _0x1b2e59);
    },
    'KFhMR': _0x44a2('0x3f5', 'Ip]C'),
    'OpNyR': _0x44a2('0x3f6', 'Y[bh'),
    'CZXOX': function _0x527c90(_0x28d53b, _0x54b9e5) {
        return _0x28d53b(_0x54b9e5);
    },
    'vHDgf': _0x44a2('0x3f7', 'YNY)'),
    'IQhEP': _0x44a2('0x3f8', 'fD[R'),
    'BDPPX': function _0xbbd8c2(_0x440dca, _0x169920) {
        return _0x440dca + _0x169920;
    },
    'zTpvi': _0x44a2('0x3f9', 'GZJs')
};

加密的js文件中存在大量调用_0x44a2()函数. 而这个函数根据2个参数, 计算出一个字符串. 比如

_0x44a2('0x3f9', 'GZJs') // 输出 'end'

现在先将js文件中的_0x44a2()替换成计算出来的字符串.
1、查找所有 _0x44a2()函数.
2、运行 _0x44a2() 得出字符串.
3、将_0x44a2()替换得出的字符串.

解密 代码如下:

// main.js
const fs = require('fs');
// 复制 _0x44a2() 函数, 用于下面 eval()
var _0x44a2 = function(_0x23744e, _0xd9f80a) {
    // code
}
// 读取 encrypt.js
fs.readFile('encrypt.js', function (err, data) {
  if (err) {
      return console.error(err);
  }
  // 根据正则找到所有 _0x44a2 函数. 执行后替换成字符串.
  var decode = data.toString().replace(/_0x44a2\('.+?', '.+?'\)/g, function(e){
    return '`' + eval(e) + '`';
  })
  // 替换后写入 decode.js 中
  fs.writeFile('decode.js', decode, function(err) {
    if (err) {
      return console.error(err);
    }
  });
});

运行node main.js. 这样就得出一个解密文件decode.js. 如下:

var _0x54115f = {
    'SUOVq': function _0x5ea3b8(_0x3382f6, _0x2982dd) {
        return _0x3382f6 === _0x2982dd;
    },
    'ThiLx': `sbw`, // => _0x44a2('0x3f3', 'u#2Z')
    'JJmbY': function _0x509711(_0x4ce407, _0x64d8b4) {
        return _0x4ce407(_0x64d8b4);
    },
    'EfhJL': `.vjs-big-play-button`, // => _0x44a2('0x3f4', '%vSB')
    'fnWOy': function _0x55b85d(_0x2704be, _0x3ccb99, _0x499ae4, _0x1b2e59) {
        return _0x2704be(_0x3ccb99, _0x499ae4, _0x1b2e59);
    },
    'KFhMR': `display`, // => _0x44a2('0x3f5', 'Ip]C')
    'OpNyR': `none`, // => _0x44a2('0x3f6', 'Y[bh')
    'CZXOX': function _0x527c90(_0x28d53b, _0x54b9e5) {
        return _0x28d53b(_0x54b9e5);
    },
    'vHDgf': `#wrapper > div:nth-child(1) > div`, // => _0x44a2('0x3f7', 'YNY)')
    'IQhEP': `removedMessage`, // => _0x44a2('0x3f8', 'fD[R')
    'BDPPX': function _0xbbd8c2(_0x440dca, _0x169920) {
        return _0x440dca + _0x169920;
    },
    'zTpvi': `end` // => _0x44a2('0x3f9', 'GZJs')
};

解出的文件运行后就会出现内存溢出. 代码如下:

var _0x1c72aa = _0x44a2['data'][_0x23744e];
if (_0x1c72aa === undefined) {
    if (_0x44a2['once'] === undefined) {
        var _0x46b851 = function(_0x264cc0) {
            this['rc4Bytes'] = _0x264cc0;
            this['states'] = [0x1, 0x0, 0x0];
            this['newState'] = function() {
                return 'newState';
            };
            this['firstState'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';
            this['secondState'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';
        };
        _0x46b851['prototype']['checkState'] = function() {
            var _0xcfc30b = new RegExp(this['firstState'] + this['secondState']);
            return this['runState'](_0xcfc30b['test'](this['newState']['toString']()) ? --this['states'][0x1] : --this['states'][0x0]);
        };
        _0x46b851['prototype']['runState'] = function(_0x20249b) {
            if (!Boolean(~_0x20249b)) {
                return _0x20249b;
            }
            return this['getState'](this['rc4Bytes']);
        };
        _0x46b851['prototype']['getState'] = function(_0xc053a0) {
            for (var i = 0; i < this.states.length; i++) {
                this.states.push(Math.round(Math['random']()));
            }
            return _0xc053a0(this.states[0]);
        };
        new _0x46b851(_0x44a2)['checkState']();
        _0x44a2['once'] = !![];
    }
    _0xc8a519 = _0x44a2['rc4'](_0xc8a519, _0xd9f80a);
    _0x44a2['data'][_0x23744e] = _0xc8a519;
} else {
    _0xc8a519 = _0x1c72aa;
}
return _0xc8a519;

请看23-28行代码, 为了方便阅读将代码重写, 如下:

_0x46b851['prototype']['getState'] = function(_0xc053a0) {
    for (var i = 0; i < this.states.length; i++) {
        this.states.push(Math.round(Math['random']()));
    }
    return _0xc053a0(this.states[0]);
}

可以看出这是一个死循环. 向回看可以看出是如何运行到这个死循环的.

 checkState() => runState() => getState() 

现在来看checkState()函数第13行, 为了方便阅读将代码重写, 如下:

_0x46b851.prototype.checkState = function() {
    var _0xcfc30b = new RegExp(`\\w+ *\\(\\) *{\\w+ * ['|"].+['|"];? *}`);
    return this.runState(
      _0xcfc30b.test( this.newState.toString() ) ? --this.states[0x1] : --this.states[0x0]
    );
};

可以看出这是正则表达式, 它在测试什么呢? 回到第7行看看this.newState.toString()输出的是什么.

this.newState.toString()
// 输出
"function () {
    return 'newState';
}"
// 正则匹配的是
"function () {return 'newState';}"

为了方便阅读, 所以将代码进行了格式化, 就导致了正则不匹配. 不得不说这个加密有点阴险.
转自:http://www.76sano.cn/index.php/archives/4/

赞(0)
版权归原作者所有,如有侵权请告知。达维营-前端网 » 尝试给一个高级加密的 js 解密

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址