溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Javascript混淆與解混淆指的是什么

發(fā)布時(shí)間:2020-12-02 11:08:57 來源:億速云 閱讀:147 作者:小新 欄目:web開發(fā)

這篇文章給大家分享的是有關(guān)Javascript混淆與解混淆指的是什么的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。

像軟件加密與解密一樣,javascript的混淆與解混淆同屬于同一個(gè)范疇。道高一尺,魔高一丈。沒有永恒的黑,也沒有永恒的白。一切都是資本市場驅(qū)動(dòng)行為,現(xiàn)在都流行你能為人解決什么問題,這個(gè)概念。那么市場究竟能容納多少個(gè)能解決這種問題的利益者。JS沒有秘密。

其實(shí)本人不贊成javascript進(jìn)行hash混淆處理,一拖慢運(yùn)行時(shí)速度,二體積大。JS代碼前端可獲取,天生賦予“開源”屬性,都可以在chrome devTools下查看。JS非壓縮性混淆完全違法前端優(yōu)化準(zhǔn)則。

目前網(wǎng)絡(luò)上可以搜索的JS混淆工具不外乎以下幾種:

eval混淆,也是最早JS出現(xiàn)的混淆加密,據(jù)說第一天就被破解,修改一下代碼,alert一下就可以破解了。這種方法從出生的那天就失去了意義。其實(shí)JS加密(混淆)是相對(duì)于可讀性而言的,其實(shí)真正有意義的就是壓縮型混淆uglify這一類,即可減少體重,也可減少可讀性。

但是,也不能排除部分商業(yè)源代碼使用hash類型混淆源代碼,比如 miniui 使用的JSA加密, fundebug使用的javascript-obfuscator。

下面通過代碼來說明 JSA加密 和 javascript-obfuscator 的區(qū)別:

要混淆的代碼:

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")

可以發(fā)現(xiàn),其實(shí)沒有做什么什么修改,只是做了一些變量替換。想還原也比較簡單的。這里就不拿它來做代表,也沒有什么人用。

通過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'));

這個(gè)復(fù)雜得多,但是分析一下你會(huì)發(fā)現(xiàn),其實(shí)多了一個(gè)字典,所有方法變量,都有可能存在字典中,調(diào)用時(shí)先調(diào)用字典還原方法名變量再執(zhí)行。
其實(shí)入口都是變量的規(guī)則。

字典函數(shù):

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;
};

通過以上發(fā)現(xiàn),我們可以把JS混淆歸結(jié)為三類,分別是 eval類型,hash類型,壓縮類型。而壓縮類型,是目前前端性能優(yōu)化的常用工具,以u(píng)glify為代表。

常用的前端壓縮優(yōu)化工具:

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。

相應(yīng)的解混淆工具:

  • eval對(duì)應(yīng)的解混淆工具, 隨便百度都可以搜索到,如jspacker
  • JSA對(duì)應(yīng)的解混淆工具unjsa
  • javascript-obfuscator對(duì)應(yīng)的解混淆工具crack.js
  • 壓縮類型uglify對(duì)應(yīng)的工具UnuglifyJS,在線版jsnice

解混淆策略其實(shí)是依據(jù)生成代碼規(guī)律編寫,不外乎觀察特征分析,再觀察特征分析,不斷調(diào)整。都是手辦眼見功夫。

都沒有什么難度可言,有的就是耐性。比如javascript-obfuscator對(duì)應(yīng)的解混淆工具可以
分解為N因子問題:

如何查詢function的作用域?
預(yù)執(zhí)行變量替換可能存在類型?
...

如:

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');

第一步你總得知道字典函數(shù),然后執(zhí)行字典函數(shù) _0x5b26('0x0') 還原成 log.

那么就好辦了,寫代碼的事。
如 https://github.com/jscck/crac...

還原后,如何重構(gòu)代碼,那么你還得知道代碼生成之前是通過什么工具打包的webpack? 還是?

如webpack 的各種封裝頭和尾
https://webpack.js.org/config...

(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_;
});

假如再深入一點(diǎn),可能會(huì)涉及到JS語法解釋器, AST抽象語法樹

目前涉及到 JS語法解釋器, AST抽象語法樹的功能如下:

prepack, esprima, babel

或者可以閱讀《編程語言實(shí)現(xiàn)模式》,涉及到 antlr4。

當(dāng)然也可以通過esprima等工具來做解混淆,只是工作量大一點(diǎn),值不值的問題。

對(duì)于未來,JS商業(yè)源碼加密的方向可能webassembly,先在服務(wù)端編譯成wasm,源碼就能真正的閉源。

有人的地方就有路,有混淆的地方就有解混淆,目前機(jī)器學(xué)習(xí)編程響應(yīng)的解混淆工具也做的相當(dāng)出色,比如

<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 產(chǎn)品
nice2predict,jsnice ...
查看 https://www.sri.inf.ethz.ch/r...

拓展參考

AST抽象語法樹

為什么額外說一下AST抽象語法樹,因?yàn)槟憧梢?input-> ast -> output Anything。

比如你jsx轉(zhuǎn)換小程序模版語法,這樣你就可以用react語法來寫小程序,如Taro。
mpvue, wepy, postcss …… 這些都是通過AST進(jìn)行構(gòu)建轉(zhuǎn)換的工具,es6 -> es5, babel 都是使用AST。

AST抽象語法樹大致流程:

Input 生成 AST tree

然后通過AST類型斷言進(jìn)行相應(yīng)的轉(zhuǎn)換

感謝各位的閱讀!關(guān)于Javascript混淆與解混淆指的是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI