Javascript混淆与解混淆的详细介绍(附代码)

互联网 19-4-2
本篇文章给大家带来的内容是关于Javascript混淆与解混淆的详细介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

像软件加密与解密一样,javascript的混淆与解混淆同属于同一个范畴。道高一尺,魔高一丈。没有永恒的黑,也没有永恒的白。一切都是资本市场驱动行为,现在都流行你能为人解决什么问题,这个概念。那么市场究竟能容纳多少个能解决这种问题的利益者。JS没有秘密。

其实本人不赞成javascript进行hash混淆处理,一拖慢运行时速度,二体积大。JS代码前端可获取,天生赋予“开源”属性,都可以在chrome devTools下查看。JS非压缩性混淆完全违法前端优化准则。

目前网络上可以搜索的JS混淆工具不外乎以下几种:

eval混淆,也是最早JS出现的混淆加密,据说第一天就被破解,修改一下代码,alert一下就可以破解了。这种方法从出生的那天就失去了意义。其实JS加密(混淆)是相对于可读性而言的,其实真正有意义的就是压缩型混淆uglify这一类,即可减少体重,也可减少可读性。

但是,也不能排除部分商业源代码使用hash类型混淆源代码,比如 miniui 使用的JSA加密, fundebug使用的javascript-obfuscator。

下面通过代码来说明 JSA加密 和 javascript-obfuscator 的区别:

要混淆的代码:

function logG(message) {   console.log('\x1b[32m%s\x1b[0m', message);  } function logR(message) {   console.log('\x1b[41m%s\x1b[0m', message);  } logG('logR'); logR('logG');

通过JSA加密混淆后生成的代码

function o00($){console.log("\x1b[32m%s\x1b[0m",$)}function o01($){console.log("\x1b[41m%s\x1b[0m",$)}o00("logR");o01("logG")

然后再beautifier一下:

function o00($) {   console.log("\x1b[32m%s\x1b[0m", $) }  function o01($) {   console.log("\x1b[41m%s\x1b[0m", $) } o00("logR"); o01("logG")

可以发现,其实没有做什么什么修改,只是做了一些变量替换。想还原也比较简单的。这里就不拿它来做代表,也没有什么人用。

通过javascript-obfuscator混淆后生成的代码

var _0xd6ac=['[41m%s[0m','logG','log'];(function(_0x203a66,_0x6dd4f4){var _0x3c5c81=function(_0x4f427c){while(--_0x4f427c){_0x203a66['push'](_0x203a66['shift']());}};_0x3c5c81(++_0x6dd4f4);}(_0xd6ac,0x6e));var _0x5b26=function(_0x2d8f05,_0x4b81bb){_0x2d8f05=_0x2d8f05-0x0;var _0x4d74cb=_0xd6ac[_0x2d8f05];return _0x4d74cb;};function logG(_0x4f1daa){console[_0x5b26('0x0')]('[32m%s[0m',_0x4f1daa);}function logR(_0x38b325){console[_0x5b26('0x0')](_0x5b26('0x1'),_0x38b325);}logG('logR');logR(_0x5b26('0x2'));

再beautifier一下:

var _0xd6ac = ['[41m%s[0m', 'logG', 'log']; (function(_0x203a66, _0x6dd4f4) {   var _0x3c5c81 = function(_0x4f427c) {     while (--_0x4f427c) {       _0x203a66['push'](_0x203a66['shift']());     }   };   _0x3c5c81(++_0x6dd4f4); }(_0xd6ac, 0x6e)); var _0x5b26 = function(_0x2d8f05, _0x4b81bb) {   _0x2d8f05 = _0x2d8f05 - 0x0;   var _0x4d74cb = _0xd6ac[_0x2d8f05];   return _0x4d74cb; };  function logG(_0x4f1daa) {   console[_0x5b26('0x0')]('[32m%s[0m', _0x4f1daa); }  function logR(_0x38b325) {   console[_0x5b26('0x0')](_0x5b26('0x1'), _0x38b325); } logG('logR'); logR(_0x5b26('0x2'));

字典函数:

var _0xd6ac = ['[41m%s[0m', 'logG', 'log']; (function(_0x203a66, _0x6dd4f4) {   var _0x3c5c81 = function(_0x4f427c) {     while (--_0x4f427c) {       _0x203a66['push'](_0x203a66['shift']());     }   };   _0x3c5c81(++_0x6dd4f4); }(_0xd6ac, 0x6e)); var _0x5b26 = function(_0x2d8f05, _0x4b81bb) {   _0x2d8f05 = _0x2d8f05 - 0x0;   var _0x4d74cb = _0xd6ac[_0x2d8f05];   return _0x4d74cb; };

