vue專案配置 `webpack-obfuscator` 進行程式碼加密混淆

Dragonir發表於2021-02-25

背景

公司程式碼提供給第三方使用,為了不完全洩露原始碼,需要對給出的程式碼進行加密混淆,前端程式碼雖然無法做到完全加密混淆,但是通過使用 webpack-obfuscator 通過增加隨機廢程式碼段、字元編碼轉義等方法可以使構建程式碼完全混淆,達到無法恢復原始碼甚至無法閱讀的目的。

安裝

webpack-obfuscator https://www.npmjs.com/package/webpack-obfuscator

npm install --save-dev webpack-obfuscator

配置

// webpack.config.js
const JavaScriptObfuscator = require('webpack-obfuscator');
module.exports = {
  entry: {
    'abc': './test/input/index.js',
    'cde': './test/input/index1.js'
  },
  output: {
    path: 'dist',
    filename: '[name].js'
  },
  plugins: [
    new JavaScriptObfuscator({
      rotateUnicodeArray: true
      // 陣列內是需要排除的檔案
    }, ['abc.js'])
  ]
};

vue cli 專案配置:

// vue.config.js
const path = require('path');
var JavaScriptObfuscator = require('webpack-obfuscator');
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
  productionSourceMap: false,
  configureWebpack: {
    plugins: [
      new JavaScriptObfuscator({
        rotateStringArray: true,
      }, [])
    ]
  },
  pwa: {},
  pages: {}
}

vue cli 2.x 配置在 webpack.prod.conf.js

構建

npm run build

構建檔案對比

1. 原始檔案

// test.js
function abc() {
    for (let i = 0; i < 10; i++) {
        console.log(`第${i}個,你好,hello`)
    }
}
abc()

2. webpack 預設工具uglifyjs-webpack-plugin

webpackJsonp([2],{lVK7:function(o,l){!function(){for(var o=0;o<10;o++)console.log("第"+o+"個,你好,hello")}()}},["lVK7"]);

3. webpack-obfuscator 無引數時

new JavaScriptObfuscator({
}, [])
var _0x1f6e=["個,你好,hello","lVK7","log"];!function(n,o){!function(o){for(;--o;)n.push(n.shift())}(++o)}(_0x1f6e,323);var _0x3655=function(n,o){return _0x1f6e[n-=0]};webpackJsonp([2],{lVK7:function(n,o){!function(){for(var n=0;n<10;n++)console[_0x3655("0x0")]("第"+n+_0x3655("0x1"))}()}},[_0x3655("0x2")]);

4. webpack-obfuscator 高度混淆

低效能:效能比沒有模糊處理慢 50-100%

new JavaScriptObfuscator({
  // 壓縮程式碼
  compact: true,
  // 是否啟用控制流扁平化(降低1.5倍的執行速度)
  controlFlowFlattening: true,
  // 應用概率;在較大的程式碼庫中,建議降低此值,因為大量的控制流轉換可能會增加程式碼的大小並降低程式碼的速度。
  controlFlowFlatteningThreshold: 1,
  // 隨機的死程式碼塊(增加了混淆程式碼的大小)
  deadCodeInjection: true,
  // 死程式碼塊的影響概率
  deadCodeInjectionThreshold: 1,
  // 此選項幾乎不可能使用開發者工具的控制檯選項卡
  debugProtection: true,
  // 如果選中,則會在“控制檯”選項卡上使用間隔強制除錯模式,從而更難使用“開發人員工具”的其他功能。
  debugProtectionInterval: true,
  // 通過用空函式替換它們來禁用console.log,console.info,console.error和console.warn。這使得偵錯程式的使用更加困難。
  disableConsoleOutput: true,
  // 識別符號的混淆方式 hexadecimal(十六進位制) mangled(短識別符號)
  identifierNamesGenerator: 'hexadecimal',
  log: false,
  // 是否啟用全域性變數和函式名稱的混淆
  renameGlobals: false,
  // 通過固定和隨機(在程式碼混淆時生成)的位置移動陣列。這使得將刪除的字串的順序與其原始位置相匹配變得更加困難。如果原始原始碼不小,建議使用此選項,因為輔助函式可以引起注意。
  rotateStringArray: true,
  // 混淆後的程式碼,不能使用程式碼美化,同時需要配置 cpmpat:true;
  selfDefending: true,
  // 刪除字串文字並將它們放在一個特殊的陣列中
  stringArray: true,
  stringArrayEncoding: 'rc4',
  stringArrayThreshold: 1,
  // 允許啟用/禁用字串轉換為unicode轉義序列。Unicode轉義序列大大增加了程式碼大小,並且可以輕鬆地將字串恢復為原始檢視。建議僅對小型原始碼啟用此選項。
  transformObjectKeys: true,
  unicodeEscapeSequence: false
}, []),

構建後檔案大小: 29,999 位元組(29.2 KB)

var _0xa0d1=["w7Bzw6oKw6E=","wrwIUcOVw4M=","w4bChi3DtcOQ","wpLDtsK5w4LDpA==","OUlQwp1z","woEqw4XCtsOe","YR3DrkDCiA==","woAjwq/Ci8KQ","dDNzw5bDgA==",
// ...
("0x201","xatR")]=function(x){return x()},x[_0x34e6("0x202","vdcx")](_0x2c01f8)},4e3);

3. webpack-obfuscator 中等混淆

最佳效能:效能比沒有模糊處理慢 30-35%

new JavaScriptObfuscator({
  // 壓縮程式碼
  compact: true,
  // 是否啟用控制流扁平化(降低1.5倍的執行速度)
  controlFlowFlattening: true,
  // 應用概率;在較大的程式碼庫中,建議降低此值,因為大量的控制流轉換可能會增加程式碼的大小並降低程式碼的速度。
  controlFlowFlatteningThreshold: 0.75,
  // 隨機的死程式碼塊(增加了混淆程式碼的大小)
  deadCodeInjection: true,
  // 死程式碼塊的影響概率
  deadCodeInjectionThreshold: 0.4,
  // 此選項幾乎不可能使用開發者工具的控制檯選項卡
  debugProtection: false,
  // 如果選中,則會在“控制檯”選項卡上使用間隔強制除錯模式,從而更難使用“開發人員工具”的其他功能。
  debugProtectionInterval: false,
  // 通過用空函式替換它們來禁用console.log,console.info,console.error和console.warn。這使得偵錯程式的使用更加困難。
  disableConsoleOutput: true,
  // 識別符號的混淆方式 hexadecimal(十六進位制) mangled(短識別符號)
  identifierNamesGenerator: 'hexadecimal',
  log: false,
  // 是否啟用全域性變數和函式名稱的混淆
  renameGlobals: false,
  // 通過固定和隨機(在程式碼混淆時生成)的位置移動陣列。這使得將刪除的字串的順序與其原始位置相匹配變得更加困難。如果原始原始碼不小,建議使用此選項,因為輔助函式可以引起注意。
  rotateStringArray: true,
  // 混淆後的程式碼,不能使用程式碼美化,同時需要配置 cpmpat:true;
  selfDefending: true,
  // 刪除字串文字並將它們放在一個特殊的陣列中
  stringArray: true,
  stringArrayEncoding: 'base64',
  stringArrayThreshold: 0.75,
  transformObjectKeys: true,
  // 允許啟用/禁用字串轉換為unicode轉義序列。Unicode轉義序列大大增加了程式碼大小,並且可以輕鬆地將字串恢復為原始檢視。建議僅對小型原始碼啟用此選項。
  unicodeEscapeSequence: false
}, []),

構建後檔案大小:7066位元組(6.90kb)

var _0x1a25=["UmFzT1U=","RkVIc0o=","VUt2eW4=","Q29IS0g=","V1NSZ0k=","d3RNT2w=","dlV6cUw=","RlpzZWg=","QnpzSlE=","cXBqQ1k=","YXBwbHk=","bFZLNw==","Y3p1Ymo=","TFZlQXE=","Y2NKWlY=","cmV0dXJuIChmdW5jdGlvbigpIA==",
// ...
(b[_0x4bcb("0x2a")]("第"+c,b[_0x4bcb("0x2b")]))}})}},[_0x4bcb("0x2f")]);

4. webpack-obfuscator 低混淆

高效能: 效能稍微慢於沒有混淆

new JavaScriptObfuscator({
  // 壓縮程式碼
  compact: true,
  // 是否啟用控制流扁平化(降低1.5倍的執行速度)
  controlFlowFlattening: false,
  // 隨機的死程式碼塊(增加了混淆程式碼的大小)
  deadCodeInjection: false,
  // 此選項幾乎不可能使用開發者工具的控制檯選項卡
  debugProtection: false,
  // 如果選中,則會在“控制檯”選項卡上使用間隔強制除錯模式,從而更難使用“開發人員工具”的其他功能。
  debugProtectionInterval: false,
  // 通過用空函式替換它們來禁用console.log,console.info,console.error和console.warn。這使得偵錯程式的使用更加困難。
  disableConsoleOutput: true,
  // 識別符號的混淆方式 hexadecimal(十六進位制) mangled(短識別符號)
  identifierNamesGenerator: 'hexadecimal',
  log: false,
  // 是否啟用全域性變數和函式名稱的混淆
  renameGlobals: false,
  // 通過固定和隨機(在程式碼混淆時生成)的位置移動陣列。這使得將刪除的字串的順序與其原始位置相匹配變得更加困難。如果原始原始碼不小,建議使用此選項,因為輔助函式可以引起注意。
  rotateStringArray: true,
  // 混淆後的程式碼,不能使用程式碼美化,同時需要配置 cpmpat:true;
  selfDefending: true,
  // 刪除字串文字並將它們放在一個特殊的陣列中
  stringArray: true,
  stringArrayEncoding: false,
  stringArrayThreshold: 0.75,
  // 允許啟用/禁用字串轉換為unicode轉義序列。Unicode轉義序列大大增加了程式碼大小,並且可以輕鬆地將字串恢復為原始檢視。建議僅對小型原始碼啟用此選項。
  unicodeEscapeSequence: false
}, []),

構建後檔案大小: 2,424 位元組(2.36 KB)

var _0x37a6=["exception","trace","console","個,你好,hello","lVK7","apply","return (function() ",'{}.constructor("return this")( )',"log","warn","debug","info","error"];!function(n,e){var o=function(e){for(;--e;)n.push(n.shift())};
// ...
[_0xe1fd("0x3")]("第"+n+_0xe1fd("0xb"))}()}},[_0xe1fd("0xc")]);

對比表格

檔名稱 檔案大小 正常構建 無引數 高度混淆 中度混淆 低度混淆
test.js 117位元組 177位元組 363位元組 29.2 KB(29,999 位元組) 6.90KB(7066位元組) 2.36 KB(2,424 位元組)
jquery.js 111 KB (113,852 位元組) 85.0 KB (87,064 位元組) 115 KB (117,770 位元組) 1.24 MB (1,304,998 位元組) 401 KB (411,543 位元組) 117 KB (120,243 位元組)

主要屬性

{
  // 壓縮,無換行
  compact: true,
  // 是否啟用控制流扁平化(降低1.5倍的執行速度)
  controlFlowFlattening: false,
  // 應用概率;在較大的程式碼庫中,建議降低此值,因為大量的控制流轉換可能會增加程式碼的大小並降低程式碼的速度。
  controlFlowFlatteningThreshold: 0.75,
  // 隨機的死程式碼塊(增加了混淆程式碼的大小)
  deadCodeInjection: false,
  // 死程式碼塊的影響概率
  deadCodeInjectionThreshold: 0.4,
  // 此選項幾乎不可能使用開發者工具的控制檯選項卡
  debugProtection: false,
  // 如果選中,則會在“控制檯”選項卡上使用間隔強制除錯模式,從而更難使用“開發人員工具”的其他功能。
  debugProtectionInterval: false,
  // 通過用空函式替換它們來禁用console.log,console.info,console.error和console.warn。這使得偵錯程式的使用更加困難。
  disableConsoleOutput: false,
  //鎖定混淆的原始碼,使其僅在特定域和/或子域上執行。這使得某人只需複製並貼上您的原始碼並在其他地方執行就變得非常困難。
  domainLock: [],
  //識別符號的混淆方式 hexadecimal(十六進位制) mangled(短識別符號)
  identifierNamesGenerator: 'hexadecimal',
  //全域性識別符號新增特定字首,在混淆同一頁面上載入的多個檔案時使用此選項。此選項有助於避免這些檔案的全域性識別符號之間發生衝突。為每個檔案使用不同的字首
  identifiersPrefix: '',
  inputFileName: '',
  // 允許將資訊記錄到控制檯。
  log: false,
  // 是否啟用全域性變數和函式名稱的混淆
  renameGlobals: false,
  // 禁用模糊處理和生成識別符號
  reservedNames: [],
  // 禁用字串文字的轉換
  reservedStrings: [],
  // 通過固定和隨機(在程式碼混淆時生成)的位置移動陣列。這使得將刪除的字串的順序與其原始位置相匹配變得更加困難。如果原始原始碼不小,建議使用此選項,因為輔助函式可以引起注意。
  rotateStringArray: true,
  // 混淆後的程式碼,不能使用程式碼美化,同時需要配置 cpmpat:true;
  seed: 0,
  selfDefending: false,
  sourceMap: false,
  sourceMapBaseUrl: '',
  sourceMapFileName: '',
  sourceMapMode: 'separate',
  // 刪除字串文字並將它們放在一個特殊的陣列中
  stringArray: true,
  // 編碼的所有字串文字stringArray使用base64或rc4並插入即用其解碼回在執行時的特殊程式碼。true(boolean):stringArray使用編碼值base64;false(boolean):不編碼stringArray值;'base64'(string):stringArray使用編碼值base64;'rc4'(string):stringArray使用編碼值rc4。大約慢30-50%base64,但更難獲得初始值。建議禁用unicodeEscapeSequence帶rc4編碼的選項以防止非常大的混淆程式碼。
  stringArrayEncoding: false,
  // 調整字串文字將插入stringArray的概率
  stringArrayThreshold: 0.75,
  // 您可以將混淆程式碼的目標環境設定為以下之一:Browser;Browser No Eval;Node
  target: 'browser',
  // 是否啟用混淆物件鍵
  transformObjectKeys: false,
  // 允許啟用/禁用字串轉換為unicode轉義序列。Unicode轉義序列大大增加了程式碼大小,並且可以輕鬆地將字串恢復為原始檢視。建議僅對小型原始碼啟用此選項。
  unicodeEscapeSequence: false
}

注意

安裝 webpack-obfuscator 時要注意webpack-obfuscator的版本要與本地專案 webpack 版本相匹配,我用的是webpack-obfuscator@0.18.0 專案 webpack4.x 版本。(4.x版webpack 使用最新版 webpack-obfuscator@3.3.0 會報錯無法使用,webpack 杳升級到 5.x 版本)

文章地址:https://www.cnblogs.com/dragonir/p/14445767.html 作者:dragonir

相關文章參考:js程式碼混淆 webpack-obfuscator https://blog.csdn.net/qq_31126175/article/details/86526237

相關文章