JavaScript obfuscator 讓你的代碼看起來(lái)讓人痛苦(最新整理)
在開(kāi)發(fā) JavaScript 應(yīng)用程序時(shí),保護(hù)源代碼免受未經(jīng)授權(quán)的訪(fǎng)問(wèn)和修改是一個(gè)重要的考慮因素。這就是 JavaScript Obfuscator 發(fā)揮作用的地方。本文將深入探討 JavaScript Obfuscator 的原理和使用方法,幫助開(kāi)發(fā)者有效地保護(hù)他們的代碼。
什么是 JavaScript Obfuscator?
JavaScript Obfuscator 是一個(gè)強(qiáng)大的工具,它通過(guò)轉(zhuǎn)換和混淆代碼來(lái)幫助開(kāi)發(fā)者保護(hù)他們的 JavaScript 源代碼。這種轉(zhuǎn)換不會(huì)改變程序的執(zhí)行方式,但會(huì)使代碼難以理解和修改,從而為源代碼提供了一層保護(hù)。
它是如何工作?
JavaScript Obfuscator 通過(guò)以下幾種方式工作來(lái)混淆代碼:
- 變量名和函數(shù)名替換:將原始的變量名和函數(shù)名替換為難以理解的字符序列。
- 字符串混淆:將字符串轉(zhuǎn)換為不易讀的格式,例如使用 ASCII 碼表示。
- 控制流平坦化:改變代碼的控制流程,使邏輯難以跟蹤。
- 插入死代碼:在代碼中插入不會(huì)執(zhí)行的代碼段,增加分析和理解的難度。
執(zhí)行過(guò)程
解析:首先,JavaScript Obfuscator讀取原始的JavaScript代碼,然后使用解析器將代碼轉(zhuǎn)換成抽象語(yǔ)法樹(shù)(AST)。AST是一種樹(shù)狀結(jié)構(gòu),用于表示程序的語(yǔ)法結(jié)構(gòu),每個(gè)節(jié)點(diǎn)代表代碼中的一個(gè)構(gòu)造(如變量聲明、函數(shù)調(diào)用等)。
變量重命名:在AST的基礎(chǔ)上,工具會(huì)對(duì)變量和函數(shù)名進(jìn)行重命名。它會(huì)用短序列或無(wú)意義的名稱(chēng)來(lái)替換原有的名稱(chēng),從而使得代碼難以閱讀和理解。
字符串加密:JavaScript Obfuscator會(huì)識(shí)別代碼中的字符串,并將它們加密或轉(zhuǎn)換成一種不易直接理解的形式。在運(yùn)行時(shí),這些字符串會(huì)被解密或轉(zhuǎn)換回原始內(nèi)容,但在源代碼中它們看起來(lái)是混亂的。
控制流扁平化:該工具會(huì)改變代碼的執(zhí)行流程,例如,將直線(xiàn)執(zhí)行的代碼轉(zhuǎn)換成使用條件語(yǔ)句和跳轉(zhuǎn)的形式,這使得靜態(tài)分析變得更加困難。
死代碼注入:為了進(jìn)一步迷惑分析者,JavaScript Obfuscator可以在代碼中注入無(wú)用的、不會(huì)被執(zhí)行的代碼段。這些代碼看起來(lái)可能和正常代碼無(wú)異,但實(shí)際上是為了增加分析的難度。
代碼轉(zhuǎn)換:除了上述操作外,JavaScript Obfuscator還會(huì)應(yīng)用多種代碼轉(zhuǎn)換技術(shù),如將數(shù)組訪(fǎng)問(wèn)轉(zhuǎn)換為復(fù)雜的函數(shù)調(diào)用,或者使用其他方式改變代碼的結(jié)構(gòu),而不改變其功能。
生成:最后,工具會(huì)根據(jù)處理后的AST生成新的JavaScript代碼。這段代碼在功能上與原始代碼相同,但在形式上大為不同,難以被人直接理解。
通過(guò)這些步驟,JavaScript Obfuscator 能夠有效地保護(hù) JavaScript 代碼,防止未經(jīng)授權(quán)的復(fù)制、修改和逆向工程。需要注意的是,雖然代碼混淆可以大大增加代碼被理解和修改的難度,但它并不能完全防止這些行為?;煜谴a保護(hù)策略中的一環(huán),應(yīng)與其他安全措施(如代碼簽名、許可證檢查等)結(jié)合使用,以提高整體的安全性。
快速開(kāi)始
在Node. js中使用
首先,你需要通過(guò) npm 安裝 JavaScript Obfuscator:
npm install --save-dev javascript-obfuscator
然后,你可以在你的 Node.js 項(xiàng)目中如下使用它:
var JavaScriptObfuscator = require('javascript-obfuscator');
var obfuscationResult = JavaScriptObfuscator.obfuscate(
`(function(){
var variable1 = '5' - 3;
var variable2 = '5' + 3;
// 更多代碼...
})();`,
{
compact: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
// 更多配置選項(xiàng)...
}
);
console.log(obfuscationResult.getObfuscatedCode());在瀏覽器中使用
你也可以直接在瀏覽器中使用 JavaScript Obfuscator,通過(guò) CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/javascript-obfuscator/dist/index.browser.js"></script>
然后,你可以在瀏覽器端腳本中使用它來(lái)混淆代碼:
var obfuscationResult = JavaScriptObfuscator.obfuscate(
// 你的JavaScript代碼...
);
console.log(obfuscationResult.getObfuscatedCode());常用配置項(xiàng)
JavaScript Obfuscator 提供了豐富的配置選項(xiàng),讓開(kāi)發(fā)者可以根據(jù)自己的需求進(jìn)行定制化的代碼混淆。下面是一些常見(jiàn)的配置項(xiàng):
- compact:類(lèi)型為
boolean,默認(rèn)值為true。當(dāng)設(shè)置為true時(shí),生成的代碼會(huì)被壓縮成一行,有助于減少代碼體積。 - controlFlowFlattening:類(lèi)型為
boolean,默認(rèn)值為false。啟用控制流平坦化可以使代碼邏輯更加復(fù)雜,但可能會(huì)影響運(yùn)行性能。 - controlFlowFlatteningThreshold:類(lèi)型為
number,默認(rèn)值為0.75。這個(gè)閾值決定了哪些部分的代碼會(huì)被控制流平坦化處理,范圍從0到1。 - deadCodeInjection:類(lèi)型為
boolean,默認(rèn)值為false。啟用后,會(huì)在代碼中插入不會(huì)被執(zhí)行的死代碼,增加反向工程的難度。 - deadCodeInjectionThreshold:類(lèi)型為
number,默認(rèn)值為0.4。這個(gè)閾值決定了有多少比例的代碼會(huì)被插入死代碼。 - debugProtection:類(lèi)型為
boolean,默認(rèn)值為false。啟用后,會(huì)使得瀏覽器的開(kāi)發(fā)者工具變得不穩(wěn)定,防止代碼被調(diào)試。 - stringArray:類(lèi)型為
boolean,默認(rèn)值為true。啟用后,會(huì)將字符串放入一個(gè)特殊的數(shù)組中,通過(guò)索引訪(fǎng)問(wèn),以增加代碼的混淆程度。 - stringArrayEncoding:類(lèi)型為
string或boolean,可以是none、base64或rc4,用于設(shè)置字符串?dāng)?shù)組的編碼方式。
預(yù)設(shè)配置模板
默認(rèn)預(yù)設(shè),高性能
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: false,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: false,
simplify: true,
splitStrings: false,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayCallsTransformThreshold: 0.5,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75,
unicodeEscapeSequence: false
}高混淆,低性能
性能將比沒(méi)有混淆時(shí)慢得多,并且代碼體積也比較大
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true,
unicodeEscapeSequence: false
}
中等混淆,最佳性能
性能將比沒(méi)有混淆時(shí)慢
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.75,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.4,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 10,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.75,
stringArrayEncoding: ['base64'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 2,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 4,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.75,
transformObjectKeys: true,
unicodeEscapeSequence: false
}
低混淆,高性能
性能將處于相對(duì)正常的水平
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: false,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75,
unicodeEscapeSequence: false
}
在打包工具中使用 JavaScript Obfuscator
Webpack
如果你使用的是 Webpack,可以通過(guò) webpack-obfuscator 插件來(lái)集成 JavaScript Obfuscator。首先,安裝這個(gè)插件:
npm install --save-dev webpack-obfuscator
插件使用:
在的 webpack.config.js 文件中配置這個(gè)插件:
const JavaScriptObfuscator = require('webpack-obfuscator');
module.exports = {
// 其他配置...
plugins: [
new JavaScriptObfuscator({
rotateUnicodeArray: true
// 其他混淆選項(xiàng)...
}, ['excluded_bundle_name.js'])
]
};加載器使用:
在 webpack 配置中定義一個(gè)規(guī)則,并使用混淆器-loader 作為模塊的最后一個(gè)加載器。你可以添加 enforce: ‘post’ 標(biāo)志,以確保在正常加載器之后調(diào)用加載器:
var WebpackObfuscator = require('webpack-obfuscator');
// webpack loader rules array
rules: [
{
test: /\.js$/,
exclude: [
path.resolve(__dirname, 'excluded_file_name.js')
],
enforce: 'post',
use: {
loader: WebpackObfuscator.loader,
options: {
rotateStringArray: true
}
}
}
]Rollup
對(duì)于使用 Rollup 的項(xiàng)目,可以通過(guò) rollup-plugin-javascript-obfuscator 插件來(lái)集成。首先,安裝這個(gè)插件:
npm install --save-dev rollup-plugin-javascript-obfuscator
然后,在 rollup.config.js 中配置這個(gè)插件:
import javascriptObfuscator from 'rollup-plugin-javascript-obfuscator';
export default {
// 其他配置...
plugins: [
javascriptObfuscator({
compact: true,
controlFlowFlattening: true
// 其他混淆選項(xiàng)...
})
]
};Gulp
如果你的項(xiàng)目使用 Gulp,可以通過(guò) gulp-javascript-obfuscator 插件來(lái)集成。首先,安裝這個(gè)插件:
npm install --save-dev gulp-javascript-obfuscator
然后,配置你的 gulpfile.js 使用這個(gè)插件:
const gulp = require('gulp');
const javascriptObfuscator = require('gulp-javascript-obfuscator');
gulp.task('obfuscate', function () {
return gulp.src('src/*.js')
.pipe(javascriptObfuscator({
compact: true,
controlFlowFlattening: true
// 其他混淆選項(xiàng)...
}))
.pipe(gulp.dest('dist'));
});Why use ?
普通的代碼壓縮工具(如 UglifyJS、Terser 等)主要目的是減少代碼體積,提高加載速度,它們通過(guò)移除空白字符、注釋、重命名變量(通常是縮短變量名)等方式來(lái)實(shí)現(xiàn)。雖然這些操作可以使代碼難以閱讀,但主要是從性能優(yōu)化的角度出發(fā),并不專(zhuān)注于增加代碼的安全性或防止代碼被逆向工程分析。
而JavaScript Obfuscator 提供的功能遠(yuǎn)超普通的代碼壓縮工具,它專(zhuān)門(mén)設(shè)計(jì)來(lái)保護(hù) JavaScript 代碼,防止被盜用或逆向工程。以下是它與普通代碼壓縮工具的主要區(qū)別:
變量重命名:JavaScript Obfuscator 不僅重命名變量,還可以使用更復(fù)雜的名稱(chēng)或生成無(wú)意義的名稱(chēng),使得代碼邏輯難以理解。
字符串提取和加密:將代碼中的字符串提取出來(lái),并進(jìn)行加密,只有在運(yùn)行時(shí)才解密,增加了逆向工程的難度。
死代碼注入:在代碼中注入不會(huì)執(zhí)行的代碼段,這些代碼段看起來(lái)像是正常的代碼,但實(shí)際上是為了迷惑逆向工程師。
控制流平坦化:改變代碼的執(zhí)行流程,使得代碼的邏輯結(jié)構(gòu)變得復(fù)雜,難以通過(guò)靜態(tài)分析來(lái)理解程序的行為。
多種代碼轉(zhuǎn)換:應(yīng)用多種代碼轉(zhuǎn)換技術(shù),如將數(shù)組訪(fǎng)問(wèn)轉(zhuǎn)換為復(fù)雜的函數(shù)調(diào)用,進(jìn)一步增加代碼的復(fù)雜性。
這些特性使得 JavaScript Obfuscator 不僅能壓縮代碼,還能大幅度提高代碼的保護(hù)級(jí)別,使得即使是有經(jīng)驗(yàn)的開(kāi)發(fā)者或黑客也難以理解和修改被混淆的代碼。因此,當(dāng)需要保護(hù) JavaScript 代碼不被輕易理解和修改時(shí),僅僅使用普通的代碼壓縮工具是不夠的,需要使用專(zhuān)門(mén)的代碼混淆工具如 JavaScript Obfuscator。
JavaScript中Obfuscator命令行使用超詳細(xì)教程
參考
- JavaScript Obfuscator Tool
- javascript-obfuscator/javascript-obfuscator: A powerful obfuscator for JavaScript and Node.js
- javascript-obfuscator/webpack-obfuscator: javascript-obfuscator plugin for Webpack
到此這篇關(guān)于JavaScript obfuscator 讓你的代碼看起來(lái)讓人痛苦的文章就介紹到這了,更多相關(guān)js obfuscator使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
判斷滾動(dòng)條滑到底部觸發(fā)事件(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇判斷滾動(dòng)條滑到底部觸發(fā)事件的實(shí)例講解。具有很好的參考價(jià)值。一起跟隨小編過(guò)來(lái)看看吧,希望對(duì)大家有所幫助2017-11-11
javascript prototype的深度探索不是原型繼承那么簡(jiǎn)單
JavaScript中對(duì)象的prototype屬性,可以返回對(duì)象類(lèi)型原型的引用。這是一個(gè)相當(dāng)拗口的解釋?zhuān)斫馑?,先要正確理解對(duì)象類(lèi)型(Type)以及原型(prototype)的概念。2008-06-06
javascript四舍五入函數(shù)代碼分享(保留后幾位)
這篇文章主要介紹了javascript四舍五入函數(shù)分享,大家參考使用吧2013-12-12
js實(shí)現(xiàn)購(gòu)物車(chē)計(jì)算的方法
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)購(gòu)物車(chē)的計(jì)算方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
在 JavaScript 中保留小數(shù)點(diǎn)后兩位的方法
在 JavaScript 中,有多種方法可以保留小數(shù)點(diǎn)后兩位,本文給大家分享比較常用的方法,文末給大家介紹了實(shí)現(xiàn)數(shù)據(jù)格式化保留兩位小數(shù)的多種方法,感興趣的朋友一起看看吧2023-10-10
ES6知識(shí)點(diǎn)整理之模塊化的應(yīng)用詳解
這篇文章主要介紹了ES6知識(shí)點(diǎn)整理之模塊化的應(yīng)用,結(jié)合實(shí)例形式分析了基于node.js環(huán)境下模擬ES6模塊化配置與使用相關(guān)操作技巧,需要的朋友可以參考下2019-04-04