通过以上发现,我们可以把JS混淆归结为三类,分别是 eval类型,hash类型,压缩类型。而压缩类型,是目前前端性能优化的常用工具,以uglify为代表。

常用的前端压缩优化工具:

JavaScript:

  • babel-minify
  • terser
  • uglify-js
  • uglify-es
  • Google Closure Compiler
  • YUI Compressor

CSS:

  • PostCSS
  • clean-css
  • CSSO
  • YUI Compressor

HTML:

  • html-minifier

从工具流(workflow) 来看,不论是 webpack 还是 gulp ,目前javascript最流行工具还是uglify。

相应的解混淆工具:

  • eval对应的解混淆工具, 随便百度都可以搜索到,如jspacker
  • JSA对应的解混淆工具unjsa
  • javascript-obfuscator对应的解混淆工具crack.js
  • 压缩类型uglify对应的工具UnuglifyJS,在线版jsnice

解混淆策略其实是依据生成代码规律编写,不外乎观察特征分析,再观察特征分析,不断调整。都是手办眼见功夫。

如何查询function的作用域?预执行变量替换可能存在类型?...

如:

var _0xd6ac = ['[41m%s[0m', 'logG', 'log']; (function(_0x203a66, _0x6dd4f4) {   var _0x3c5c81 = function(_0x4f427c) {     while (--_0x4f427c) {       _0x203a66['push'](_0x203a66['shift']());     }   };   _0x3c5c81(++_0x6dd4f4); }(_0xd6ac, 0x6e)); var _0x5b26 = function(_0x2d8f05, _0x4b81bb) {   _0x2d8f05 = _0x2d8f05 - 0x0;   var _0x4d74cb = _0xd6ac[_0x2d8f05];   return _0x4d74cb; };  function logG(_0x4f1daa) {   console[_0x5b26('0x0')]('[32m%s[0m', _0x4f1daa); }  function logR(_0x38b325) {   console[_0x5b26('0x0')](_0x5b26('0x1'), _0x38b325); } logG('logR'); logR(_0x5b26('0x2'));

要还原成

function logG(message) {   console.log('\x1b[32m%s\x1b[0m', message);  } function logR(message) {   console.log('\x1b[41m%s\x1b[0m', message);  } logG('logR'); logR('logG');

第一步你总得知道字典函数,然后执行字典函数 _0x5b26('0x0') 还原成 log.

还原后,如何重构代码,那么你还得知道代码生成之前是通过什么工具打包的webpack? 还是?

(function webpackUniversalModuleDefinition(root, factory) {   if(typeof exports === 'object' && typeof module === 'object')     module.exports = factory();   else if(typeof define === 'function' && define.amd)     define([], factory);   else if(typeof exports === 'object')     exports['MyLibrary'] = factory();   else     root['MyLibrary'] = factory(); })(typeof self !== 'undefined' ? self : this, function() {   return _entry_return_; });

假如再深入一点,可能会涉及到JS语法解释器, AST抽象语法树

目前涉及到 JS语法解释器, AST抽象语法树的功能如下:

prepack, esprima, babel

或者可以阅读《编程语言实现模式》,涉及到 antlr4。

当然也可以通过esprima等工具来做解混淆,只是工作量大一点,值不值的问题。

对于未来,JS商业源码加密的方向可能webassembly,先在服务端编译成wasm,源码就能真正的闭源。

有人的地方就有路,有混淆的地方就有解混淆,目前机器学习编程响应的解混淆工具也做的相当出色,比如

<img src="https://www.sri.inf.ethz.ch/assets/images/sri-logo.svg" alt="Secure, Reliable, and Intelligent Systems Lab" width="136" >

Machine Learning for Programming 产品nice2predict,jsnice ...查看 https://www.sri.inf.ethz.ch/r...

拓展参考

AST抽象语法树

为什么额外说一下AST抽象语法树,因为你可以 input-> ast -> output Anything。

AST抽象语法树大致流程:

Input 生成 AST tree

然后通过AST类型断言进行相应的转换

【相关推荐:JavaScript视频教程】

以上就是Javascript混淆与解混淆的详细介绍(附代码)的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: JavaScript
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:Node.js中package.json中库的版本号的介绍

相关资讯