Tham khảo tùy chọn
Nội dung
compact
config
controlFlowFlattening
controlFlowFlatteningThreshold
deadCodeInjection
deadCodeInjectionThreshold
debugProtection
debugProtectionInterval
disableConsoleOutput
domainLock
Nhiều tên miền và tên miền phụ
domainLockRedirectUrl
exclude
forceTransformStrings
identifierNamesCache
Node.js API
CLI
identifierNamesGenerator
identifiersDictionary
identifiersPrefix
randomIdentifiersPrefix
ignoreImports
inputFileName
log
numbersToExpressions
optionsPreset
parseHtml
renameGlobals
renameProperties
renamePropertiesMode
reservedNames
reservedStrings
seed
selfDefending
simplify
sourceMap
sourceMapBaseUrl
sourceMapFileName
sourceMapMode
sourceMapSourcesMode
splitStrings
splitStringsChunkLength
stringArray
stringArrayCallsTransform
stringArrayCallsTransformThreshold
stringArrayEncoding
stringArrayIndexesType
stringArrayIndexShift
stringArrayRotate
stringArrayShuffle
stringArrayWrappersCount
stringArrayWrappersChainedCalls
stringArrayWrappersParametersMaxCount
stringArrayWrappersType
stringArrayThreshold
strictMode
target
transformObjectKeys
warnings
vmObfuscation
vmTargetFunctions
vmExcludeFunctions
vmTargetFunctionsMode
vmForceCompileDynamicCode
vmWrapTopLevelInitializers
vmDynamicOpcodes
vmBytecodeEncoding
vmBytecodeArrayEncoding
vmBytecodeArrayEncodingKey
vmBytecodeArrayEncodingKeyGetter
vmAsyncExecutor
vmJumpsEncoding
vmMacroOps
vmDebugProtection
vmSelfDefending
vmDefenseHook
vmDefenseReaction
vmStatefulOpcodes
vmCallContextOpcodes
vmStackEncoding
vmCompactDispatcher
vmStringArrayBytecodeOnly
vmDomainLock
Nhiều tên miền và tên miền phụ
vmDomainLockRedirectUrl
Preset Options
Làm rối cao, hiệu năng thấp
Làm rối trung bình, hiệu năng tối ưu
Làm rối thấp, hiệu năng cao
Preset mặc định, hiệu năng cao
VM Ultra High obfuscation (Maximum Security)
VM Anti-LLM (AI Agent Protection)
VM High obfuscation (Highest Security)
VM Medium obfuscation (Balanced Security)
VM Low obfuscation (Basic Security, Better Performance)
VM Default (VM + String Array Protection)
compact
Type: boolean Default: true
Xuất mã gọn trên một dòng.
config
Type: string Default: ``
Tên tệp cấu hình JS/JSON chứa các tùy chọn của trình làm rối. Chúng sẽ bị ghi đè bởi các tùy chọn được truyền trực tiếp cho CLI
controlFlowFlattening
Type: boolean Default: false
⚠️ Tùy chọn này ảnh hưởng lớn đến hiệu năng, tốc độ khi chạy có thể chậm tới 1.5 lần. Dùng controlFlowFlatteningThreshold để đặt phần trăm số node bị ảnh hưởng bởi việc làm phẳng luồng điều khiển.
Bật làm phẳng luồng điều khiển cho mã. Làm phẳng luồng điều khiển là một phép biến đổi cấu trúc của mã nguồn nhằm gây khó khăn cho việc hiểu chương trình.
Ví dụ:
// input
(function(){
function foo () {
return function () {
var sum = 1 + 2;
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
}
}
foo()();
})();
// output
(function () {
function _0x3bfc5c() {
return function () {
var _0x3260a5 = {
'WtABe': '4|0|6|5|3|2|1',
'GokKo': function _0xf87260(_0x427a8e, _0x43354c) {
return _0x427a8e + _0x43354c;
}
};
var _0x1ad4d6 = _0x3260a5['WtABe']['split']('|'), _0x1a7b12 = 0x0;
while (!![]) {
switch (_0x1ad4d6[_0x1a7b12++]) {
case '0':
console['log'](0x1);
continue;
case '1':
console['log'](0x6);
continue;
case '2':
console['log'](0x5);
continue;
case '3':
console['log'](0x4);
continue;
case '4':
var _0x1f2f2f = _0x3260a5['GokKo'](0x1, 0x2);
continue;
case '5':
console['log'](0x3);
continue;
case '6':
console['log'](0x2);
continue;
}
break;
}
};
}
_0x3bfc5c()();
}());
controlFlowFlatteningThreshold
Type: number Default: 0.75 Min: 0 Max: 1
Xác suất mà phép biến đổi controlFlowFlattening sẽ được áp dụng cho một node bất kỳ.
Cài đặt này đặc biệt hữu ích với mã có kích thước lớn, vì một lượng lớn phép biến đổi luồng điều khiển có thể làm chậm mã và tăng kích thước mã.
controlFlowFlatteningThreshold: 0 tương đương với controlFlowFlattening: false.
deadCodeInjection
Type: boolean Default: false
⚠️ Tăng đáng kể kích thước mã đã làm rối (lên tới 200%), chỉ dùng nếu kích thước mã đã làm rối không quan trọng. Dùng deadCodeInjectionThreshold để đặt phần trăm số node bị ảnh hưởng bởi việc chèn mã chết.
⚠️ Tùy chọn này buộc bật tùy chọn stringArray.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật.
Với tùy chọn này, các khối mã chết ngẫu nhiên sẽ được thêm vào mã đã làm rối.
Ví dụ:
// input
(function(){
if (true) {
var foo = function () {
console.log('abc');
};
var bar = function () {
console.log('def');
};
var baz = function () {
console.log('ghi');
};
var bark = function () {
console.log('jkl');
};
var hawk = function () {
console.log('mno');
};
foo();
bar();
baz();
bark();
hawk();
}
})();
// output
var _0x37b8 = [
'YBCtz',
'GlrkA',
'urPbb',
'abc',
'NMIhC',
'yZgAj',
'zrAId',
'EtyJA',
'log',
'mno',
'jkl',
'def',
'Quzya',
'IWbBa',
'ghi'
];
function _0x43a7(_0x12cf56, _0x587376) {
_0x43a7 = function (_0x2f87a8, _0x47eac2) {
_0x2f87a8 = _0x2f87a8 - (0x16a7 * 0x1 + 0x5 * 0x151 + -0x1c92);
var _0x341e03 = _0x37b8[_0x2f87a8];
return _0x341e03;
};
return _0x43a7(_0x12cf56, _0x587376);
}
(function () {
if (!![]) {
var _0xbbe28f = function () {
var _0x2fc85f = _0x43a7;
if (_0x2fc85f(0xaf) === _0x2fc85f(0xae)) {
_0x1dd94f[_0x2fc85f(0xb2)](_0x2fc85f(0xb5));
} else {
console[_0x2fc85f(0xb2)](_0x2fc85f(0xad));
}
};
var _0x5e46bc = function () {
var _0x15b472 = _0x43a7;
if (_0x15b472(0xb6) !== _0x15b472(0xaa)) {
console[_0x15b472(0xb2)](_0x15b472(0xb5));
} else {
_0x47eac2[_0x15b472(0xb2)](_0x15b472(0xad));
}
};
var _0x3669e8 = function () {
var _0x47a442 = _0x43a7;
if (_0x47a442(0xb7) !== _0x47a442(0xb0)) {
console[_0x47a442(0xb2)](_0x47a442(0xb8));
} else {
_0x24e0bf[_0x47a442(0xb2)](_0x47a442(0xb3));
}
};
var _0x28b05a = function () {
var _0x497902 = _0x43a7;
if (_0x497902(0xb1) === _0x497902(0xb1)) {
console[_0x497902(0xb2)](_0x497902(0xb4));
} else {
_0x59c9c6[_0x497902(0xb2)](_0x497902(0xb4));
}
};
var _0x402a54 = function () {
var _0x1906b7 = _0x43a7;
if (_0x1906b7(0xab) === _0x1906b7(0xac)) {
_0xb89cd0[_0x1906b7(0xb2)](_0x1906b7(0xb8));
} else {
console[_0x1906b7(0xb2)](_0x1906b7(0xb3));
}
};
_0xbbe28f();
_0x5e46bc();
_0x3669e8();
_0x28b05a();
_0x402a54();
}
}());
deadCodeInjectionThreshold
Type: number Default: 0.4 Min: 0 Max: 1
Cho phép đặt phần trăm số node sẽ bị ảnh hưởng bởi deadCodeInjection.
debugProtection
Type: boolean Default: false
⚠️ Có thể làm treo trình duyệt của bạn nếu bạn mở Developer Tools.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmDebugProtection thay thế.
Tùy chọn này khiến việc sử dụng chức năng debugger của Developer Tools gần như không thể (cả trên trình duyệt nền WebKit lẫn Mozilla Firefox).
debugProtectionInterval
Type: number Default: 0
⚠️ Có thể làm treo trình duyệt của bạn! Dùng và tự chịu rủi ro.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmDebugProtection thay thế.
Nếu được đặt, một khoảng thời gian tính bằng mili giây sẽ được dùng để buộc chế độ gỡ lỗi trên tab Console, khiến việc sử dụng các tính năng khác của Developer Tools khó khăn hơn. Hoạt động nếu debugProtection được bật. Giá trị khuyến nghị nằm trong khoảng 2000 đến 4000 mili giây.
disableConsoleOutput
Type: boolean Default: false
⚠️ Tùy chọn này vô hiệu hóa các lệnh gọi console trên phạm vi toàn cục cho mọi script
Vô hiệu hóa việc sử dụng console.log, console.info, console.error, console.warn, console.debug, console.exception và console.trace bằng cách thay chúng bằng các hàm rỗng. Điều này khiến việc sử dụng trình gỡ lỗi khó khăn hơn.
domainLock
Type: string[] Default: []
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép mã nguồn đã làm rối chỉ chạy trên các tên miền và/hoặc tên miền phụ cụ thể. Điều này khiến việc ai đó chỉ sao chép và dán mã nguồn của bạn rồi chạy ở nơi khác trở nên rất khó khăn.
Nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi tùy chọn này, trình duyệt sẽ được chuyển hướng đến URL được truyền cho tùy chọn domainLockRedirectUrl.
Nhiều tên miền và tên miền phụ
Bạn có thể khóa mã của mình cho nhiều hơn một tên miền hoặc tên miền phụ. Ví dụ, để khóa sao cho mã chỉ chạy trên www.example.com, hãy thêm www.example.com. Để mã hoạt động trên tên miền gốc bao gồm mọi tên miền phụ (example.com, sub.example.com), hãy dùng .example.com.
domainLockRedirectUrl
Type: string Default: about:blank
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép chuyển hướng trình duyệt đến một URL được truyền vào nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi domainLock
exclude
Type: string[] Default: []
Danh sách tên tệp hoặc glob chỉ định các tệp cần loại trừ khỏi việc làm rối.
forceTransformStrings
Type: string[] Default: []
Bật việc buộc biến đổi các chuỗi ký tự khớp với các mẫu RegExp được truyền vào.
⚠️ Tùy chọn này chỉ ảnh hưởng đến những chuỗi lẽ ra không bị biến đổi bởi stringArrayThreshold (hoặc các ngưỡng khác có thể có trong tương lai)
Tùy chọn này có độ ưu tiên cao hơn tùy chọn reservedStrings nhưng không có độ ưu tiên cao hơn conditional comments.
Ví dụ:
{
forceTransformStrings: [
'some-important-value',
'some-string_\d'
]
}
identifierNamesCache
Type: Object | null Default: null
Mục tiêu chính của tùy chọn này là khả năng sử dụng cùng một tập tên định danh khi làm rối nhiều nguồn/tệp.
Hiện tại hai loại định danh được hỗ trợ:
- Định danh toàn cục:
- Tất cả định danh toàn cục sẽ được ghi vào cache;
- Tất cả định danh toàn cục chưa được khai báo khớp sẽ được thay bằng các giá trị từ cache.
- Định danh thuộc tính, chỉ khi tùy chọn
renamePropertiesđược bật:- Tất cả định danh thuộc tính sẽ được ghi vào cache;
- Tất cả định danh thuộc tính khớp sẽ được thay bằng các giá trị từ cache.
Node.js API
Nếu truyền giá trị null, cache sẽ bị vô hiệu hóa hoàn toàn.
Nếu truyền một đối tượng rỗng ({}), sẽ bật việc ghi tên định danh vào đối tượng cache (kiểu TIdentifierNamesCache). Đối tượng cache này được truy cập thông qua lệnh gọi phương thức getIdentifierNamesCache của đối tượng ObfuscationResult.
Đối tượng cache thu được sau đó có thể được dùng làm giá trị của tùy chọn identifierNamesGenerator để sử dụng các tên này khi làm rối tất cả các tên định danh khớp của các nguồn tiếp theo.
Ví dụ:
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo(arg) {
console.log(arg)
}
function bar() {
var bark = 2;
}
`,
{
compact: false,
identifierNamesCache: {},
renameGlobals: true
}
)
console.log(source1ObfuscationResult.getIdentifierNamesCache());
/*
{
globalIdentifiers: {
foo: '_0x5de86d',
bar: '_0x2a943b'
}
}
*/
const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
// Expecting that these global functions are defined in another obfuscated file
foo(1);
bar();
// Expecting that this global function is defined in third-party package
baz();
`,
{
compact: false,
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
renameGlobals: true
}
)
console.log(source2ObfuscationResult.getObfuscatedCode());
/*
_0x5de86d(0x1);
_0x2a943b();
baz();
*/
CLI
CLI có một tùy chọn khác --identifier-names-cache-path cho phép định nghĩa đường dẫn đến tệp .json hiện có sẽ được dùng để đọc và ghi cache tên định danh.
Nếu truyền đường dẫn đến một tệp rỗng - cache tên định danh sẽ được ghi vào tệp đó.
Tệp chứa cache hiện có này có thể được dùng lại làm giá trị của tùy chọn --identifier-names-cache-path để sử dụng các tên này khi làm rối tất cả các tên định danh khớp của các tệp tiếp theo.
identifierNamesGenerator
Type: string Default: hexadecimal
Đặt bộ tạo tên định danh.
Các giá trị có sẵn:
dictionary: tên định danh lấy từ danh sáchidentifiersDictionaryhexadecimal: tên định danh dạng_0xabc123mangled: tên định danh ngắn nhưa,b,cmangled-shuffled: giốngmanglednhưng với bảng chữ cái được xáo trộn
identifiersDictionary
Type: string[] Default: []
Đặt từ điển định danh cho tùy chọn identifierNamesGenerator: dictionary. Mỗi định danh trong từ điển sẽ được dùng ở một vài biến thể với cách viết hoa/thường khác nhau cho từng ký tự. Do đó, số lượng định danh trong từ điển nên phụ thuộc vào số lượng định danh trong mã nguồn gốc.
identifiersPrefix
Type: string Default: ''
Đặt tiền tố cho tất cả định danh toàn cục.
Dùng tùy chọn này khi bạn muốn làm rối nhiều tệp. Tùy chọn này giúp tránh xung đột giữa các định danh toàn cục của những tệp đó. Tiền tố nên khác nhau cho từng tệp.
randomIdentifiersPrefix
Type: boolean Default: false
Thêm một tiền tố ngẫu nhiên dựa trên seed (6 ký tự chữ và số) vào tất cả định danh toàn cục. Dùng tùy chọn này để tránh trùng lặp giữa các bundle được làm rối riêng lẻ nhưng được nạp vào cùng một phạm vi toàn cục — nó loại bỏ nhu cầu phải tự chọn một identifiersPrefix duy nhất cho từng bundle.
- Giá trị ngẫu nhiên được suy ra từ tùy chọn
seedvà hash của mã nguồn, nên các bản build có thể tái lập với cùng seed sẽ tạo ra cùng một tiền tố. - Khi kết hợp với
identifiersPrefix, các ký tự ngẫu nhiên được nối vào tiền tố do người dùng cung cấp (ví dụ:myApp+ ngẫu nhiênaBc123→myAppaBc123). - Khi kết hợp với
vmObfuscation, giá trị ngẫu nhiên thay thế tiền tốvmmặc định — tính ngẫu nhiên đã đảm bảo tính duy nhất.
ignoreImports
Type: boolean Default: false
Ngăn việc làm rối các import require. Có thể hữu ích trong một số trường hợp khi vì lý do nào đó môi trường khi chạy yêu cầu các import này chỉ với chuỗi tĩnh.
inputFileName
Type: string Default: ''
Cho phép đặt tên của tệp đầu vào chứa mã nguồn. Tên này sẽ được dùng nội bộ để tạo source map.
Bắt buộc khi dùng NodeJS API và tùy chọn sourceMapSourcesMode có giá trị sources.
log
Type: boolean Default: false
Bật việc ghi log thông tin ra console.
numbersToExpressions
Type: boolean Default: false
Bật việc chuyển đổi các số thành biểu thức
Ví dụ:
// input
const foo = 1234;
// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;
optionsPreset
Type: string Default: default
Cho phép đặt preset tùy chọn.
Các giá trị có sẵn:
vm-default;vm-low-obfuscation;vm-medium-obfuscation;vm-high-obfuscation;vm-ultra-high-obfuscation;vm-anti-llm;default;low-obfuscation;medium-obfuscation;high-obfuscation.
Tất cả tùy chọn bổ sung sẽ được gộp với preset tùy chọn đã chọn.
parseHtml
Type: boolean Default: false
Bật việc làm rối JavaScript bên trong các thẻ HTML <script>.
Khi được bật, trình làm rối sẽ:
- Tự động phát hiện đầu vào có phải là HTML hay không (bằng cách kiểm tra các thẻ
<!DOCTYPE,<html>,<head>,<body>, hoặc<script>) - Trích xuất JavaScript từ các thẻ
<script>được đánh dấu bằng thuộc tínhdata-javascript-obfuscator - Làm rối từng script được đánh dấu một cách riêng lẻ trong khi vẫn giữ nguyên cấu trúc HTML
- Chèn mã đã làm rối trở lại các vị trí ban đầu
Quan trọng: Chỉ các script có thuộc tính data-javascript-obfuscator mới được làm rối. Mỗi script được đánh dấu được làm rối một cách riêng lẻ và độc lập. Điều này có nghĩa là:
- Mã bên trong các thẻ script được đánh dấu phải được cô lập - nó KHÔNG được tham chiếu đến các biến, hàm hoặc lớp được định nghĩa trong các thẻ script được đánh dấu khác
- Các script không được đánh dấu vẫn có thể truy cập các biến toàn cục do các script được đánh dấu định nghĩa (qua khai báo
varhoặc gánglobalThistường minh) - Điều này cho bạn quyền kiểm soát tường minh những script nào cần bảo vệ
Được làm rối (phải có thuộc tính data-javascript-obfuscator):
<script data-javascript-obfuscator>- script thông thường<script type="text/javascript" data-javascript-obfuscator>- script có kiểu được khai báo tường minh- Các script có bất kỳ thuộc tính bổ sung nào (
id,class,data-*khác, v.v.)
Bị bỏ qua (giữ nguyên không đổi):
- Các script không có thuộc tính
data-javascript-obfuscator <script type="module">- ES module (kể cả khi có thuộc tính)<script src="...">- script bên ngoài (kể cả khi có thuộc tính)- Các thẻ script rỗng
Lưu ý: Source map không được tạo khi parseHtml được bật, vì chúng sẽ không ánh xạ chính xác tới đầu ra HTML.
Ví dụ:
// input
const html = `<!DOCTYPE html>
<html>
<body>
<!-- This script will NOT be obfuscated -->
<script>
var helper = 'utility';
</script>
<!-- This script WILL be obfuscated -->
<script data-javascript-obfuscator>
var greeting = 'Hello World';
console.log(greeting);
</script>
</body>
</html>`;
JavaScriptObfuscator.obfuscate(html, {
parseHtml: true,
stringArray: true
});
// output: HTML with only the marked script obfuscated
renameGlobals
Type: boolean Default: false
⚠️ tùy chọn này có thể làm hỏng mã của bạn. Chỉ bật nếu bạn biết nó làm gì!
Bật việc làm rối tên các biến và hàm toàn cục cùng với phần khai báo.
Khi tùy chọn này bị tắt và mã đầu vào khai báo các hàm hoặc lớp trong phạm vi toàn cục (tức là mã không được bọc trong một IIFE), tên của chúng được giữ nguyên trong mã đã làm rối — các script khác có thể tham chiếu đến chúng theo tên. Dưới vmObfuscation, một cảnh báo VMGlobalFunctionNamesNotRenamed liệt kê các tên này sẽ được báo cáo, vì thân hàm được ẩn dưới dạng bytecode nhưng tên cấp cao dễ đọc vẫn để lộ những gì mã đó làm (ví dụ cho một LLM). Để tránh việc lộ này, hãy bọc mã trong một IIFE hoặc bật tùy chọn này.
renameProperties
Type: boolean Default: false
⚠️ tùy chọn này CÓ THỂ làm hỏng mã của bạn. Chỉ bật nếu bạn biết nó làm gì!
Bật việc đổi tên các thuộc tính. Tất cả thuộc tính DOM dựng sẵn và thuộc tính trong các lớp JavaScript cốt lõi sẽ được bỏ qua.
Để chuyển đổi giữa chế độ safe và unsafe của tùy chọn này, dùng tùy chọn renamePropertiesMode.
Để đặt định dạng cho tên thuộc tính được đổi, dùng tùy chọn identifierNamesGenerator.
Để kiểm soát những thuộc tính nào sẽ được đổi tên, dùng tùy chọn reservedNames.
Ví dụ:
// input
(function () {
const foo = {
prop1: 1,
prop2: 2,
calc: function () {
return this.prop1 + this.prop2;
}
};
console.log(foo.calc());
})();
// output
(function () {
const _0x46529b = {
'_0x10cec7': 0x1,
'_0xc1c0ca': 0x2,
'_0x4b961d': function () {
return this['_0x10cec7'] + this['_0xc1c0ca'];
}
};
console['log'](_0x46529b['_0x4b961d']());
}());
renamePropertiesMode
Type: string Default: safe
⚠️ Ngay cả ở chế độ safe, tùy chọn renameProperties CÓ THỂ làm hỏng mã của bạn.
Chỉ định chế độ của tùy chọn renameProperties:
safe- hành vi mặc định sau bản phát hành2.11.0. Cố gắng đổi tên thuộc tính theo cách an toàn hơn để tránh lỗi khi chạy. Với chế độ này, một số thuộc tính sẽ được loại trừ khỏi việc đổi tên.unsafe- hành vi mặc định trước bản phát hành2.11.0. Đổi tên thuộc tính theo cách không an toàn mà không có bất kỳ hạn chế nào.
Nếu một tệp đang dùng các thuộc tính từ tệp khác, hãy dùng tùy chọn identifierNamesCache để giữ nguyên tên thuộc tính giữa các tệp này.
reservedNames
Type: string[] Default: []
Vô hiệu hóa việc làm rối và tạo các định danh khớp với các mẫu RegExp được truyền vào.
Ví dụ:
{
reservedNames: [
'^someVariable',
'functionParameter_\d'
]
}
reservedStrings
Type: string[] Default: []
Vô hiệu hóa việc biến đổi các chuỗi ký tự khớp với các mẫu RegExp được truyền vào. Các chuỗi khớp sẽ vẫn hiển thị trong mã đã làm rối.
Khi dùng làm rối VM, các chuỗi được dành riêng được lưu trong một mảng riêng không mã hóa để giữ chúng hiển thị. Điều này hữu ích cho những chuỗi phải giữ được khả năng đọc, chẳng hạn như các API endpoint để giám sát hoặc các định danh thư viện.
Ví dụ:
{
reservedStrings: [
'react-native',
'\.\/src\/test',
'some-string_\d'
]
}
seed
Type: string|number Default: 0
Tùy chọn này đặt seed cho bộ tạo số ngẫu nhiên. Điều này hữu ích để tạo ra các kết quả có thể lặp lại.
Nếu seed là 0 - bộ tạo số ngẫu nhiên sẽ hoạt động mà không có seed.
selfDefending
Type: boolean Default: false
⚠️ Đừng thay đổi mã đã làm rối theo bất kỳ cách nào sau khi làm rối với tùy chọn này, vì bất kỳ thay đổi nào như uglify mã đều có thể kích hoạt self defending và mã sẽ không còn hoạt động nữa!
⚠️ Tùy chọn này buộc đặt giá trị compact thành true
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmSelfDefending thay thế.
Tùy chọn này khiến mã đầu ra có khả năng chống lại việc định dạng lại và đổi tên biến. Nếu ai đó cố dùng một trình làm đẹp (beautifier) JavaScript trên mã đã làm rối, mã sẽ không còn hoạt động, khiến việc hiểu và chỉnh sửa nó khó khăn hơn.
simplify
Type: boolean Default: true
Bật thêm việc làm rối mã thông qua đơn giản hóa.
⚠️ ở các bản phát hành trong tương lai, việc làm rối các literal boolean (true => !![]) sẽ được chuyển vào tùy chọn này.
Ví dụ:
// input
if (condition1) {
const foo = 1;
const bar = 2;
console.log(foo);
return bar;
} else if (condition2) {
console.log(1);
console.log(2);
console.log(3);
return 4;
} else {
return 5;
}
// output
if (condition1) {
const foo = 0x1, bar = 0x2;
return console['log'](foo), bar;
} else
return condition2 ? (console['log'](0x1), console['log'](0x2), console['log'](0x3), 0x4) : 0x5;
sourceMap
Type: boolean Default: false
Bật việc tạo source map cho mã đã làm rối.
Source map có thể hữu ích để giúp bạn gỡ lỗi mã nguồn JavaScript đã làm rối. Nếu bạn muốn hoặc cần gỡ lỗi trong môi trường thực tế, bạn có thể tải tệp source map riêng lên một vị trí bí mật rồi trỏ trình duyệt đến đó.
sourceMapBaseUrl
Type: string Default: ``
Đặt base url cho url import của source map khi sourceMapMode: 'separate'.
Ví dụ CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'
Kết quả:
//# sourceMappingURL=http://localhost:9000/out.js.map
sourceMapFileName
Type: string Default: ``
Đặt tên tệp cho source map đầu ra khi sourceMapMode: 'separate'.
Ví dụ CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example
Kết quả:
//# sourceMappingURL=http://localhost:9000/example.js.map
sourceMapMode
Type: string Default: separate
Chỉ định chế độ tạo source map:
inline- thêm source map vào cuối mỗi tệp .js;separate- tạo tệp '.map' tương ứng chứa source map. Trong trường hợp bạn chạy trình làm rối qua CLI - thêm liên kết đến tệp source map vào cuối tệp mã đã làm rối//# sourceMappingUrl=file.js.map.
sourceMapSourcesMode
Type: string Default: sources-content
Cho phép kiểm soát các trường sources và sourcesContent của source map:
sources-content- thêm trườngsourcesgiả, thêm trườngsourcesContentchứa mã nguồn gốc;sources- thêm trườngsourcesvới mô tả nguồn hợp lệ, không thêm trườngsourcesContent. Khi dùng NodeJS API, bắt buộc phải định nghĩa tùy chọninputFileNamesẽ được dùng làm giá trị của trườngsources.
splitStrings
Type: boolean Default: false
Chia các chuỗi ký tự thành các đoạn (chunk) có độ dài bằng giá trị của tùy chọn splitStringsChunkLength.
Ví dụ:
// input
(function(){
var test = 'abcdefg';
})();
// output
(function(){
var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();
splitStringsChunkLength
Type: number Default: 10
Đặt độ dài đoạn (chunk) của tùy chọn splitStrings.
stringArray
Type: boolean Default: true
Loại bỏ các chuỗi ký tự và đặt chúng vào một mảng đặc biệt. Ví dụ, chuỗi "Hello World" trong var m = "Hello World"; sẽ được thay bằng thứ gì đó như var m = _0x12c456[0x1];
stringArrayCallsTransform
Type: boolean Default: false
⚠️ Tùy chọn stringArray phải được bật
Bật việc biến đổi các lệnh gọi đến stringArray. Tất cả đối số của các lệnh gọi này có thể được trích xuất ra một đối tượng khác tùy theo giá trị stringArrayCallsTransformThreshold.
Điều này khiến việc tự động tìm các lệnh gọi đến string array càng khó khăn hơn.
Ví dụ:
function foo() {
var k = {
c: 0x2f2,
d: '0x396',
e: '0x397',
f: '0x39a',
g: '0x39d',
h: 0x398,
l: 0x394,
m: '0x39b',
n: '0x39f',
o: 0x395,
p: 0x395,
q: 0x399,
r: '0x399'
};
var c = i(k.d, k.e);
var d = i(k.f, k.g);
var e = i(k.h, k.l);
var f = i(k.m, k.n);
function i(c, d) {
return b(c - k.c, d);
}
var g = i(k.o, k.p);
var h = i(k.q, k.r);
}
function j(c, d) {
var l = { c: 0x14b };
return b(c - -l.c, d);
}
console[j(-'0xa6', -'0xa6')](foo());
function b(c, d) {
var e = a();
b = function (f, g) {
f = f - 0xa3;
var h = e[f];
return h;
};
return b(c, d);
}
function a() {
var m = [
'string5',
'string1',
'log',
'string3',
'string6',
'string2',
'string4'
];
a = function () {
return m;
};
return a();
}
stringArrayCallsTransformThreshold
Type: number Default: 0.5
⚠️ Các tùy chọn stringArray và stringArrayCallsTransformThreshold phải được bật
Bạn có thể dùng cài đặt này để điều chỉnh xác suất (từ 0 đến 1) mà các lệnh gọi đến string array sẽ được biến đổi.
stringArrayEncoding
Type: string[] Default: []
⚠️ Tùy chọn stringArray phải được bật
Tùy chọn này có thể làm chậm script của bạn.
Mã hóa tất cả các chuỗi ký tự của stringArray bằng base64 hoặc rc4 và chèn một đoạn mã đặc biệt dùng để giải mã trở lại khi chạy.
Mỗi giá trị stringArray sẽ được mã hóa bằng kiểu mã hóa được chọn ngẫu nhiên từ danh sách được truyền vào. Điều này giúp có thể sử dụng nhiều kiểu mã hóa.
Các giá trị có sẵn:
'none'(boolean): không mã hóa giá trịstringArray'base64'(string): mã hóa giá trịstringArraybằngbase64'rc4'(string): mã hóa giá trịstringArraybằngrc4. Chậm hơnbase64khoảng 30-50%, nhưng khó lấy được giá trị ban đầu hơn.
Ví dụ, với các giá trị tùy chọn sau, một số giá trị stringArray sẽ không được mã hóa, và một số giá trị sẽ được mã hóa bằng base64 và rc4:
stringArrayEncoding: [
'none',
'base64',
'rc4'
]
stringArrayIndexesType
Type: string[] Default: ['hexadecimal-number']
⚠️ Tùy chọn stringArray phải được bật
Cho phép kiểm soát kiểu của các chỉ mục lệnh gọi string array.
Mỗi chỉ mục lệnh gọi stringArray sẽ được biến đổi bằng kiểu được chọn ngẫu nhiên từ danh sách được truyền vào. Điều này giúp có thể sử dụng nhiều kiểu.
Các giá trị có sẵn:
'hexadecimal-number'(default): biến đổi các chỉ mục lệnh gọi string array thành số thập lục phân'hexadecimal-numeric-string': biến đổi các chỉ mục lệnh gọi string array thành chuỗi số thập lục phân
Trước bản phát hành 2.9.0, javascript-obfuscator biến đổi tất cả các chỉ mục lệnh gọi string array bằng kiểu hexadecimal-numeric-string. Điều này khiến việc gỡ rối thủ công khó hơn một chút nhưng lại giúp các công cụ gỡ rối tự động dễ phát hiện các lệnh gọi này.
Kiểu hexadecimal-number mới hướng tới việc khiến việc tự động phát hiện các mẫu lệnh gọi string array trong mã khó khăn hơn.
Nhiều kiểu hơn sẽ được bổ sung trong tương lai.
stringArrayIndexShift
Type: boolean Default: true
⚠️ Tùy chọn stringArray phải được bật
Bật việc dịch chỉ mục bổ sung cho tất cả các lệnh gọi string array
stringArrayRotate
Type: boolean Default: true
⚠️ stringArray phải được bật
Dịch chuyển mảng stringArray đi một số vị trí cố định và ngẫu nhiên (được tạo lúc làm rối mã). Điều này khiến việc khớp thứ tự của các chuỗi đã bị loại bỏ với vị trí gốc của chúng khó khăn hơn.
stringArrayShuffle
Type: boolean Default: true
⚠️ stringArray phải được bật
Xáo trộn ngẫu nhiên các phần tử của mảng stringArray.
stringArrayWrappersCount
Type: number Default: 1
⚠️ Tùy chọn stringArray phải được bật
Đặt số lượng wrapper cho string array bên trong mỗi phạm vi gốc hoặc phạm vi hàm.
Số lượng wrapper thực tế bên trong mỗi phạm vi bị giới hạn bởi số lượng node literal trong phạm vi đó.
Ví dụ:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
const hawk = 'hawk';
}
const eagle = 'eagle';
// Output, stringArrayWrappersCount: 5
const _0x3f6c = [
'bark',
'bar',
'foo',
'eagle',
'hawk',
'baz'
];
const _0x48f96e = _0x2e13;
const _0x4dfed8 = _0x2e13;
const _0x55e970 = _0x2e13;
function _0x2e13(_0x33c4f5, _0x3f6c62) {
_0x2e13 = function (_0x2e1388, _0x60b1e) {
_0x2e1388 = _0x2e1388 - 0xe2;
let _0x53d475 = _0x3f6c[_0x2e1388];
return _0x53d475;
};
return _0x2e13(_0x33c4f5, _0x3f6c62);
}
const foo = _0x48f96e(0xe4);
const bar = _0x4dfed8(0xe3);
function test() {
const _0x1c262f = _0x2e13;
const _0x54d7a4 = _0x2e13;
const _0x5142fe = _0x2e13;
const _0x1392b0 = _0x1c262f(0xe7);
const _0x201a58 = _0x1c262f(0xe2);
const _0xd3a7fb = _0x1c262f(0xe6);
}
const eagle = _0x48f96e(0xe5);
stringArrayWrappersChainedCalls
Type: boolean Default: true
⚠️ Các tùy chọn stringArray và stringArrayWrappersCount phải được bật
Bật các lệnh gọi chuỗi (chained calls) giữa các wrapper của string array.
Ví dụ:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
function test1() {
const hawk = 'hawk';
const eagle = 'eagle';
}
}
// Output, stringArrayWrappersCount: 5, stringArrayWrappersChainedCalls: true
const _0x40c2 = [
'bar',
'bark',
'hawk',
'eagle',
'foo',
'baz'
];
const _0x31c087 = _0x3280;
const _0x31759a = _0x3280;
function _0x3280(_0x1f52ee, _0x40c2a2) {
_0x3280 = function (_0x3280a4, _0xf07b02) {
_0x3280a4 = _0x3280a4 - 0x1c4;
let _0x57a182 = _0x40c2[_0x3280a4];
return _0x57a182;
};
return _0x3280(_0x1f52ee, _0x40c2a2);
}
const foo = _0x31c087(0x1c8);
const bar = _0x31c087(0x1c4);
function test() {
const _0x848719 = _0x31759a;
const _0x2693bf = _0x31c087;
const _0x2c08e8 = _0x848719(0x1c9);
const _0x359365 = _0x2693bf(0x1c5);
function _0x175e90() {
const _0x310023 = _0x848719;
const _0x2302ef = _0x2693bf;
const _0x237437 = _0x310023(0x1c6);
const _0x56145c = _0x310023(0x1c7);
}
}
stringArrayWrappersParametersMaxCount
Type: number Default: 2
⚠️ Tùy chọn stringArray phải được bật
⚠️ Hiện tại tùy chọn này chỉ ảnh hưởng đến các wrapper được thêm bởi giá trị function của tùy chọn stringArrayWrappersType
Cho phép kiểm soát số lượng tham số tối đa của các wrapper string array.
Giá trị mặc định và tối thiểu là 2. Giá trị khuyến nghị nằm trong khoảng 2 đến 5.
stringArrayWrappersType
Type: string Default: variable
⚠️ Các tùy chọn stringArray và stringArrayWrappersCount phải được bật
Cho phép chọn kiểu wrapper được thêm bởi tùy chọn stringArrayWrappersCount.
Các giá trị có sẵn:
'variable': thêm wrapper dạng biến ở đầu mỗi phạm vi. Hiệu năng nhanh.'function': thêm wrapper dạng hàm ở các vị trí ngẫu nhiên bên trong mỗi phạm vi. Hiệu năng chậm hơn so vớivariablenhưng cung cấp mức làm rối chặt chẽ hơn.
Rất khuyến nghị dùng wrapper function để làm rối mạnh hơn khi việc mất hiệu năng không gây ảnh hưởng lớn đến ứng dụng đã làm rối.
Ví dụ về giá trị tùy chọn 'function':
// input
const foo = 'foo';
function test () {
const bar = 'bar';
console.log(foo, bar);
}
test();
// output
const a = [
'log',
'bar',
'foo'
];
const foo = d(0x567, 0x568);
function b(c, d) {
b = function (e, f) {
e = e - 0x185;
let g = a[e];
return g;
};
return b(c, d);
}
function test() {
const c = e(0x51c, 0x51b);
function e (c, g) {
return b(c - 0x396, g);
}
console[f(0x51b, 0x51d)](foo, c);
function f (c, g) {
return b(c - 0x396, g);
}
}
function d (c, g) {
return b(g - 0x3e1, c);
}
test();
stringArrayThreshold
Type: number Default: 0.8 Min: 0 Max: 1
⚠️ Tùy chọn stringArray phải được bật
Bạn có thể dùng cài đặt này để điều chỉnh xác suất (từ 0 đến 1) mà một chuỗi ký tự sẽ được đưa vào stringArray.
Cài đặt này đặc biệt hữu ích với mã có kích thước lớn vì nó gọi đến string array nhiều lần và có thể làm chậm mã của bạn.
stringArrayThreshold: 0 tương đương với stringArray: false.
strictMode
Type: boolean | null Default: null
Cho phép chỉ định cách trình làm rối nên xử lý mã liên quan đến chế độ strict của JavaScript.
Các giá trị có sẵn:
null(mặc định) - tự động phát hiện chế độ strict từ mã. Nếu mã có chỉ thị'use strict'tường minh, cú pháp ES module, hoặc phương thức lớp, nó được xem là chế độ strict. Ngược lại, chế độ sloppy được giả định.true- buộc xử lý theo chế độ strict cho toàn bộ mã, ngay cả khi không có chỉ thị'use strict'tường minh. Dùng giá trị này khi mã của bạn sẽ chạy trong ngữ cảnh chế độ strict (ví dụ: trong ES module, bundler, hoặc các framework hiện đại).false- chỉ những dấu hiệu chế độ strict tường minh ('use strict', ES module, phương thức lớp) mới được xem là strict. Việc kế thừa từ phạm vi cha vẫn áp dụng theo đặc tả JS.
target
Type: string Default: browser
Cho phép đặt môi trường mục tiêu cho mã đã làm rối.
Các giá trị có sẵn:
browser(mặc định) — môi trường trang web tiêu chuẩn. Mã đầu ra giống hệt vớinode, nhưng một số tùy chọn dành riêng cho trình duyệt không được phép dùng với mục tiêunodebrowser-no-eval— giốngbrowser, nhưng đầu ra không dùngeval(). Dùng khi trang mục tiêu có Content Security Policy cấmeval/unsafe-eval.node— môi trường Node.js. Các tùy chọn dành riêng cho trình duyệt bị vô hiệu hóa (chúng cầnwindow/documentvà sẽ không làm gì hoặc ném lỗi trong Node). Một số biện pháp phòng thủvmSelfDefendingdựa trên các API chỉ có ở trình duyệt — phát hiện trình duyệt headless, khôi phục realm sạch dựa trên iframe, kiểm tra chống inspector/DOM — không được phát ra cho mục tiêu này.service-worker— ngữ cảnh Service Worker. Không cówindow, không códocument, biến toàn cụcselfkhác.userscript— sandbox của trình quản lý userscript (ví dụ Tampermonkey). Các biện pháp phòng thủvmSelfDefendingđược điều chỉnh tương ứng.bytenode— mã Node.js sẽ được biên dịch bằng bộ nạp bytenode (bytecode được V8 cache.jsc) sau khi làm rối. Bản thân trình làm rối không gọibytenode; nó phát ra JavaScript đã làm rối VM có runtime được cấu trúc để vượt qua bước biên dịch của bytenode, và các biện pháp phòng thủvmSelfDefendingđược điều chỉnh tương ứng. Hãy tự chạybytenodetrên đầu ra đã làm rối để tạo ra tệp.jsccuối cùng.
transformObjectKeys
Type: boolean Default: false
Bật việc biến đổi các khóa của đối tượng.
Ví dụ:
// input
(function(){
var object = {
foo: 'test1',
bar: {
baz: 'test2'
}
};
})();
// output
var _0x4735 = [
'foo',
'baz',
'bar',
'test1',
'test2'
];
function _0x390c(_0x33d6b6, _0x4735f4) {
_0x390c = function (_0x390c37, _0x1eed85) {
_0x390c37 = _0x390c37 - 0x198;
var _0x2275f8 = _0x4735[_0x390c37];
return _0x2275f8;
};
return _0x390c(_0x33d6b6, _0x4735f4);
}
(function () {
var _0x17d1b7 = _0x390c;
var _0xc9b6bb = {};
_0xc9b6bb[_0x17d1b7(0x199)] = _0x17d1b7(0x19c);
var _0x3d959a = {};
_0x3d959a[_0x17d1b7(0x198)] = _0x17d1b7(0x19b);
_0x3d959a[_0x17d1b7(0x19a)] = _0xc9b6bb;
var _0x41fd86 = _0x3d959a;
}());
warnings
Type: string | object Default: all
Kiểm soát những cảnh báo làm rối không nghiêm trọng nào được phát ra thông qua phương thức ObfuscationResult.getWarnings().
Các giá trị có sẵn:
'all'(mặc định) — mọi cảnh báo đều được phát ra.'none'— tất cả cảnh báo đều bị chặn.- một đối tượng ánh xạ các loại cảnh báo sang giá trị boolean — một loại được ánh xạ thành
falsesẽ bị chặn; mọi loại không có mặt (hoặc được ánh xạ thànhtrue) vẫn được bật. Ví dụ,{ "VMGlobalFunctionNamesNotRenamed": false }giữ mọi cảnh báo ngoại trừ cảnh báo đó.
Các loại cảnh báo:
VMGlobalFunctionNamesNotRenamed— dướivmObfuscation, tên của các khai báo hàm cấp cao, khai báo lớp, và các biến được gán một biểu thức hàm/mũi tên/lớp được giữ nguyên (tùy chọnrenameGlobalsbị tắt và mã không được bọc trong một IIFE), nên chúng vẫn dễ đọc trong đầu ra dù thân hàm được ẩn dưới dạng bytecode. Các tên được export không được báo cáo.VMTopLevelInitializerNotVirtualized— các bộ khởi tạo biến cấp cao vẫn nằm ở dạng JavaScript thuần dưới làm rối VM vìvmWrapTopLevelInitializersbị tắt hoặc không thể ảo hóa chúng.DynamicCodeRenameRisk— mã xây dựng một hàm từ một chuỗi khi chạy (directeval, hàm dựngFunction, hoặcfn.toString()được chèn vào một<script>/Worker), điều này có thể tham chiếu đến các định danh mà trình làm rối đã đổi tên.VMDynamicCodeSkipped— một hàm bị bỏ qua khỏi việc dịch bytecode VM vì nó chứa directeval/new Functionđộng /Function(xemvmForceCompileDynamicCode).VMSyncFunctionSkippedInAsyncMode— khivmAsyncExecutorđược bật, một hàm bạn đánh dấu tường minh ở chế độcommenthóa ra lại là đồng bộ và đã bị bỏ qua (chỉ các hàm async mới được ảo hóa ở chế độ đó).VMAsyncGeneratorSkippedInAsyncMode— khivmAsyncExecutorvà một async key getter đang hoạt động, một async generator được đánh dấu không thể được ảo hóa (nó phải trả về iterator của mình một cách đồng bộ).BrowserTargetWithNodeStyleCode— mã trông như nhắm tới Node.js (ví dụrequire('fs'),__dirname,process.argv) trong khi tùy chọntargetđược đặt thành một môi trường giống trình duyệt.
vmObfuscation
Type: boolean Default: false
Bật làm rối bytecode dựa trên VM. Khi được bật, các hàm JavaScript được biên dịch thành bytecode tùy chỉnh chạy trên một máy ảo nhúng. Điều này cung cấp mức bảo vệ cao nhất vì logic mã gốc được biến đổi hoàn toàn.
Ví dụ:
Mã dễ đọc của bạn như return qty * price trở thành một danh sách các số như [0x15,0x03,0x17,...] mà chỉ trình thông dịch VM nhúng mới có thể thực thi. Logic gốc không còn hiển thị dưới dạng JavaScript nữa.
vmTargetFunctions
Type: string[] Default: []
Chỉ định chính xác theo tên những hàm cấp gốc nào sẽ được bảo vệ bằng VM.
Ví dụ:
{
vmObfuscation: true,
vmTargetFunctions: ['someFunctionName']
}
Kết quả: Chỉ ba hàm này được bảo vệ bằng VM. Mọi thứ còn lại vẫn là JavaScript thông thường (nhưng vẫn được làm rối). Hoàn hảo để bảo vệ các đoạn kiểm tra giấy phép nhạy cảm hoặc logic xác thực trong khi giữ phần còn lại của mã gọn nhẹ.
vmExcludeFunctions
Type: string[] Default: []
Chỉ định những hàm cấp gốc không bao giờ được bảo vệ bằng VM. Có độ ưu tiên cao hơn các cài đặt khác.
Ví dụ:
{
vmObfuscation: true,
vmExcludeFunctions: ['someFunctionName']
}
Khi nào dùng: Các hàm cấp gốc quan trọng về hiệu năng (vòng lặp animation, xử lý dữ liệu thời gian thực) có thể được loại trừ để tránh chi phí phụ trội của VM trong khi vẫn bảo vệ mọi thứ còn lại.
vmTargetFunctionsMode
Type: string Default: root
Kiểm soát cách các hàm/phương thức được chọn để làm rối VM.
Ví dụ - Chế độ comment:
// Source code
function regularFunction() {
return 'not virtualized';
}
/* javascript-obfuscator:vm */
function sensitiveFunction() {
return 'this will be VM-protected';
}
function outer() {
/* javascript-obfuscator:vm */
function nestedSensitive() {
return 'nested but still VM-protected';
}
return nestedSensitive();
}
// Obfuscator options
{
vmObfuscation: true,
vmTargetFunctionsMode: 'comment'
}
Khi nào dùng: Khi bạn cần kiểm soát chính xác đến từng chi tiết những hàm nào được bảo vệ bằng VM, đặc biệt là các hàm lồng nhau chứa logic nhạy cảm. Không giống vmTargetFunctions vốn chỉ hoạt động với các hàm có tên ở cấp gốc, chế độ comment cho phép bạn bảo vệ bất kỳ hàm nào ở bất cứ đâu trong mã.
vmForceCompileDynamicCode
Type: boolean Default: false
Kiểm soát điều mà làm rối VM thực hiện với một hàm chứa lệnh gọi direct eval, new Function(...), hoặc Function(...).
Theo mặc định, một hàm như vậy (và mọi hàm được định nghĩa bên trong nó) bị bỏ qua khỏi việc dịch bytecode VM và một cảnh báo VMDynamicCodeSkipped được báo cáo trong result.getWarnings(). Điều này là vì mã nguồn được dựng khi chạy có thể tham chiếu đến các định danh từ chuỗi phạm vi xung quanh — những định danh mà trình làm rối đã đổi tên.
Khi được đặt thành true, hàm vẫn được dịch thành bytecode và cảnh báo VMDynamicCodeSkipped không còn được phát ra nữa.
Cảnh báo riêng DynamicCodeRenameRisk vẫn tiếp tục kích hoạt bất kể tùy chọn này, vì rủi ro đổi tên mà nó mô tả là độc lập với việc bỏ qua VM — bật tùy chọn này không khiến mẫu bên dưới an toàn hơn chút nào.
// Source code
function loadConfig(src) {
return eval(src);
}
loadConfig('1 + 2');
// Options
{
vmObfuscation: true,
vmForceCompileDynamicCode: true
}
Khi tùy chọn tắt (mặc định), loadConfig được giữ nguyên ở dạng JavaScript thuần. Khi tùy chọn bật, loadConfig được biên dịch thành bytecode VM như bất kỳ hàm nào khác. Dùng tùy chọn này khi bạn đã kiểm tra kỹ điểm gọi và biết chắc mã được dựng khi chạy không phụ thuộc vào các định danh đã bị đổi tên trong closure.
vmWrapTopLevelInitializers
Type: boolean Default: false
Bọc một số bộ khởi tạo biến cấp cao trong các IIFE (Biểu thức hàm được gọi ngay lập tức) để chúng có thể được làm rối VM.
Nó làm gì: Nếu không có tùy chọn này, các hằng và biến cấp cao vẫn hiển thị trong đầu ra:
// Input
const MY_STRING = "my-string";
// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string"; // String is visible!
Khi tùy chọn này được bật, bộ khởi tạo được bọc trong một IIFE và được làm rối VM:
// Input
const MY_STRING = "my-string";
// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })(); // String hidden in bytecode
Lưu ý: Tùy chọn này chỉ hoạt động khi vmTargetFunctionsMode là 'root' (giá trị mặc định).
Cảnh báo: Bất cứ khi nào một bộ khởi tạo cấp cao rốt cuộc nằm ở dạng JavaScript thuần dưới làm rối VM, một cảnh báo VMTopLevelInitializerNotVirtualized liệt kê tên các biến bị ảnh hưởng sẽ được báo cáo. Điều đó bao gồm: tùy chọn này bị tắt, các bộ khởi tạo mà tùy chọn này phải bỏ qua (mỗi cái kèm theo lý do — ví dụ bộ khởi tạo tham chiếu đến một declarator anh em hoặc chứa top-level await), và chế độ vmAsyncExecutor nơi các wrapper đồng bộ hoàn toàn không thể được ảo hóa.
vmDynamicOpcodes
Type: boolean Default: false
Làm cho trình thông dịch VM nhỏ hơn và khác biệt với mỗi bản build.
Nó làm gì:
- Lọc bỏ các lệnh không dùng đến - Nếu mã của bạn không dùng lớp, các lệnh liên quan đến lớp sẽ bị loại bỏ hoàn toàn
- Ngẫu nhiên hóa cấu trúc - Thứ tự của các trình xử lý lệnh được xáo trộn ở mỗi bản build
Kết quả là - đầu ra nhỏ hơn và mỗi bản build trông khác nhau.
vmBytecodeEncoding
Type: boolean Default: false
Mã hóa từng lệnh bytecode. Các lệnh được giải mã từng cái một trong quá trình thực thi.
vmBytecodeArrayEncoding
Type: boolean Default: false
Mã hóa toàn bộ mảng bytecode như một khối duy nhất. Mảng được giải mã một lần lúc khởi động trước khi việc thực thi bắt đầu. Dùng cùng với vmBytecodeEncoding để có hai lớp bảo vệ.
vmBytecodeArrayEncodingKey
Type: string Default: ''
Khóa mã hóa tùy chỉnh cho việc mã hóa mảng bytecode. Khi được đặt, khóa này được dùng thay cho khóa mặc định suy ra từ môi trường. Khóa phải được cung cấp khi chạy thông qua vmBytecodeArrayEncodingKeyGetter.
Tùy chọn này đưa khóa mã hóa ra bên ngoài - nó không được nhúng vào chính mã đã làm rối. Dù khóa vẫn có thể truy cập được khi chạy (và do đó không thực sự bí mật), sự tách biệt này ngăn các công cụ phân tích tĩnh tìm ra khóa chỉ bằng cách xem xét mã.
Quan trọng: Khóa phải có sẵn một cách đồng bộ khi mã đã làm rối được nạp. Hãy dùng các kho lưu trữ đồng bộ như cookie, localStorage, sessionStorage, biến toàn cục, hoặc phần tử DOM (ví dụ các thẻ meta do máy chủ chèn vào). Các phương thức bất đồng bộ như fetch() không thể được dùng trực tiếp trong biểu thức key getter.
vmBytecodeArrayEncodingKeyGetter
Type: string Default: ''
Biểu thức JavaScript đồng bộ trả về khóa mã hóa khi chạy. Biểu thức này được ước lượng khi mã đã làm rối được nạp, và phải trả về đúng khóa đã được cung cấp trong vmBytecodeArrayEncodingKey. Để giải quyết khóa một cách bất đồng bộ (một Promise), hãy bật vmAsyncExecutor.
Lưu ý: một getter trả về Promise yêu cầu vmAsyncExecutor. Điều này không thể được kiểm tra lúc build, nên một getter Promise với vmAsyncExecutor tắt sẽ thất bại khi chạy — bộ giải mã nhận được Promise thay vì khóa.
Mã đã làm rối chỉ hoạt động khi key getter trả về đúng khóa đã được dùng trong quá trình làm rối. Nếu các khóa không khớp, việc giải mã sẽ thất bại và mã sẽ tạo ra rác hoặc lỗi. Nếu key getter trả về undefined, null, hoặc một chuỗi rỗng, mã sẽ ném ra một lỗi: "VM decryption key not available".
Quan trọng: Giữ khóa ở ngoài cùng tệp/script với mã đã làm rối — việc nhúng nó ngay đó cho phép ngay cả một lần quét tĩnh thuần túy trên bundle cũng khôi phục được nó. Thay vào đó hãy lưu nó ở một nguồn riêng: cookie do máy chủ đặt, localStorage được một script khác điền vào, một thẻ meta HTML do máy chủ chèn vào, một biến toàn cục do một script khác đặt, hoặc (với vmAsyncExecutor) được lấy từ backend của bạn khi chạy.
Khi khóa được lấy từ backend của bạn (qua vmAsyncExecutor), hãy thêm các kiểm tra dựa trên phiên hoặc dựa trên origin trên endpoint đó: trả về khóa đúng cho người dùng thật (phiên hợp lệ, Origin/Referer như mong đợi) và một khóa rác cho các yêu cầu đáng ngờ (ví dụ một origin localhost/không mong đợi, không có phiên). Người dùng thật chạy bình thường; một bản sao chạy bên ngoài môi trường của bạn nhận được một khóa giải mã ra thứ vô nghĩa. Logic cụ thể tùy thuộc vào trang web của bạn.
Ví dụ:
// From cookie
vmBytecodeArrayEncodingKeyGetter: "document.cookie.match(/vmKey=([^;]+)/)?.[1]"
// From localStorage
vmBytecodeArrayEncodingKeyGetter: "localStorage.getItem('vmKey')"
// From global variable
vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__"
// From meta tag (server-injected)
vmBytecodeArrayEncodingKeyGetter: "document.querySelector('meta[name=\"vm-key\"]').content"
// From nested object
vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"
// From backend, async (requires vmAsyncExecutor)
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
Ví dụ sử dụng:
// Build time
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
});
// Runtime - key must be set before obfuscated code runs
window.__VM_KEY__ = 'mySecretKey123';
vmAsyncExecutor
Type: boolean Default: false
Bật executor VM bất đồng bộ, cho phép vmBytecodeArrayEncodingKeyGetter trả về một Promise (một key getter bất đồng bộ) — nhờ đó khóa giải mã có thể được lấy khi chạy (yêu cầu mạng, IndexedDB, v.v.) thay vì phải có sẵn một cách đồng bộ khi mã được nạp.
Rất được khuyến nghị cho các codebase bất đồng bộ hoàn toàn. Ở chế độ này chỉ các hàm async mới được ảo hóa — một hàm đồng bộ không thể biến thành async mà không biến giá trị trả về của nó thành Promise và làm hỏng những nơi gọi nó — nên mã async xuyên suốt sẽ đạt độ bao phủ cao nhất. Nó vẫn hoạt động khi phần gốc là đồng bộ (ví dụ một IIFE / wrapper UMD đồng bộ): các hàm async ngoài cùng bên trong được bảo vệ, còn các phần đồng bộ được giữ nguyên.
Những gì được biến đổi: mọi hàm async ngoài cùng, dù xuất hiện ở đâu (kể cả lồng bên trong các wrapper đồng bộ). Hàm async ngoài cùng trong mỗi chuỗi là đơn vị được bảo vệ — mọi thứ bên trong nó, dù đồng bộ hay bất đồng bộ, đều được biên dịch vào. Các hàm đồng bộ và generator thường được giữ nguyên không làm rối.
function foo() { // sync — left as-is
function bar() {} // sync — left as-is
async function baz() { // transformed
// any code here, including calls to other async or sync functions
}
async function bark() { // transformed
// any code here, including calls to other async or sync functions
}
}
Bỏ qua và cảnh báo. Các async generator cũng được giữ nguyên không làm rối khi một async key getter đang hoạt động (một async generator phải trả về iterator của mình một cách đồng bộ và không thể chờ khóa). Ở chế độ mặc định vmTargetFunctionsMode: 'root' việc bỏ qua diễn ra âm thầm (việc chọn là tự động); ở chế độ comment, một cảnh báo được phát ra qua ObfuscationResult.getWarnings() bất cứ khi nào một hàm bạn đánh dấu tường minh không thể được ảo hóa — hóa ra nó đồng bộ, hoặc nó là một async generator dưới một async key getter.
Async key getter còn yêu cầu thêm vmBytecodeArrayEncoding cùng với một vmBytecodeArrayEncodingKeyGetter.
Ví dụ sử dụng:
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmAsyncExecutor: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
// the key getter may now return a Promise
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
});
vmJumpsEncoding
Type: boolean Default: false
Mã hóa các đích nhảy trong bytecode. Các offset nhảy được tính khi chạy, ẩn cấu trúc luồng điều khiển (if/else, vòng lặp, v.v.) khỏi phân tích tĩnh.
vmMacroOps
Type: boolean Default: false
Kết hợp các chuỗi lệnh phổ biến thành các opcode "macro" đơn lẻ. Ví dụ, LOAD + ADD + STORE có thể trở thành một lệnh MACRO_ADD_TO_VAR duy nhất. Điều này phá vỡ việc nhận dạng mẫu và có thể cải thiện hiệu năng.
vmDebugProtection
Type: boolean Default: false
Thêm các biện pháp phòng thủ nhiều lớp chống gỡ lỗi, chống phân tích và chống LLM vào runtime của VM. Hoạt động tốt nhất với các mục tiêu browser/browser-no-eval.
vmSelfDefending
Type: boolean Default: false
Thêm bảo vệ nhiều lớp chống can thiệp, chống hooking và chống dịch ngược vào runtime của VM.
⚠️ Tùy chọn này buộc bật vmBytecodeArrayEncoding.
⚠️ Phát hiện môi trường nhạy cảm. Tùy chọn này ràng buộc mã đã làm rối với môi trường runtime mục tiêu của nó và dùng kỹ thuật fingerprint trình duyệt nâng cao để phát hiện các công cụ tự động hóa. Mã được bảo vệ bằng tùy chọn này sẽ cố ý hỏng khi chạy trong:
- Trình duyệt headless (Chrome/Chromium headless, PhantomJS)
- Công cụ tự động hóa trình duyệt (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
- Node.js (khi
targetđược đặt thànhbrowser) - jsdom hoặc các bản mô phỏng DOM phía máy chủ tương tự
- Các môi trường mà các builtin gốc của trình duyệt đã bị hook hoặc thay thế
Mã sẽ hoạt động đúng trong các trình duyệt thông thường (Chrome, Firefox, Safari, Edge), kể cả khi được nạp bên trong iframe, tiện ích mở rộng trình duyệt (content script), và Web Worker. Nếu bạn cần chạy kiểm thử tự động trên mã được bảo vệ, hãy tắt vmSelfDefending cho các bản build kiểm thử — tùy chọn này được thiết kế để ngăn phân tích tự động và không thể được dùng an toàn với bất kỳ framework tự động hóa nào.
Rất khuyến nghị dùng cùng với vmDebugProtection, vmBytecodeArrayEncodingKey, và vmBytecodeArrayEncodingKeyGetter.
vmDefenseHook
Type: { name: string, aliases?: object } Default: ''
vmDefenseHook nhận một đối tượng với hai khóa: name (bắt buộc) và aliases (không bắt buộc).
name là một hàm toàn cục mà trang chủ của bạn định nghĩa và được một biện pháp phòng thủ VM (vmDebugProtection / vmSelfDefending) gọi với một đối tượng tín hiệu khi nó phát hiện một tín hiệu thù địch — một trình gỡ lỗi hoặc inspector, một trình duyệt headless / tự động hóa, một tiến trình AI-coding-agent, một tên miền không được phép, v.v. Dùng nó để báo cáo sự kiện về backend của bạn (ví dụ navigator.sendBeacon). Hook là một điểm thu telemetry thuần túy: giá trị trả về của nó bị bỏ qua, và một hook thiếu hoặc ném lỗi là một no-op âm thầm không bao giờ có thể vô hiệu hóa một biện pháp phòng thủ. Để thay đổi điều mà một biện pháp phòng thủ làm khi phát hiện, hãy dùng vmDefenseReaction.
aliases tùy chọn đổi tên các trường của đối tượng tín hiệu đó — được trình bày ở phần Đổi tên các trường tín hiệu bên dưới.
Đối tượng tín hiệu. Hook nhận một signal duy nhất:
source— bộ phát hiện cụ thể đã kích hoạt (xem bảng).category— nhóm mà nó báo cáo dưới đó:automation(trình duyệt không phải con người),debugger(một trình gỡ lỗi/inspector đang hoạt động),sandbox(host bị đo đạc/giả),domain(vi phạm domain-lock),tamper(các builtin bị vá khi chạy), hoặcintegrity(mã của chính VM bị thay đổi).score/threshold— bộ phát hiện đã kích hoạt mạnh đến mức nào và giá trị mà nó phải đạt tới; hook chỉ kích hoạt khiscore >= threshold. Hầu hết các kiểm tra là được-ăn-cả-ngã-về-không (một tín hiệu quyết định duy nhất);headlesscộng gộp nhiều tín hiệu về hình dạng trình duyệt, nênscorecủa nó thường cao hơnthresholdcủa nó.
Đăng ký hook. Định nghĩa nó như một biến toàn cục thuần túy trước khi bundle đã làm rối được nạp — runtime của VM và các biện pháp phòng thủ của nó chạy trước chương trình (được bảo vệ) của bạn, nên nhiều phát hiện kích hoạt trong quá trình khởi động:
// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }
Một hook được định nghĩa bên trong mã nguồn đã làm rối được đăng ký quá muộn để bắt được các phát hiện lúc khởi động, và nếu nó bị biên dịch VM thì không thể tiếp cận được cho đến khi chương trình của bạn chạy. Dù thế nào nó vẫn được giữ an toàn (một hook thiếu sẽ no-op, và một cơ chế bảo vệ chống tái nhập ngăn mọi tình huống mất kiểm soát), nhưng để có độ bao phủ hoàn chỉnh hãy đăng ký nó từ đầu. Để vẫn bảo vệ logic báo cáo của bạn, hãy giữ hook đã đăng ký là một bộ đệm một dòng ((window.__vmDet = window.__vmDet || []).push(signal)) và đọc/gửi bộ đệm đó từ mã đã làm rối của bạn.
Đổi tên các trường tín hiệu (aliases). Các giá trị source/category mặc định là những tên mang tính mô tả, nên bất kỳ ai đo đạc callback (hoặc đọc đầu ra) đều có thể nhận ra cơ chế bảo vệ và bộ phát hiện nào đã kích hoạt. aliases đổi tên các trường tín hiệu thành các token mờ đục do bạn chọn, được áp dụng bên trong VM trước khi tín hiệu được phát ra, nên những tên đó không bao giờ xuất hiện trong đầu ra hoặc đến được callback. Ứng dụng của bạn biết ánh xạ của riêng nó và chuyển tiếp các token đến backend của bạn.
Aliases áp dụng theo từng trường, giữ việc đổi tên khóa và giá trị tách biệt: mỗi trường nhận một key (tên thuộc tính mà callback nhận được); các trường tên dạng chuỗi source và category cũng nhận một ánh xạ values, trong khi score/threshold là số và chỉ nhận một key. Những tên bạn có thể ánh xạ (bất kỳ tên nào khác sẽ bị từ chối lúc build):
- khóa trường —
source,category,score,threshold - giá trị
source—headless,agent,node,debugger,timing,sandbox,domain,nativeHook,integrity - giá trị
category—automation,debugger,sandbox,domain,tamper,integrity
vmDefenseHook: {
name: '__vmDetection',
aliases: {
source: { key: 'a8Qm', values: { headless: 'xP4m9Q' } },
category: { key: 'p3Tx', values: { automation: 'bQ7s1M' } },
score: { key: 's1' },
threshold: { key: 't1' }
}
// the callback now receives e.g. { a8Qm: 'xP4m9Q', p3Tx: 'bQ7s1M', s1: <score>, t1: <threshold> }
}
Đây là việc tránh bị fingerprint, không phải sự bí mật — ánh xạ vẫn có thể được suy ra bằng cách thử nghiệm lặp lại — nên lợi ích duy nhất của nó là không để lộ những tên ổn định, tự giải thích. Các mục chưa đặt sẽ giữ tên mặc định của chúng.
Một chuỗi trần (vmDefenseHook: '__vmDetection') được chấp nhận như dạng viết tắt của { name: '__vmDetection' } nhưng đã lỗi thời — nên dùng dạng đối tượng.
vmDefenseReaction
Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }
Cấu hình cách mỗi category phát hiện phản ứng. Nó không bật bất cứ thứ gì — bản thân các biện pháp phòng thủ được bật bởi vmSelfDefending, vmDebugProtection, và vmDomainLock; tùy chọn này chỉ chọn cách một biện pháp phòng thủ đang bật phản ứng. Category là đơn vị kiểm soát — mọi bộ phát hiện trong một category đều thực thi phản ứng của category đó.
Mỗi category nhóm các bộ phát hiện theo dõi một loại điều kiện thù địch. Một category chỉ phản ứng khi tùy chọn phát ra các bộ phát hiện của nó được bật:
Mỗi category ánh xạ tới một hoặc nhiều trong số vmSelfDefending, vmDebugProtection, và vmDomainLock; không có category nào nằm ngoài ba tùy chọn đó, và một phản ứng được đặt cho một category có tùy chọn đang tắt thì đơn giản là không có tác dụng.
Các khóa là sáu tên category này, hoặc default (một dự phòng cho các category không được chỉ định). Các giá trị là:
break— dừng ngay lập tứcdecoy— tiếp tục chạy trên trạng thái đã bị đầu độc, âm thầm tạo ra kết quả sainone— không làm gì cục bộ (chỉ telemetry)
Các giá trị mặc định theo từng category được hiển thị ở trên; một category bạn không đặt (hoặc đặt về giá trị mặc định của nó) sẽ dùng giá trị mặc định đó. default áp dụng tới mọi category, bao gồm cả những category đúng-theo-thiết-kế (integrity, tamper), nên { default: 'none' } là một bản build thực sự không gây hỏng, chỉ dùng telemetry:
vmDefenseReaction: { default: 'none' } // never break — pair with vmDefenseHook
vmDefenseReaction: { automation: 'none', domain: 'break' } // tolerate automation FPs, still break on a bad domain
vmStatefulOpcodes
Type: boolean Default: false
Làm cho ý nghĩa của opcode phụ thuộc vào vị trí trong bytecode. Mỗi vị trí có một ánh xạ opcode-sang-handler khác nhau được suy ra từ một seed, nên cùng một số opcode thực hiện các thao tác khác nhau ở các vị trí khác nhau.
vmCallContextOpcodes
Type: boolean Default: false
Làm cho một hàm được bảo vệ phụ thuộc vào nơi nó được gọi, để nó không thể bị tách ra khỏi mã rồi chạy hoặc phân tích một cách độc lập — nó chỉ hành xử đúng khi được gọi thông qua các điểm gọi thực sự của nó trong chương trình. Tùy chọn này ảnh hưởng đến hiệu năng khi chạy.
Hiện tại chỉ các cấu trúc sau được hỗ trợ:
- khai báo hàm (
function f() {}); - biểu thức hàm và hàm mũi tên được gán cho một biến (
const f = () => {}); - phương thức riêng tư của thể hiện (
this.#m()).
Trong mọi trường hợp, hàm luôn phải được tiếp cận thông qua một lệnh gọi trực tiếp (f(), this.#m()). Nếu nó được lưu trong một biến khác, được truyền như một đối số, hoặc được dùng như một giá trị theo cách khác, nó sẽ không được bảo vệ. Các hàm async được hỗ trợ; generator thì không.
Tùy chọn này mang tính thử nghiệm và có thể làm hỏng mã của bạn, vì vậy hãy kiểm thử kỹ đầu ra trước khi dùng.
vmStackEncoding
Type: boolean Default: false
Mã hóa các giá trị trên stack của VM trong quá trình thực thi. Các giá trị được mã hóa khi được đẩy vào (push) và được giải mã khi được lấy ra (pop), nên việc kiểm tra bộ nhớ chỉ thấy dữ liệu đã mã hóa thay vì giá trị thực.
Tùy chọn này ảnh hưởng nặng đến hiệu năng.
vmCompactDispatcher
Type: boolean Default: false
Dùng một executor VM duy nhất thay vì hai executor (sync + generator). Giảm kích thước mã đã làm rối nhưng thêm khoảng ~20% chi phí hiệu năng phụ trội trên mã nhiều đệ quy.
false(mặc định): hai executor — hiệu năng tối ưu, đầu ra lớn hơntrue: một executor — đầu ra nhỏ hơn, chậm hơn một chút
vmStringArrayBytecodeOnly
Type: boolean Default: false
Khi được bật, string array sẽ chỉ trích xuất các chuỗi từ dữ liệu bytecode — không có chuỗi nào khác trong mã bị biến đổi. Tùy chọn này buộc bật stringArray ngay cả khi nó không được đặt tường minh.
Vì sao dùng tùy chọn này: Việc trích xuất tất cả các chuỗi runtime của VM vào một string array thì chậm. Tùy chọn này chỉ nhắm đến nội dung bytecode cho việc trích xuất string array, cải thiện hiệu năng trong khi vẫn bảo vệ các hằng bytecode.
- Khi
vmBytecodeArrayEncoding: false— các chuỗi bên trong các bể hằng bytecode (mảngc) được trích xuất - Khi
vmBytecodeArrayEncoding: true— các chuỗi bytecode được mã hóa base64 ở cấp cao được trích xuất stringArrayThresholdvẫn kiểm soát bao nhiêu phần trăm của các chuỗi bytecode đó được trích xuất
vmDomainLock
Type: string[] Default: []
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Giới hạn mã đã làm rối chỉ chạy trên các tên miền và/hoặc tên miền phụ cụ thể, và khó định vị cũng như loại bỏ hơn nhiều so với domainLock.
Nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi tùy chọn này, trình duyệt sẽ được chuyển hướng đến URL được truyền cho vmDomainLockRedirectUrl, và các lệnh gọi được bảo vệ tiếp theo sẽ trả về kết quả không chính xác ngay cả khi việc chuyển hướng bị chặn.
Nhiều tên miền và tên miền phụ
Bạn có thể khóa mã của mình cho nhiều hơn một tên miền hoặc tên miền phụ. Ví dụ, để khóa sao cho mã chỉ chạy trên www.example.com, hãy thêm www.example.com. Để mã hoạt động trên tên miền gốc bao gồm mọi tên miền phụ (example.com, sub.example.com), hãy dùng .example.com.
vmDomainLockRedirectUrl
Type: string Default: about:blank
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép chuyển hướng trình duyệt đến một URL được truyền vào nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi vmDomainLock.
Preset Options
Làm rối cao, hiệu năng thấp
Hiệu năng sẽ chậm hơn nhiều so với khi không làm rối
{
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,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true
}
Làm rối trung bình, hiệu năng tối ưu
Hiệu năng sẽ chậm hơn so với khi không làm rối
{
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,
strictMode: null,
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
}
Làm rối thấp, hiệu năng cao
Hiệu năng sẽ ở mức tương đối bình thường
{
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,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Preset mặc định, hiệu năng cao
{
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,
strictMode: null,
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
}
VM Ultra High obfuscation (Maximum Security)
Preset này bật làm rối bytecode dựa trên VM với tất cả các tính năng gia cố bao gồm cả điều phối gián tiếp (indirect dispatch). Cung cấp mức bảo vệ mạnh nhất nhưng với kích thước đầu ra lớn hơn và tốc độ thực thi chậm hơn nhiều.
{
optionsPreset: 'vm-ultra-high-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.5,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.5,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.5,
transformObjectKeys: true
}
VM Anti-LLM (AI Agent Protection)
Preset này được thiết kế riêng để ngăn các AI agent và LLM dịch ngược mã đã được VM dịch thành bytecode. Dựa trên vm-default với self-defending và debug protection được bật. Nhẹ hơn vm-high-obfuscation nhưng được gia cố riêng để chống lại phân tích tự động.
{
optionsPreset: 'vm-anti-llm'
}
Bao gồm:
- Làm rối bytecode VM cùng với string array (từ
vm-default) vmSelfDefending— phát hiện chống hook, hash toàn vẹn, fingerprint mã nguồn, xác minh realm sạch bằng iframe, dẫn xuất khóa cipher ARXvmDebugProtection— các kiểm tra chống gỡ lỗi trong vòng lặp điều phối của VMdebugProtection: false— không dùng debug protection cũ (debug protection của VM ưu việt hơn)
VM High obfuscation (Highest Security)
Preset này bật làm rối bytecode dựa trên VM với hầu hết các tính năng gia cố. Cung cấp bảo vệ mạnh với hiệu năng tốt hơn preset ultra-high.
{
optionsPreset: 'vm-high-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: false
}
VM Medium obfuscation (Balanced Security)
Preset này bật làm rối bytecode dựa trên VM với một tập các tính năng gia cố cân bằng. Là sự thỏa hiệp tốt giữa bảo mật và hiệu năng.
{
optionsPreset: 'vm-medium-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Low obfuscation (Basic Security, Better Performance)
Preset này bật làm rối bytecode dựa trên VM cơ bản mà không có các tính năng gia cố bổ sung. Là sự cân bằng tốt giữa bảo mật và kích thước đầu ra.
{
optionsPreset: 'vm-low-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: false,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Default (VM + String Array Protection)
Preset này kết hợp làm rối bytecode dựa trên VM cơ bản với bảo vệ string array. Điểm khởi đầu tốt cho việc làm rối VM kèm bảo vệ chuỗi.
{
optionsPreset: 'vm-default'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: true,
vmStringArrayBytecodeOnly: true,
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false,
stringArray: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayThreshold: 1,
stringArrayIndexShift: true,
stringArrayIndexesType: ['hexadecimal-number'],
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1,
stringArrayWrappersCount: 3,
stringArrayWrappersType: 'function',
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayEncoding: ['base64'],
splitStrings: true,
splitStringsChunkLength: 6
}
compact
Type: boolean Default: true
Xuất mã gọn trên một dòng.
config
Type: string Default: ``
Tên tệp cấu hình JS/JSON chứa các tùy chọn của trình làm rối. Chúng sẽ bị ghi đè bởi các tùy chọn được truyền trực tiếp cho CLI
controlFlowFlattening
Type: boolean Default: false
⚠️ Tùy chọn này ảnh hưởng lớn đến hiệu năng, tốc độ khi chạy có thể chậm tới 1.5 lần. Dùng controlFlowFlatteningThreshold để đặt phần trăm số node bị ảnh hưởng bởi việc làm phẳng luồng điều khiển.
Bật làm phẳng luồng điều khiển cho mã. Làm phẳng luồng điều khiển là một phép biến đổi cấu trúc của mã nguồn nhằm gây khó khăn cho việc hiểu chương trình.
Ví dụ:
// input
(function(){
function foo () {
return function () {
var sum = 1 + 2;
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
}
}
foo()();
})();
// output
(function () {
function _0x3bfc5c() {
return function () {
var _0x3260a5 = {
'WtABe': '4|0|6|5|3|2|1',
'GokKo': function _0xf87260(_0x427a8e, _0x43354c) {
return _0x427a8e + _0x43354c;
}
};
var _0x1ad4d6 = _0x3260a5['WtABe']['split']('|'), _0x1a7b12 = 0x0;
while (!![]) {
switch (_0x1ad4d6[_0x1a7b12++]) {
case '0':
console['log'](0x1);
continue;
case '1':
console['log'](0x6);
continue;
case '2':
console['log'](0x5);
continue;
case '3':
console['log'](0x4);
continue;
case '4':
var _0x1f2f2f = _0x3260a5['GokKo'](0x1, 0x2);
continue;
case '5':
console['log'](0x3);
continue;
case '6':
console['log'](0x2);
continue;
}
break;
}
};
}
_0x3bfc5c()();
}());
controlFlowFlatteningThreshold
Type: number Default: 0.75 Min: 0 Max: 1
Xác suất mà phép biến đổi controlFlowFlattening sẽ được áp dụng cho một node bất kỳ.
Cài đặt này đặc biệt hữu ích với mã có kích thước lớn, vì một lượng lớn phép biến đổi luồng điều khiển có thể làm chậm mã và tăng kích thước mã.
controlFlowFlatteningThreshold: 0 tương đương với controlFlowFlattening: false.
deadCodeInjection
Type: boolean Default: false
⚠️ Tăng đáng kể kích thước mã đã làm rối (lên tới 200%), chỉ dùng nếu kích thước mã đã làm rối không quan trọng. Dùng deadCodeInjectionThreshold để đặt phần trăm số node bị ảnh hưởng bởi việc chèn mã chết.
⚠️ Tùy chọn này buộc bật tùy chọn stringArray.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật.
Với tùy chọn này, các khối mã chết ngẫu nhiên sẽ được thêm vào mã đã làm rối.
Ví dụ:
// input
(function(){
if (true) {
var foo = function () {
console.log('abc');
};
var bar = function () {
console.log('def');
};
var baz = function () {
console.log('ghi');
};
var bark = function () {
console.log('jkl');
};
var hawk = function () {
console.log('mno');
};
foo();
bar();
baz();
bark();
hawk();
}
})();
// output
var _0x37b8 = [
'YBCtz',
'GlrkA',
'urPbb',
'abc',
'NMIhC',
'yZgAj',
'zrAId',
'EtyJA',
'log',
'mno',
'jkl',
'def',
'Quzya',
'IWbBa',
'ghi'
];
function _0x43a7(_0x12cf56, _0x587376) {
_0x43a7 = function (_0x2f87a8, _0x47eac2) {
_0x2f87a8 = _0x2f87a8 - (0x16a7 * 0x1 + 0x5 * 0x151 + -0x1c92);
var _0x341e03 = _0x37b8[_0x2f87a8];
return _0x341e03;
};
return _0x43a7(_0x12cf56, _0x587376);
}
(function () {
if (!![]) {
var _0xbbe28f = function () {
var _0x2fc85f = _0x43a7;
if (_0x2fc85f(0xaf) === _0x2fc85f(0xae)) {
_0x1dd94f[_0x2fc85f(0xb2)](_0x2fc85f(0xb5));
} else {
console[_0x2fc85f(0xb2)](_0x2fc85f(0xad));
}
};
var _0x5e46bc = function () {
var _0x15b472 = _0x43a7;
if (_0x15b472(0xb6) !== _0x15b472(0xaa)) {
console[_0x15b472(0xb2)](_0x15b472(0xb5));
} else {
_0x47eac2[_0x15b472(0xb2)](_0x15b472(0xad));
}
};
var _0x3669e8 = function () {
var _0x47a442 = _0x43a7;
if (_0x47a442(0xb7) !== _0x47a442(0xb0)) {
console[_0x47a442(0xb2)](_0x47a442(0xb8));
} else {
_0x24e0bf[_0x47a442(0xb2)](_0x47a442(0xb3));
}
};
var _0x28b05a = function () {
var _0x497902 = _0x43a7;
if (_0x497902(0xb1) === _0x497902(0xb1)) {
console[_0x497902(0xb2)](_0x497902(0xb4));
} else {
_0x59c9c6[_0x497902(0xb2)](_0x497902(0xb4));
}
};
var _0x402a54 = function () {
var _0x1906b7 = _0x43a7;
if (_0x1906b7(0xab) === _0x1906b7(0xac)) {
_0xb89cd0[_0x1906b7(0xb2)](_0x1906b7(0xb8));
} else {
console[_0x1906b7(0xb2)](_0x1906b7(0xb3));
}
};
_0xbbe28f();
_0x5e46bc();
_0x3669e8();
_0x28b05a();
_0x402a54();
}
}());
deadCodeInjectionThreshold
Type: number Default: 0.4 Min: 0 Max: 1
Cho phép đặt phần trăm số node sẽ bị ảnh hưởng bởi deadCodeInjection.
debugProtection
Type: boolean Default: false
⚠️ Có thể làm treo trình duyệt của bạn nếu bạn mở Developer Tools.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmDebugProtection thay thế.
Tùy chọn này khiến việc sử dụng chức năng debugger của Developer Tools gần như không thể (cả trên trình duyệt nền WebKit lẫn Mozilla Firefox).
debugProtectionInterval
Type: number Default: 0
⚠️ Có thể làm treo trình duyệt của bạn! Dùng và tự chịu rủi ro.
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmDebugProtection thay thế.
Nếu được đặt, một khoảng thời gian tính bằng mili giây sẽ được dùng để buộc chế độ gỡ lỗi trên tab Console, khiến việc sử dụng các tính năng khác của Developer Tools khó khăn hơn. Hoạt động nếu debugProtection được bật. Giá trị khuyến nghị nằm trong khoảng 2000 đến 4000 mili giây.
disableConsoleOutput
Type: boolean Default: false
⚠️ Tùy chọn này vô hiệu hóa các lệnh gọi console trên phạm vi toàn cục cho mọi script
Vô hiệu hóa việc sử dụng console.log, console.info, console.error, console.warn, console.debug, console.exception và console.trace bằng cách thay chúng bằng các hàm rỗng. Điều này khiến việc sử dụng trình gỡ lỗi khó khăn hơn.
domainLock
Type: string[] Default: []
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép mã nguồn đã làm rối chỉ chạy trên các tên miền và/hoặc tên miền phụ cụ thể. Điều này khiến việc ai đó chỉ sao chép và dán mã nguồn của bạn rồi chạy ở nơi khác trở nên rất khó khăn.
Nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi tùy chọn này, trình duyệt sẽ được chuyển hướng đến URL được truyền cho tùy chọn domainLockRedirectUrl.
Nhiều tên miền và tên miền phụ
Bạn có thể khóa mã của mình cho nhiều hơn một tên miền hoặc tên miền phụ. Ví dụ, để khóa sao cho mã chỉ chạy trên www.example.com, hãy thêm www.example.com. Để mã hoạt động trên tên miền gốc bao gồm mọi tên miền phụ (example.com, sub.example.com), hãy dùng .example.com.
domainLockRedirectUrl
Type: string Default: about:blank
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép chuyển hướng trình duyệt đến một URL được truyền vào nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi domainLock
exclude
Type: string[] Default: []
Danh sách tên tệp hoặc glob chỉ định các tệp cần loại trừ khỏi việc làm rối.
forceTransformStrings
Type: string[] Default: []
Bật việc buộc biến đổi các chuỗi ký tự khớp với các mẫu RegExp được truyền vào.
⚠️ Tùy chọn này chỉ ảnh hưởng đến những chuỗi lẽ ra không bị biến đổi bởi stringArrayThreshold (hoặc các ngưỡng khác có thể có trong tương lai)
Tùy chọn này có độ ưu tiên cao hơn tùy chọn reservedStrings nhưng không có độ ưu tiên cao hơn conditional comments.
Ví dụ:
{
forceTransformStrings: [
'some-important-value',
'some-string_\d'
]
}
identifierNamesCache
Type: Object | null Default: null
Mục tiêu chính của tùy chọn này là khả năng sử dụng cùng một tập tên định danh khi làm rối nhiều nguồn/tệp.
Hiện tại hai loại định danh được hỗ trợ:
- Định danh toàn cục:
- Tất cả định danh toàn cục sẽ được ghi vào cache;
- Tất cả định danh toàn cục chưa được khai báo khớp sẽ được thay bằng các giá trị từ cache.
- Định danh thuộc tính, chỉ khi tùy chọn
renamePropertiesđược bật:- Tất cả định danh thuộc tính sẽ được ghi vào cache;
- Tất cả định danh thuộc tính khớp sẽ được thay bằng các giá trị từ cache.
Node.js API
Nếu truyền giá trị null, cache sẽ bị vô hiệu hóa hoàn toàn.
Nếu truyền một đối tượng rỗng ({}), sẽ bật việc ghi tên định danh vào đối tượng cache (kiểu TIdentifierNamesCache). Đối tượng cache này được truy cập thông qua lệnh gọi phương thức getIdentifierNamesCache của đối tượng ObfuscationResult.
Đối tượng cache thu được sau đó có thể được dùng làm giá trị của tùy chọn identifierNamesGenerator để sử dụng các tên này khi làm rối tất cả các tên định danh khớp của các nguồn tiếp theo.
Ví dụ:
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo(arg) {
console.log(arg)
}
function bar() {
var bark = 2;
}
`,
{
compact: false,
identifierNamesCache: {},
renameGlobals: true
}
)
console.log(source1ObfuscationResult.getIdentifierNamesCache());
/*
{
globalIdentifiers: {
foo: '_0x5de86d',
bar: '_0x2a943b'
}
}
*/
const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
// Expecting that these global functions are defined in another obfuscated file
foo(1);
bar();
// Expecting that this global function is defined in third-party package
baz();
`,
{
compact: false,
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
renameGlobals: true
}
)
console.log(source2ObfuscationResult.getObfuscatedCode());
/*
_0x5de86d(0x1);
_0x2a943b();
baz();
*/
CLI
CLI có một tùy chọn khác --identifier-names-cache-path cho phép định nghĩa đường dẫn đến tệp .json hiện có sẽ được dùng để đọc và ghi cache tên định danh.
Nếu truyền đường dẫn đến một tệp rỗng - cache tên định danh sẽ được ghi vào tệp đó.
Tệp chứa cache hiện có này có thể được dùng lại làm giá trị của tùy chọn --identifier-names-cache-path để sử dụng các tên này khi làm rối tất cả các tên định danh khớp của các tệp tiếp theo.
identifierNamesGenerator
Type: string Default: hexadecimal
Đặt bộ tạo tên định danh.
Các giá trị có sẵn:
dictionary: tên định danh lấy từ danh sáchidentifiersDictionaryhexadecimal: tên định danh dạng_0xabc123mangled: tên định danh ngắn nhưa,b,cmangled-shuffled: giốngmanglednhưng với bảng chữ cái được xáo trộn
identifiersDictionary
Type: string[] Default: []
Đặt từ điển định danh cho tùy chọn identifierNamesGenerator: dictionary. Mỗi định danh trong từ điển sẽ được dùng ở một vài biến thể với cách viết hoa/thường khác nhau cho từng ký tự. Do đó, số lượng định danh trong từ điển nên phụ thuộc vào số lượng định danh trong mã nguồn gốc.
identifiersPrefix
Type: string Default: ''
Đặt tiền tố cho tất cả định danh toàn cục.
Dùng tùy chọn này khi bạn muốn làm rối nhiều tệp. Tùy chọn này giúp tránh xung đột giữa các định danh toàn cục của những tệp đó. Tiền tố nên khác nhau cho từng tệp.
randomIdentifiersPrefix
Type: boolean Default: false
Thêm một tiền tố ngẫu nhiên dựa trên seed (6 ký tự chữ và số) vào tất cả định danh toàn cục. Dùng tùy chọn này để tránh trùng lặp giữa các bundle được làm rối riêng lẻ nhưng được nạp vào cùng một phạm vi toàn cục — nó loại bỏ nhu cầu phải tự chọn một identifiersPrefix duy nhất cho từng bundle.
- Giá trị ngẫu nhiên được suy ra từ tùy chọn
seedvà hash của mã nguồn, nên các bản build có thể tái lập với cùng seed sẽ tạo ra cùng một tiền tố. - Khi kết hợp với
identifiersPrefix, các ký tự ngẫu nhiên được nối vào tiền tố do người dùng cung cấp (ví dụ:myApp+ ngẫu nhiênaBc123→myAppaBc123). - Khi kết hợp với
vmObfuscation, giá trị ngẫu nhiên thay thế tiền tốvmmặc định — tính ngẫu nhiên đã đảm bảo tính duy nhất.
ignoreImports
Type: boolean Default: false
Ngăn việc làm rối các import require. Có thể hữu ích trong một số trường hợp khi vì lý do nào đó môi trường khi chạy yêu cầu các import này chỉ với chuỗi tĩnh.
inputFileName
Type: string Default: ''
Cho phép đặt tên của tệp đầu vào chứa mã nguồn. Tên này sẽ được dùng nội bộ để tạo source map.
Bắt buộc khi dùng NodeJS API và tùy chọn sourceMapSourcesMode có giá trị sources.
log
Type: boolean Default: false
Bật việc ghi log thông tin ra console.
numbersToExpressions
Type: boolean Default: false
Bật việc chuyển đổi các số thành biểu thức
Ví dụ:
// input
const foo = 1234;
// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;
optionsPreset
Type: string Default: default
Cho phép đặt preset tùy chọn.
Các giá trị có sẵn:
vm-default;vm-low-obfuscation;vm-medium-obfuscation;vm-high-obfuscation;vm-ultra-high-obfuscation;vm-anti-llm;default;low-obfuscation;medium-obfuscation;high-obfuscation.
Tất cả tùy chọn bổ sung sẽ được gộp với preset tùy chọn đã chọn.
parseHtml
Type: boolean Default: false
Bật việc làm rối JavaScript bên trong các thẻ HTML <script>.
Khi được bật, trình làm rối sẽ:
- Tự động phát hiện đầu vào có phải là HTML hay không (bằng cách kiểm tra các thẻ
<!DOCTYPE,<html>,<head>,<body>, hoặc<script>) - Trích xuất JavaScript từ các thẻ
<script>được đánh dấu bằng thuộc tínhdata-javascript-obfuscator - Làm rối từng script được đánh dấu một cách riêng lẻ trong khi vẫn giữ nguyên cấu trúc HTML
- Chèn mã đã làm rối trở lại các vị trí ban đầu
Quan trọng: Chỉ các script có thuộc tính data-javascript-obfuscator mới được làm rối. Mỗi script được đánh dấu được làm rối một cách riêng lẻ và độc lập. Điều này có nghĩa là:
- Mã bên trong các thẻ script được đánh dấu phải được cô lập - nó KHÔNG được tham chiếu đến các biến, hàm hoặc lớp được định nghĩa trong các thẻ script được đánh dấu khác
- Các script không được đánh dấu vẫn có thể truy cập các biến toàn cục do các script được đánh dấu định nghĩa (qua khai báo
varhoặc gánglobalThistường minh) - Điều này cho bạn quyền kiểm soát tường minh những script nào cần bảo vệ
Được làm rối (phải có thuộc tính data-javascript-obfuscator):
<script data-javascript-obfuscator>- script thông thường<script type="text/javascript" data-javascript-obfuscator>- script có kiểu được khai báo tường minh- Các script có bất kỳ thuộc tính bổ sung nào (
id,class,data-*khác, v.v.)
Bị bỏ qua (giữ nguyên không đổi):
- Các script không có thuộc tính
data-javascript-obfuscator <script type="module">- ES module (kể cả khi có thuộc tính)<script src="...">- script bên ngoài (kể cả khi có thuộc tính)- Các thẻ script rỗng
Lưu ý: Source map không được tạo khi parseHtml được bật, vì chúng sẽ không ánh xạ chính xác tới đầu ra HTML.
Ví dụ:
// input
const html = `<!DOCTYPE html>
<html>
<body>
<!-- This script will NOT be obfuscated -->
<script>
var helper = 'utility';
</script>
<!-- This script WILL be obfuscated -->
<script data-javascript-obfuscator>
var greeting = 'Hello World';
console.log(greeting);
</script>
</body>
</html>`;
JavaScriptObfuscator.obfuscate(html, {
parseHtml: true,
stringArray: true
});
// output: HTML with only the marked script obfuscated
renameGlobals
Type: boolean Default: false
⚠️ tùy chọn này có thể làm hỏng mã của bạn. Chỉ bật nếu bạn biết nó làm gì!
Bật việc làm rối tên các biến và hàm toàn cục cùng với phần khai báo.
Khi tùy chọn này bị tắt và mã đầu vào khai báo các hàm hoặc lớp trong phạm vi toàn cục (tức là mã không được bọc trong một IIFE), tên của chúng được giữ nguyên trong mã đã làm rối — các script khác có thể tham chiếu đến chúng theo tên. Dưới vmObfuscation, một cảnh báo VMGlobalFunctionNamesNotRenamed liệt kê các tên này sẽ được báo cáo, vì thân hàm được ẩn dưới dạng bytecode nhưng tên cấp cao dễ đọc vẫn để lộ những gì mã đó làm (ví dụ cho một LLM). Để tránh việc lộ này, hãy bọc mã trong một IIFE hoặc bật tùy chọn này.
renameProperties
Type: boolean Default: false
⚠️ tùy chọn này CÓ THỂ làm hỏng mã của bạn. Chỉ bật nếu bạn biết nó làm gì!
Bật việc đổi tên các thuộc tính. Tất cả thuộc tính DOM dựng sẵn và thuộc tính trong các lớp JavaScript cốt lõi sẽ được bỏ qua.
Để chuyển đổi giữa chế độ safe và unsafe của tùy chọn này, dùng tùy chọn renamePropertiesMode.
Để đặt định dạng cho tên thuộc tính được đổi, dùng tùy chọn identifierNamesGenerator.
Để kiểm soát những thuộc tính nào sẽ được đổi tên, dùng tùy chọn reservedNames.
Ví dụ:
// input
(function () {
const foo = {
prop1: 1,
prop2: 2,
calc: function () {
return this.prop1 + this.prop2;
}
};
console.log(foo.calc());
})();
// output
(function () {
const _0x46529b = {
'_0x10cec7': 0x1,
'_0xc1c0ca': 0x2,
'_0x4b961d': function () {
return this['_0x10cec7'] + this['_0xc1c0ca'];
}
};
console['log'](_0x46529b['_0x4b961d']());
}());
renamePropertiesMode
Type: string Default: safe
⚠️ Ngay cả ở chế độ safe, tùy chọn renameProperties CÓ THỂ làm hỏng mã của bạn.
Chỉ định chế độ của tùy chọn renameProperties:
safe- hành vi mặc định sau bản phát hành2.11.0. Cố gắng đổi tên thuộc tính theo cách an toàn hơn để tránh lỗi khi chạy. Với chế độ này, một số thuộc tính sẽ được loại trừ khỏi việc đổi tên.unsafe- hành vi mặc định trước bản phát hành2.11.0. Đổi tên thuộc tính theo cách không an toàn mà không có bất kỳ hạn chế nào.
Nếu một tệp đang dùng các thuộc tính từ tệp khác, hãy dùng tùy chọn identifierNamesCache để giữ nguyên tên thuộc tính giữa các tệp này.
reservedNames
Type: string[] Default: []
Vô hiệu hóa việc làm rối và tạo các định danh khớp với các mẫu RegExp được truyền vào.
Ví dụ:
{
reservedNames: [
'^someVariable',
'functionParameter_\d'
]
}
reservedStrings
Type: string[] Default: []
Vô hiệu hóa việc biến đổi các chuỗi ký tự khớp với các mẫu RegExp được truyền vào. Các chuỗi khớp sẽ vẫn hiển thị trong mã đã làm rối.
Khi dùng làm rối VM, các chuỗi được dành riêng được lưu trong một mảng riêng không mã hóa để giữ chúng hiển thị. Điều này hữu ích cho những chuỗi phải giữ được khả năng đọc, chẳng hạn như các API endpoint để giám sát hoặc các định danh thư viện.
Ví dụ:
{
reservedStrings: [
'react-native',
'\.\/src\/test',
'some-string_\d'
]
}
seed
Type: string|number Default: 0
Tùy chọn này đặt seed cho bộ tạo số ngẫu nhiên. Điều này hữu ích để tạo ra các kết quả có thể lặp lại.
Nếu seed là 0 - bộ tạo số ngẫu nhiên sẽ hoạt động mà không có seed.
selfDefending
Type: boolean Default: false
⚠️ Đừng thay đổi mã đã làm rối theo bất kỳ cách nào sau khi làm rối với tùy chọn này, vì bất kỳ thay đổi nào như uglify mã đều có thể kích hoạt self defending và mã sẽ không còn hoạt động nữa!
⚠️ Tùy chọn này buộc đặt giá trị compact thành true
⚠️ Tùy chọn này bị vô hiệu hóa một cách âm thầm khi vmObfuscation được bật. Hãy dùng vmSelfDefending thay thế.
Tùy chọn này khiến mã đầu ra có khả năng chống lại việc định dạng lại và đổi tên biến. Nếu ai đó cố dùng một trình làm đẹp (beautifier) JavaScript trên mã đã làm rối, mã sẽ không còn hoạt động, khiến việc hiểu và chỉnh sửa nó khó khăn hơn.
simplify
Type: boolean Default: true
Bật thêm việc làm rối mã thông qua đơn giản hóa.
⚠️ ở các bản phát hành trong tương lai, việc làm rối các literal boolean (true => !![]) sẽ được chuyển vào tùy chọn này.
Ví dụ:
// input
if (condition1) {
const foo = 1;
const bar = 2;
console.log(foo);
return bar;
} else if (condition2) {
console.log(1);
console.log(2);
console.log(3);
return 4;
} else {
return 5;
}
// output
if (condition1) {
const foo = 0x1, bar = 0x2;
return console['log'](foo), bar;
} else
return condition2 ? (console['log'](0x1), console['log'](0x2), console['log'](0x3), 0x4) : 0x5;
sourceMap
Type: boolean Default: false
Bật việc tạo source map cho mã đã làm rối.
Source map có thể hữu ích để giúp bạn gỡ lỗi mã nguồn JavaScript đã làm rối. Nếu bạn muốn hoặc cần gỡ lỗi trong môi trường thực tế, bạn có thể tải tệp source map riêng lên một vị trí bí mật rồi trỏ trình duyệt đến đó.
sourceMapBaseUrl
Type: string Default: ``
Đặt base url cho url import của source map khi sourceMapMode: 'separate'.
Ví dụ CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'
Kết quả:
//# sourceMappingURL=http://localhost:9000/out.js.map
sourceMapFileName
Type: string Default: ``
Đặt tên tệp cho source map đầu ra khi sourceMapMode: 'separate'.
Ví dụ CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example
Kết quả:
//# sourceMappingURL=http://localhost:9000/example.js.map
sourceMapMode
Type: string Default: separate
Chỉ định chế độ tạo source map:
inline- thêm source map vào cuối mỗi tệp .js;separate- tạo tệp '.map' tương ứng chứa source map. Trong trường hợp bạn chạy trình làm rối qua CLI - thêm liên kết đến tệp source map vào cuối tệp mã đã làm rối//# sourceMappingUrl=file.js.map.
sourceMapSourcesMode
Type: string Default: sources-content
Cho phép kiểm soát các trường sources và sourcesContent của source map:
sources-content- thêm trườngsourcesgiả, thêm trườngsourcesContentchứa mã nguồn gốc;sources- thêm trườngsourcesvới mô tả nguồn hợp lệ, không thêm trườngsourcesContent. Khi dùng NodeJS API, bắt buộc phải định nghĩa tùy chọninputFileNamesẽ được dùng làm giá trị của trườngsources.
splitStrings
Type: boolean Default: false
Chia các chuỗi ký tự thành các đoạn (chunk) có độ dài bằng giá trị của tùy chọn splitStringsChunkLength.
Ví dụ:
// input
(function(){
var test = 'abcdefg';
})();
// output
(function(){
var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();
splitStringsChunkLength
Type: number Default: 10
Đặt độ dài đoạn (chunk) của tùy chọn splitStrings.
stringArray
Type: boolean Default: true
Loại bỏ các chuỗi ký tự và đặt chúng vào một mảng đặc biệt. Ví dụ, chuỗi "Hello World" trong var m = "Hello World"; sẽ được thay bằng thứ gì đó như var m = _0x12c456[0x1];
stringArrayCallsTransform
Type: boolean Default: false
⚠️ Tùy chọn stringArray phải được bật
Bật việc biến đổi các lệnh gọi đến stringArray. Tất cả đối số của các lệnh gọi này có thể được trích xuất ra một đối tượng khác tùy theo giá trị stringArrayCallsTransformThreshold.
Điều này khiến việc tự động tìm các lệnh gọi đến string array càng khó khăn hơn.
Ví dụ:
function foo() {
var k = {
c: 0x2f2,
d: '0x396',
e: '0x397',
f: '0x39a',
g: '0x39d',
h: 0x398,
l: 0x394,
m: '0x39b',
n: '0x39f',
o: 0x395,
p: 0x395,
q: 0x399,
r: '0x399'
};
var c = i(k.d, k.e);
var d = i(k.f, k.g);
var e = i(k.h, k.l);
var f = i(k.m, k.n);
function i(c, d) {
return b(c - k.c, d);
}
var g = i(k.o, k.p);
var h = i(k.q, k.r);
}
function j(c, d) {
var l = { c: 0x14b };
return b(c - -l.c, d);
}
console[j(-'0xa6', -'0xa6')](foo());
function b(c, d) {
var e = a();
b = function (f, g) {
f = f - 0xa3;
var h = e[f];
return h;
};
return b(c, d);
}
function a() {
var m = [
'string5',
'string1',
'log',
'string3',
'string6',
'string2',
'string4'
];
a = function () {
return m;
};
return a();
}
stringArrayCallsTransformThreshold
Type: number Default: 0.5
⚠️ Các tùy chọn stringArray và stringArrayCallsTransformThreshold phải được bật
Bạn có thể dùng cài đặt này để điều chỉnh xác suất (từ 0 đến 1) mà các lệnh gọi đến string array sẽ được biến đổi.
stringArrayEncoding
Type: string[] Default: []
⚠️ Tùy chọn stringArray phải được bật
Tùy chọn này có thể làm chậm script của bạn.
Mã hóa tất cả các chuỗi ký tự của stringArray bằng base64 hoặc rc4 và chèn một đoạn mã đặc biệt dùng để giải mã trở lại khi chạy.
Mỗi giá trị stringArray sẽ được mã hóa bằng kiểu mã hóa được chọn ngẫu nhiên từ danh sách được truyền vào. Điều này giúp có thể sử dụng nhiều kiểu mã hóa.
Các giá trị có sẵn:
'none'(boolean): không mã hóa giá trịstringArray'base64'(string): mã hóa giá trịstringArraybằngbase64'rc4'(string): mã hóa giá trịstringArraybằngrc4. Chậm hơnbase64khoảng 30-50%, nhưng khó lấy được giá trị ban đầu hơn.
Ví dụ, với các giá trị tùy chọn sau, một số giá trị stringArray sẽ không được mã hóa, và một số giá trị sẽ được mã hóa bằng base64 và rc4:
stringArrayEncoding: [
'none',
'base64',
'rc4'
]
stringArrayIndexesType
Type: string[] Default: ['hexadecimal-number']
⚠️ Tùy chọn stringArray phải được bật
Cho phép kiểm soát kiểu của các chỉ mục lệnh gọi string array.
Mỗi chỉ mục lệnh gọi stringArray sẽ được biến đổi bằng kiểu được chọn ngẫu nhiên từ danh sách được truyền vào. Điều này giúp có thể sử dụng nhiều kiểu.
Các giá trị có sẵn:
'hexadecimal-number'(default): biến đổi các chỉ mục lệnh gọi string array thành số thập lục phân'hexadecimal-numeric-string': biến đổi các chỉ mục lệnh gọi string array thành chuỗi số thập lục phân
Trước bản phát hành 2.9.0, javascript-obfuscator biến đổi tất cả các chỉ mục lệnh gọi string array bằng kiểu hexadecimal-numeric-string. Điều này khiến việc gỡ rối thủ công khó hơn một chút nhưng lại giúp các công cụ gỡ rối tự động dễ phát hiện các lệnh gọi này.
Kiểu hexadecimal-number mới hướng tới việc khiến việc tự động phát hiện các mẫu lệnh gọi string array trong mã khó khăn hơn.
Nhiều kiểu hơn sẽ được bổ sung trong tương lai.
stringArrayIndexShift
Type: boolean Default: true
⚠️ Tùy chọn stringArray phải được bật
Bật việc dịch chỉ mục bổ sung cho tất cả các lệnh gọi string array
stringArrayRotate
Type: boolean Default: true
⚠️ stringArray phải được bật
Dịch chuyển mảng stringArray đi một số vị trí cố định và ngẫu nhiên (được tạo lúc làm rối mã). Điều này khiến việc khớp thứ tự của các chuỗi đã bị loại bỏ với vị trí gốc của chúng khó khăn hơn.
stringArrayShuffle
Type: boolean Default: true
⚠️ stringArray phải được bật
Xáo trộn ngẫu nhiên các phần tử của mảng stringArray.
stringArrayWrappersCount
Type: number Default: 1
⚠️ Tùy chọn stringArray phải được bật
Đặt số lượng wrapper cho string array bên trong mỗi phạm vi gốc hoặc phạm vi hàm.
Số lượng wrapper thực tế bên trong mỗi phạm vi bị giới hạn bởi số lượng node literal trong phạm vi đó.
Ví dụ:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
const hawk = 'hawk';
}
const eagle = 'eagle';
// Output, stringArrayWrappersCount: 5
const _0x3f6c = [
'bark',
'bar',
'foo',
'eagle',
'hawk',
'baz'
];
const _0x48f96e = _0x2e13;
const _0x4dfed8 = _0x2e13;
const _0x55e970 = _0x2e13;
function _0x2e13(_0x33c4f5, _0x3f6c62) {
_0x2e13 = function (_0x2e1388, _0x60b1e) {
_0x2e1388 = _0x2e1388 - 0xe2;
let _0x53d475 = _0x3f6c[_0x2e1388];
return _0x53d475;
};
return _0x2e13(_0x33c4f5, _0x3f6c62);
}
const foo = _0x48f96e(0xe4);
const bar = _0x4dfed8(0xe3);
function test() {
const _0x1c262f = _0x2e13;
const _0x54d7a4 = _0x2e13;
const _0x5142fe = _0x2e13;
const _0x1392b0 = _0x1c262f(0xe7);
const _0x201a58 = _0x1c262f(0xe2);
const _0xd3a7fb = _0x1c262f(0xe6);
}
const eagle = _0x48f96e(0xe5);
stringArrayWrappersChainedCalls
Type: boolean Default: true
⚠️ Các tùy chọn stringArray và stringArrayWrappersCount phải được bật
Bật các lệnh gọi chuỗi (chained calls) giữa các wrapper của string array.
Ví dụ:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
function test1() {
const hawk = 'hawk';
const eagle = 'eagle';
}
}
// Output, stringArrayWrappersCount: 5, stringArrayWrappersChainedCalls: true
const _0x40c2 = [
'bar',
'bark',
'hawk',
'eagle',
'foo',
'baz'
];
const _0x31c087 = _0x3280;
const _0x31759a = _0x3280;
function _0x3280(_0x1f52ee, _0x40c2a2) {
_0x3280 = function (_0x3280a4, _0xf07b02) {
_0x3280a4 = _0x3280a4 - 0x1c4;
let _0x57a182 = _0x40c2[_0x3280a4];
return _0x57a182;
};
return _0x3280(_0x1f52ee, _0x40c2a2);
}
const foo = _0x31c087(0x1c8);
const bar = _0x31c087(0x1c4);
function test() {
const _0x848719 = _0x31759a;
const _0x2693bf = _0x31c087;
const _0x2c08e8 = _0x848719(0x1c9);
const _0x359365 = _0x2693bf(0x1c5);
function _0x175e90() {
const _0x310023 = _0x848719;
const _0x2302ef = _0x2693bf;
const _0x237437 = _0x310023(0x1c6);
const _0x56145c = _0x310023(0x1c7);
}
}
stringArrayWrappersParametersMaxCount
Type: number Default: 2
⚠️ Tùy chọn stringArray phải được bật
⚠️ Hiện tại tùy chọn này chỉ ảnh hưởng đến các wrapper được thêm bởi giá trị function của tùy chọn stringArrayWrappersType
Cho phép kiểm soát số lượng tham số tối đa của các wrapper string array.
Giá trị mặc định và tối thiểu là 2. Giá trị khuyến nghị nằm trong khoảng 2 đến 5.
stringArrayWrappersType
Type: string Default: variable
⚠️ Các tùy chọn stringArray và stringArrayWrappersCount phải được bật
Cho phép chọn kiểu wrapper được thêm bởi tùy chọn stringArrayWrappersCount.
Các giá trị có sẵn:
'variable': thêm wrapper dạng biến ở đầu mỗi phạm vi. Hiệu năng nhanh.'function': thêm wrapper dạng hàm ở các vị trí ngẫu nhiên bên trong mỗi phạm vi. Hiệu năng chậm hơn so vớivariablenhưng cung cấp mức làm rối chặt chẽ hơn.
Rất khuyến nghị dùng wrapper function để làm rối mạnh hơn khi việc mất hiệu năng không gây ảnh hưởng lớn đến ứng dụng đã làm rối.
Ví dụ về giá trị tùy chọn 'function':
// input
const foo = 'foo';
function test () {
const bar = 'bar';
console.log(foo, bar);
}
test();
// output
const a = [
'log',
'bar',
'foo'
];
const foo = d(0x567, 0x568);
function b(c, d) {
b = function (e, f) {
e = e - 0x185;
let g = a[e];
return g;
};
return b(c, d);
}
function test() {
const c = e(0x51c, 0x51b);
function e (c, g) {
return b(c - 0x396, g);
}
console[f(0x51b, 0x51d)](foo, c);
function f (c, g) {
return b(c - 0x396, g);
}
}
function d (c, g) {
return b(g - 0x3e1, c);
}
test();
stringArrayThreshold
Type: number Default: 0.8 Min: 0 Max: 1
⚠️ Tùy chọn stringArray phải được bật
Bạn có thể dùng cài đặt này để điều chỉnh xác suất (từ 0 đến 1) mà một chuỗi ký tự sẽ được đưa vào stringArray.
Cài đặt này đặc biệt hữu ích với mã có kích thước lớn vì nó gọi đến string array nhiều lần và có thể làm chậm mã của bạn.
stringArrayThreshold: 0 tương đương với stringArray: false.
strictMode
Type: boolean | null Default: null
Cho phép chỉ định cách trình làm rối nên xử lý mã liên quan đến chế độ strict của JavaScript.
Các giá trị có sẵn:
null(mặc định) - tự động phát hiện chế độ strict từ mã. Nếu mã có chỉ thị'use strict'tường minh, cú pháp ES module, hoặc phương thức lớp, nó được xem là chế độ strict. Ngược lại, chế độ sloppy được giả định.true- buộc xử lý theo chế độ strict cho toàn bộ mã, ngay cả khi không có chỉ thị'use strict'tường minh. Dùng giá trị này khi mã của bạn sẽ chạy trong ngữ cảnh chế độ strict (ví dụ: trong ES module, bundler, hoặc các framework hiện đại).false- chỉ những dấu hiệu chế độ strict tường minh ('use strict', ES module, phương thức lớp) mới được xem là strict. Việc kế thừa từ phạm vi cha vẫn áp dụng theo đặc tả JS.
target
Type: string Default: browser
Cho phép đặt môi trường mục tiêu cho mã đã làm rối.
Các giá trị có sẵn:
browser(mặc định) — môi trường trang web tiêu chuẩn. Mã đầu ra giống hệt vớinode, nhưng một số tùy chọn dành riêng cho trình duyệt không được phép dùng với mục tiêunodebrowser-no-eval— giốngbrowser, nhưng đầu ra không dùngeval(). Dùng khi trang mục tiêu có Content Security Policy cấmeval/unsafe-eval.node— môi trường Node.js. Các tùy chọn dành riêng cho trình duyệt bị vô hiệu hóa (chúng cầnwindow/documentvà sẽ không làm gì hoặc ném lỗi trong Node). Một số biện pháp phòng thủvmSelfDefendingdựa trên các API chỉ có ở trình duyệt — phát hiện trình duyệt headless, khôi phục realm sạch dựa trên iframe, kiểm tra chống inspector/DOM — không được phát ra cho mục tiêu này.service-worker— ngữ cảnh Service Worker. Không cówindow, không códocument, biến toàn cụcselfkhác.userscript— sandbox của trình quản lý userscript (ví dụ Tampermonkey). Các biện pháp phòng thủvmSelfDefendingđược điều chỉnh tương ứng.bytenode— mã Node.js sẽ được biên dịch bằng bộ nạp bytenode (bytecode được V8 cache.jsc) sau khi làm rối. Bản thân trình làm rối không gọibytenode; nó phát ra JavaScript đã làm rối VM có runtime được cấu trúc để vượt qua bước biên dịch của bytenode, và các biện pháp phòng thủvmSelfDefendingđược điều chỉnh tương ứng. Hãy tự chạybytenodetrên đầu ra đã làm rối để tạo ra tệp.jsccuối cùng.
transformObjectKeys
Type: boolean Default: false
Bật việc biến đổi các khóa của đối tượng.
Ví dụ:
// input
(function(){
var object = {
foo: 'test1',
bar: {
baz: 'test2'
}
};
})();
// output
var _0x4735 = [
'foo',
'baz',
'bar',
'test1',
'test2'
];
function _0x390c(_0x33d6b6, _0x4735f4) {
_0x390c = function (_0x390c37, _0x1eed85) {
_0x390c37 = _0x390c37 - 0x198;
var _0x2275f8 = _0x4735[_0x390c37];
return _0x2275f8;
};
return _0x390c(_0x33d6b6, _0x4735f4);
}
(function () {
var _0x17d1b7 = _0x390c;
var _0xc9b6bb = {};
_0xc9b6bb[_0x17d1b7(0x199)] = _0x17d1b7(0x19c);
var _0x3d959a = {};
_0x3d959a[_0x17d1b7(0x198)] = _0x17d1b7(0x19b);
_0x3d959a[_0x17d1b7(0x19a)] = _0xc9b6bb;
var _0x41fd86 = _0x3d959a;
}());
warnings
Type: string | object Default: all
Kiểm soát những cảnh báo làm rối không nghiêm trọng nào được phát ra thông qua phương thức ObfuscationResult.getWarnings().
Các giá trị có sẵn:
'all'(mặc định) — mọi cảnh báo đều được phát ra.'none'— tất cả cảnh báo đều bị chặn.- một đối tượng ánh xạ các loại cảnh báo sang giá trị boolean — một loại được ánh xạ thành
falsesẽ bị chặn; mọi loại không có mặt (hoặc được ánh xạ thànhtrue) vẫn được bật. Ví dụ,{ "VMGlobalFunctionNamesNotRenamed": false }giữ mọi cảnh báo ngoại trừ cảnh báo đó.
Các loại cảnh báo:
VMGlobalFunctionNamesNotRenamed— dướivmObfuscation, tên của các khai báo hàm cấp cao, khai báo lớp, và các biến được gán một biểu thức hàm/mũi tên/lớp được giữ nguyên (tùy chọnrenameGlobalsbị tắt và mã không được bọc trong một IIFE), nên chúng vẫn dễ đọc trong đầu ra dù thân hàm được ẩn dưới dạng bytecode. Các tên được export không được báo cáo.VMTopLevelInitializerNotVirtualized— các bộ khởi tạo biến cấp cao vẫn nằm ở dạng JavaScript thuần dưới làm rối VM vìvmWrapTopLevelInitializersbị tắt hoặc không thể ảo hóa chúng.DynamicCodeRenameRisk— mã xây dựng một hàm từ một chuỗi khi chạy (directeval, hàm dựngFunction, hoặcfn.toString()được chèn vào một<script>/Worker), điều này có thể tham chiếu đến các định danh mà trình làm rối đã đổi tên.VMDynamicCodeSkipped— một hàm bị bỏ qua khỏi việc dịch bytecode VM vì nó chứa directeval/new Functionđộng /Function(xemvmForceCompileDynamicCode).VMSyncFunctionSkippedInAsyncMode— khivmAsyncExecutorđược bật, một hàm bạn đánh dấu tường minh ở chế độcommenthóa ra lại là đồng bộ và đã bị bỏ qua (chỉ các hàm async mới được ảo hóa ở chế độ đó).VMAsyncGeneratorSkippedInAsyncMode— khivmAsyncExecutorvà một async key getter đang hoạt động, một async generator được đánh dấu không thể được ảo hóa (nó phải trả về iterator của mình một cách đồng bộ).BrowserTargetWithNodeStyleCode— mã trông như nhắm tới Node.js (ví dụrequire('fs'),__dirname,process.argv) trong khi tùy chọntargetđược đặt thành một môi trường giống trình duyệt.
vmObfuscation
Type: boolean Default: false
Bật làm rối bytecode dựa trên VM. Khi được bật, các hàm JavaScript được biên dịch thành bytecode tùy chỉnh chạy trên một máy ảo nhúng. Điều này cung cấp mức bảo vệ cao nhất vì logic mã gốc được biến đổi hoàn toàn.
Ví dụ:
Mã dễ đọc của bạn như return qty * price trở thành một danh sách các số như [0x15,0x03,0x17,...] mà chỉ trình thông dịch VM nhúng mới có thể thực thi. Logic gốc không còn hiển thị dưới dạng JavaScript nữa.
vmTargetFunctions
Type: string[] Default: []
Chỉ định chính xác theo tên những hàm cấp gốc nào sẽ được bảo vệ bằng VM.
Ví dụ:
{
vmObfuscation: true,
vmTargetFunctions: ['someFunctionName']
}
Kết quả: Chỉ ba hàm này được bảo vệ bằng VM. Mọi thứ còn lại vẫn là JavaScript thông thường (nhưng vẫn được làm rối). Hoàn hảo để bảo vệ các đoạn kiểm tra giấy phép nhạy cảm hoặc logic xác thực trong khi giữ phần còn lại của mã gọn nhẹ.
vmExcludeFunctions
Type: string[] Default: []
Chỉ định những hàm cấp gốc không bao giờ được bảo vệ bằng VM. Có độ ưu tiên cao hơn các cài đặt khác.
Ví dụ:
{
vmObfuscation: true,
vmExcludeFunctions: ['someFunctionName']
}
Khi nào dùng: Các hàm cấp gốc quan trọng về hiệu năng (vòng lặp animation, xử lý dữ liệu thời gian thực) có thể được loại trừ để tránh chi phí phụ trội của VM trong khi vẫn bảo vệ mọi thứ còn lại.
vmTargetFunctionsMode
Type: string Default: root
Kiểm soát cách các hàm/phương thức được chọn để làm rối VM.
Ví dụ - Chế độ comment:
// Source code
function regularFunction() {
return 'not virtualized';
}
/* javascript-obfuscator:vm */
function sensitiveFunction() {
return 'this will be VM-protected';
}
function outer() {
/* javascript-obfuscator:vm */
function nestedSensitive() {
return 'nested but still VM-protected';
}
return nestedSensitive();
}
// Obfuscator options
{
vmObfuscation: true,
vmTargetFunctionsMode: 'comment'
}
Khi nào dùng: Khi bạn cần kiểm soát chính xác đến từng chi tiết những hàm nào được bảo vệ bằng VM, đặc biệt là các hàm lồng nhau chứa logic nhạy cảm. Không giống vmTargetFunctions vốn chỉ hoạt động với các hàm có tên ở cấp gốc, chế độ comment cho phép bạn bảo vệ bất kỳ hàm nào ở bất cứ đâu trong mã.
vmForceCompileDynamicCode
Type: boolean Default: false
Kiểm soát điều mà làm rối VM thực hiện với một hàm chứa lệnh gọi direct eval, new Function(...), hoặc Function(...).
Theo mặc định, một hàm như vậy (và mọi hàm được định nghĩa bên trong nó) bị bỏ qua khỏi việc dịch bytecode VM và một cảnh báo VMDynamicCodeSkipped được báo cáo trong result.getWarnings(). Điều này là vì mã nguồn được dựng khi chạy có thể tham chiếu đến các định danh từ chuỗi phạm vi xung quanh — những định danh mà trình làm rối đã đổi tên.
Khi được đặt thành true, hàm vẫn được dịch thành bytecode và cảnh báo VMDynamicCodeSkipped không còn được phát ra nữa.
Cảnh báo riêng DynamicCodeRenameRisk vẫn tiếp tục kích hoạt bất kể tùy chọn này, vì rủi ro đổi tên mà nó mô tả là độc lập với việc bỏ qua VM — bật tùy chọn này không khiến mẫu bên dưới an toàn hơn chút nào.
// Source code
function loadConfig(src) {
return eval(src);
}
loadConfig('1 + 2');
// Options
{
vmObfuscation: true,
vmForceCompileDynamicCode: true
}
Khi tùy chọn tắt (mặc định), loadConfig được giữ nguyên ở dạng JavaScript thuần. Khi tùy chọn bật, loadConfig được biên dịch thành bytecode VM như bất kỳ hàm nào khác. Dùng tùy chọn này khi bạn đã kiểm tra kỹ điểm gọi và biết chắc mã được dựng khi chạy không phụ thuộc vào các định danh đã bị đổi tên trong closure.
vmWrapTopLevelInitializers
Type: boolean Default: false
Bọc một số bộ khởi tạo biến cấp cao trong các IIFE (Biểu thức hàm được gọi ngay lập tức) để chúng có thể được làm rối VM.
Nó làm gì: Nếu không có tùy chọn này, các hằng và biến cấp cao vẫn hiển thị trong đầu ra:
// Input
const MY_STRING = "my-string";
// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string"; // String is visible!
Khi tùy chọn này được bật, bộ khởi tạo được bọc trong một IIFE và được làm rối VM:
// Input
const MY_STRING = "my-string";
// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })(); // String hidden in bytecode
Lưu ý: Tùy chọn này chỉ hoạt động khi vmTargetFunctionsMode là 'root' (giá trị mặc định).
Cảnh báo: Bất cứ khi nào một bộ khởi tạo cấp cao rốt cuộc nằm ở dạng JavaScript thuần dưới làm rối VM, một cảnh báo VMTopLevelInitializerNotVirtualized liệt kê tên các biến bị ảnh hưởng sẽ được báo cáo. Điều đó bao gồm: tùy chọn này bị tắt, các bộ khởi tạo mà tùy chọn này phải bỏ qua (mỗi cái kèm theo lý do — ví dụ bộ khởi tạo tham chiếu đến một declarator anh em hoặc chứa top-level await), và chế độ vmAsyncExecutor nơi các wrapper đồng bộ hoàn toàn không thể được ảo hóa.
vmDynamicOpcodes
Type: boolean Default: false
Làm cho trình thông dịch VM nhỏ hơn và khác biệt với mỗi bản build.
Nó làm gì:
- Lọc bỏ các lệnh không dùng đến - Nếu mã của bạn không dùng lớp, các lệnh liên quan đến lớp sẽ bị loại bỏ hoàn toàn
- Ngẫu nhiên hóa cấu trúc - Thứ tự của các trình xử lý lệnh được xáo trộn ở mỗi bản build
Kết quả là - đầu ra nhỏ hơn và mỗi bản build trông khác nhau.
vmBytecodeEncoding
Type: boolean Default: false
Mã hóa từng lệnh bytecode. Các lệnh được giải mã từng cái một trong quá trình thực thi.
vmBytecodeArrayEncoding
Type: boolean Default: false
Mã hóa toàn bộ mảng bytecode như một khối duy nhất. Mảng được giải mã một lần lúc khởi động trước khi việc thực thi bắt đầu. Dùng cùng với vmBytecodeEncoding để có hai lớp bảo vệ.
vmBytecodeArrayEncodingKey
Type: string Default: ''
Khóa mã hóa tùy chỉnh cho việc mã hóa mảng bytecode. Khi được đặt, khóa này được dùng thay cho khóa mặc định suy ra từ môi trường. Khóa phải được cung cấp khi chạy thông qua vmBytecodeArrayEncodingKeyGetter.
Tùy chọn này đưa khóa mã hóa ra bên ngoài - nó không được nhúng vào chính mã đã làm rối. Dù khóa vẫn có thể truy cập được khi chạy (và do đó không thực sự bí mật), sự tách biệt này ngăn các công cụ phân tích tĩnh tìm ra khóa chỉ bằng cách xem xét mã.
Quan trọng: Khóa phải có sẵn một cách đồng bộ khi mã đã làm rối được nạp. Hãy dùng các kho lưu trữ đồng bộ như cookie, localStorage, sessionStorage, biến toàn cục, hoặc phần tử DOM (ví dụ các thẻ meta do máy chủ chèn vào). Các phương thức bất đồng bộ như fetch() không thể được dùng trực tiếp trong biểu thức key getter.
vmBytecodeArrayEncodingKeyGetter
Type: string Default: ''
Biểu thức JavaScript đồng bộ trả về khóa mã hóa khi chạy. Biểu thức này được ước lượng khi mã đã làm rối được nạp, và phải trả về đúng khóa đã được cung cấp trong vmBytecodeArrayEncodingKey. Để giải quyết khóa một cách bất đồng bộ (một Promise), hãy bật vmAsyncExecutor.
Lưu ý: một getter trả về Promise yêu cầu vmAsyncExecutor. Điều này không thể được kiểm tra lúc build, nên một getter Promise với vmAsyncExecutor tắt sẽ thất bại khi chạy — bộ giải mã nhận được Promise thay vì khóa.
Mã đã làm rối chỉ hoạt động khi key getter trả về đúng khóa đã được dùng trong quá trình làm rối. Nếu các khóa không khớp, việc giải mã sẽ thất bại và mã sẽ tạo ra rác hoặc lỗi. Nếu key getter trả về undefined, null, hoặc một chuỗi rỗng, mã sẽ ném ra một lỗi: "VM decryption key not available".
Quan trọng: Giữ khóa ở ngoài cùng tệp/script với mã đã làm rối — việc nhúng nó ngay đó cho phép ngay cả một lần quét tĩnh thuần túy trên bundle cũng khôi phục được nó. Thay vào đó hãy lưu nó ở một nguồn riêng: cookie do máy chủ đặt, localStorage được một script khác điền vào, một thẻ meta HTML do máy chủ chèn vào, một biến toàn cục do một script khác đặt, hoặc (với vmAsyncExecutor) được lấy từ backend của bạn khi chạy.
Khi khóa được lấy từ backend của bạn (qua vmAsyncExecutor), hãy thêm các kiểm tra dựa trên phiên hoặc dựa trên origin trên endpoint đó: trả về khóa đúng cho người dùng thật (phiên hợp lệ, Origin/Referer như mong đợi) và một khóa rác cho các yêu cầu đáng ngờ (ví dụ một origin localhost/không mong đợi, không có phiên). Người dùng thật chạy bình thường; một bản sao chạy bên ngoài môi trường của bạn nhận được một khóa giải mã ra thứ vô nghĩa. Logic cụ thể tùy thuộc vào trang web của bạn.
Ví dụ:
// From cookie
vmBytecodeArrayEncodingKeyGetter: "document.cookie.match(/vmKey=([^;]+)/)?.[1]"
// From localStorage
vmBytecodeArrayEncodingKeyGetter: "localStorage.getItem('vmKey')"
// From global variable
vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__"
// From meta tag (server-injected)
vmBytecodeArrayEncodingKeyGetter: "document.querySelector('meta[name=\"vm-key\"]').content"
// From nested object
vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"
// From backend, async (requires vmAsyncExecutor)
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
Ví dụ sử dụng:
// Build time
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
});
// Runtime - key must be set before obfuscated code runs
window.__VM_KEY__ = 'mySecretKey123';
vmAsyncExecutor
Type: boolean Default: false
Bật executor VM bất đồng bộ, cho phép vmBytecodeArrayEncodingKeyGetter trả về một Promise (một key getter bất đồng bộ) — nhờ đó khóa giải mã có thể được lấy khi chạy (yêu cầu mạng, IndexedDB, v.v.) thay vì phải có sẵn một cách đồng bộ khi mã được nạp.
Rất được khuyến nghị cho các codebase bất đồng bộ hoàn toàn. Ở chế độ này chỉ các hàm async mới được ảo hóa — một hàm đồng bộ không thể biến thành async mà không biến giá trị trả về của nó thành Promise và làm hỏng những nơi gọi nó — nên mã async xuyên suốt sẽ đạt độ bao phủ cao nhất. Nó vẫn hoạt động khi phần gốc là đồng bộ (ví dụ một IIFE / wrapper UMD đồng bộ): các hàm async ngoài cùng bên trong được bảo vệ, còn các phần đồng bộ được giữ nguyên.
Những gì được biến đổi: mọi hàm async ngoài cùng, dù xuất hiện ở đâu (kể cả lồng bên trong các wrapper đồng bộ). Hàm async ngoài cùng trong mỗi chuỗi là đơn vị được bảo vệ — mọi thứ bên trong nó, dù đồng bộ hay bất đồng bộ, đều được biên dịch vào. Các hàm đồng bộ và generator thường được giữ nguyên không làm rối.
function foo() { // sync — left as-is
function bar() {} // sync — left as-is
async function baz() { // transformed
// any code here, including calls to other async or sync functions
}
async function bark() { // transformed
// any code here, including calls to other async or sync functions
}
}
Bỏ qua và cảnh báo. Các async generator cũng được giữ nguyên không làm rối khi một async key getter đang hoạt động (một async generator phải trả về iterator của mình một cách đồng bộ và không thể chờ khóa). Ở chế độ mặc định vmTargetFunctionsMode: 'root' việc bỏ qua diễn ra âm thầm (việc chọn là tự động); ở chế độ comment, một cảnh báo được phát ra qua ObfuscationResult.getWarnings() bất cứ khi nào một hàm bạn đánh dấu tường minh không thể được ảo hóa — hóa ra nó đồng bộ, hoặc nó là một async generator dưới một async key getter.
Async key getter còn yêu cầu thêm vmBytecodeArrayEncoding cùng với một vmBytecodeArrayEncodingKeyGetter.
Ví dụ sử dụng:
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmAsyncExecutor: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
// the key getter may now return a Promise
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
});
vmJumpsEncoding
Type: boolean Default: false
Mã hóa các đích nhảy trong bytecode. Các offset nhảy được tính khi chạy, ẩn cấu trúc luồng điều khiển (if/else, vòng lặp, v.v.) khỏi phân tích tĩnh.
vmMacroOps
Type: boolean Default: false
Kết hợp các chuỗi lệnh phổ biến thành các opcode "macro" đơn lẻ. Ví dụ, LOAD + ADD + STORE có thể trở thành một lệnh MACRO_ADD_TO_VAR duy nhất. Điều này phá vỡ việc nhận dạng mẫu và có thể cải thiện hiệu năng.
vmDebugProtection
Type: boolean Default: false
Thêm các biện pháp phòng thủ nhiều lớp chống gỡ lỗi, chống phân tích và chống LLM vào runtime của VM. Hoạt động tốt nhất với các mục tiêu browser/browser-no-eval.
vmSelfDefending
Type: boolean Default: false
Thêm bảo vệ nhiều lớp chống can thiệp, chống hooking và chống dịch ngược vào runtime của VM.
⚠️ Tùy chọn này buộc bật vmBytecodeArrayEncoding.
⚠️ Phát hiện môi trường nhạy cảm. Tùy chọn này ràng buộc mã đã làm rối với môi trường runtime mục tiêu của nó và dùng kỹ thuật fingerprint trình duyệt nâng cao để phát hiện các công cụ tự động hóa. Mã được bảo vệ bằng tùy chọn này sẽ cố ý hỏng khi chạy trong:
- Trình duyệt headless (Chrome/Chromium headless, PhantomJS)
- Công cụ tự động hóa trình duyệt (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
- Node.js (khi
targetđược đặt thànhbrowser) - jsdom hoặc các bản mô phỏng DOM phía máy chủ tương tự
- Các môi trường mà các builtin gốc của trình duyệt đã bị hook hoặc thay thế
Mã sẽ hoạt động đúng trong các trình duyệt thông thường (Chrome, Firefox, Safari, Edge), kể cả khi được nạp bên trong iframe, tiện ích mở rộng trình duyệt (content script), và Web Worker. Nếu bạn cần chạy kiểm thử tự động trên mã được bảo vệ, hãy tắt vmSelfDefending cho các bản build kiểm thử — tùy chọn này được thiết kế để ngăn phân tích tự động và không thể được dùng an toàn với bất kỳ framework tự động hóa nào.
Rất khuyến nghị dùng cùng với vmDebugProtection, vmBytecodeArrayEncodingKey, và vmBytecodeArrayEncodingKeyGetter.
vmDefenseHook
Type: { name: string, aliases?: object } Default: ''
vmDefenseHook nhận một đối tượng với hai khóa: name (bắt buộc) và aliases (không bắt buộc).
name là một hàm toàn cục mà trang chủ của bạn định nghĩa và được một biện pháp phòng thủ VM (vmDebugProtection / vmSelfDefending) gọi với một đối tượng tín hiệu khi nó phát hiện một tín hiệu thù địch — một trình gỡ lỗi hoặc inspector, một trình duyệt headless / tự động hóa, một tiến trình AI-coding-agent, một tên miền không được phép, v.v. Dùng nó để báo cáo sự kiện về backend của bạn (ví dụ navigator.sendBeacon). Hook là một điểm thu telemetry thuần túy: giá trị trả về của nó bị bỏ qua, và một hook thiếu hoặc ném lỗi là một no-op âm thầm không bao giờ có thể vô hiệu hóa một biện pháp phòng thủ. Để thay đổi điều mà một biện pháp phòng thủ làm khi phát hiện, hãy dùng vmDefenseReaction.
aliases tùy chọn đổi tên các trường của đối tượng tín hiệu đó — được trình bày ở phần Đổi tên các trường tín hiệu bên dưới.
Đối tượng tín hiệu. Hook nhận một signal duy nhất:
source— bộ phát hiện cụ thể đã kích hoạt (xem bảng).category— nhóm mà nó báo cáo dưới đó:automation(trình duyệt không phải con người),debugger(một trình gỡ lỗi/inspector đang hoạt động),sandbox(host bị đo đạc/giả),domain(vi phạm domain-lock),tamper(các builtin bị vá khi chạy), hoặcintegrity(mã của chính VM bị thay đổi).score/threshold— bộ phát hiện đã kích hoạt mạnh đến mức nào và giá trị mà nó phải đạt tới; hook chỉ kích hoạt khiscore >= threshold. Hầu hết các kiểm tra là được-ăn-cả-ngã-về-không (một tín hiệu quyết định duy nhất);headlesscộng gộp nhiều tín hiệu về hình dạng trình duyệt, nênscorecủa nó thường cao hơnthresholdcủa nó.
Đăng ký hook. Định nghĩa nó như một biến toàn cục thuần túy trước khi bundle đã làm rối được nạp — runtime của VM và các biện pháp phòng thủ của nó chạy trước chương trình (được bảo vệ) của bạn, nên nhiều phát hiện kích hoạt trong quá trình khởi động:
// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }
Một hook được định nghĩa bên trong mã nguồn đã làm rối được đăng ký quá muộn để bắt được các phát hiện lúc khởi động, và nếu nó bị biên dịch VM thì không thể tiếp cận được cho đến khi chương trình của bạn chạy. Dù thế nào nó vẫn được giữ an toàn (một hook thiếu sẽ no-op, và một cơ chế bảo vệ chống tái nhập ngăn mọi tình huống mất kiểm soát), nhưng để có độ bao phủ hoàn chỉnh hãy đăng ký nó từ đầu. Để vẫn bảo vệ logic báo cáo của bạn, hãy giữ hook đã đăng ký là một bộ đệm một dòng ((window.__vmDet = window.__vmDet || []).push(signal)) và đọc/gửi bộ đệm đó từ mã đã làm rối của bạn.
Đổi tên các trường tín hiệu (aliases). Các giá trị source/category mặc định là những tên mang tính mô tả, nên bất kỳ ai đo đạc callback (hoặc đọc đầu ra) đều có thể nhận ra cơ chế bảo vệ và bộ phát hiện nào đã kích hoạt. aliases đổi tên các trường tín hiệu thành các token mờ đục do bạn chọn, được áp dụng bên trong VM trước khi tín hiệu được phát ra, nên những tên đó không bao giờ xuất hiện trong đầu ra hoặc đến được callback. Ứng dụng của bạn biết ánh xạ của riêng nó và chuyển tiếp các token đến backend của bạn.
Aliases áp dụng theo từng trường, giữ việc đổi tên khóa và giá trị tách biệt: mỗi trường nhận một key (tên thuộc tính mà callback nhận được); các trường tên dạng chuỗi source và category cũng nhận một ánh xạ values, trong khi score/threshold là số và chỉ nhận một key. Những tên bạn có thể ánh xạ (bất kỳ tên nào khác sẽ bị từ chối lúc build):
- khóa trường —
source,category,score,threshold - giá trị
source—headless,agent,node,debugger,timing,sandbox,domain,nativeHook,integrity - giá trị
category—automation,debugger,sandbox,domain,tamper,integrity
vmDefenseHook: {
name: '__vmDetection',
aliases: {
source: { key: 'a8Qm', values: { headless: 'xP4m9Q' } },
category: { key: 'p3Tx', values: { automation: 'bQ7s1M' } },
score: { key: 's1' },
threshold: { key: 't1' }
}
// the callback now receives e.g. { a8Qm: 'xP4m9Q', p3Tx: 'bQ7s1M', s1: <score>, t1: <threshold> }
}
Đây là việc tránh bị fingerprint, không phải sự bí mật — ánh xạ vẫn có thể được suy ra bằng cách thử nghiệm lặp lại — nên lợi ích duy nhất của nó là không để lộ những tên ổn định, tự giải thích. Các mục chưa đặt sẽ giữ tên mặc định của chúng.
Một chuỗi trần (vmDefenseHook: '__vmDetection') được chấp nhận như dạng viết tắt của { name: '__vmDetection' } nhưng đã lỗi thời — nên dùng dạng đối tượng.
vmDefenseReaction
Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }
Cấu hình cách mỗi category phát hiện phản ứng. Nó không bật bất cứ thứ gì — bản thân các biện pháp phòng thủ được bật bởi vmSelfDefending, vmDebugProtection, và vmDomainLock; tùy chọn này chỉ chọn cách một biện pháp phòng thủ đang bật phản ứng. Category là đơn vị kiểm soát — mọi bộ phát hiện trong một category đều thực thi phản ứng của category đó.
Mỗi category nhóm các bộ phát hiện theo dõi một loại điều kiện thù địch. Một category chỉ phản ứng khi tùy chọn phát ra các bộ phát hiện của nó được bật:
Mỗi category ánh xạ tới một hoặc nhiều trong số vmSelfDefending, vmDebugProtection, và vmDomainLock; không có category nào nằm ngoài ba tùy chọn đó, và một phản ứng được đặt cho một category có tùy chọn đang tắt thì đơn giản là không có tác dụng.
Các khóa là sáu tên category này, hoặc default (một dự phòng cho các category không được chỉ định). Các giá trị là:
break— dừng ngay lập tứcdecoy— tiếp tục chạy trên trạng thái đã bị đầu độc, âm thầm tạo ra kết quả sainone— không làm gì cục bộ (chỉ telemetry)
Các giá trị mặc định theo từng category được hiển thị ở trên; một category bạn không đặt (hoặc đặt về giá trị mặc định của nó) sẽ dùng giá trị mặc định đó. default áp dụng tới mọi category, bao gồm cả những category đúng-theo-thiết-kế (integrity, tamper), nên { default: 'none' } là một bản build thực sự không gây hỏng, chỉ dùng telemetry:
vmDefenseReaction: { default: 'none' } // never break — pair with vmDefenseHook
vmDefenseReaction: { automation: 'none', domain: 'break' } // tolerate automation FPs, still break on a bad domain
vmStatefulOpcodes
Type: boolean Default: false
Làm cho ý nghĩa của opcode phụ thuộc vào vị trí trong bytecode. Mỗi vị trí có một ánh xạ opcode-sang-handler khác nhau được suy ra từ một seed, nên cùng một số opcode thực hiện các thao tác khác nhau ở các vị trí khác nhau.
vmCallContextOpcodes
Type: boolean Default: false
Làm cho một hàm được bảo vệ phụ thuộc vào nơi nó được gọi, để nó không thể bị tách ra khỏi mã rồi chạy hoặc phân tích một cách độc lập — nó chỉ hành xử đúng khi được gọi thông qua các điểm gọi thực sự của nó trong chương trình. Tùy chọn này ảnh hưởng đến hiệu năng khi chạy.
Hiện tại chỉ các cấu trúc sau được hỗ trợ:
- khai báo hàm (
function f() {}); - biểu thức hàm và hàm mũi tên được gán cho một biến (
const f = () => {}); - phương thức riêng tư của thể hiện (
this.#m()).
Trong mọi trường hợp, hàm luôn phải được tiếp cận thông qua một lệnh gọi trực tiếp (f(), this.#m()). Nếu nó được lưu trong một biến khác, được truyền như một đối số, hoặc được dùng như một giá trị theo cách khác, nó sẽ không được bảo vệ. Các hàm async được hỗ trợ; generator thì không.
Tùy chọn này mang tính thử nghiệm và có thể làm hỏng mã của bạn, vì vậy hãy kiểm thử kỹ đầu ra trước khi dùng.
vmStackEncoding
Type: boolean Default: false
Mã hóa các giá trị trên stack của VM trong quá trình thực thi. Các giá trị được mã hóa khi được đẩy vào (push) và được giải mã khi được lấy ra (pop), nên việc kiểm tra bộ nhớ chỉ thấy dữ liệu đã mã hóa thay vì giá trị thực.
Tùy chọn này ảnh hưởng nặng đến hiệu năng.
vmCompactDispatcher
Type: boolean Default: false
Dùng một executor VM duy nhất thay vì hai executor (sync + generator). Giảm kích thước mã đã làm rối nhưng thêm khoảng ~20% chi phí hiệu năng phụ trội trên mã nhiều đệ quy.
false(mặc định): hai executor — hiệu năng tối ưu, đầu ra lớn hơntrue: một executor — đầu ra nhỏ hơn, chậm hơn một chút
vmStringArrayBytecodeOnly
Type: boolean Default: false
Khi được bật, string array sẽ chỉ trích xuất các chuỗi từ dữ liệu bytecode — không có chuỗi nào khác trong mã bị biến đổi. Tùy chọn này buộc bật stringArray ngay cả khi nó không được đặt tường minh.
Vì sao dùng tùy chọn này: Việc trích xuất tất cả các chuỗi runtime của VM vào một string array thì chậm. Tùy chọn này chỉ nhắm đến nội dung bytecode cho việc trích xuất string array, cải thiện hiệu năng trong khi vẫn bảo vệ các hằng bytecode.
- Khi
vmBytecodeArrayEncoding: false— các chuỗi bên trong các bể hằng bytecode (mảngc) được trích xuất - Khi
vmBytecodeArrayEncoding: true— các chuỗi bytecode được mã hóa base64 ở cấp cao được trích xuất stringArrayThresholdvẫn kiểm soát bao nhiêu phần trăm của các chuỗi bytecode đó được trích xuất
vmDomainLock
Type: string[] Default: []
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Giới hạn mã đã làm rối chỉ chạy trên các tên miền và/hoặc tên miền phụ cụ thể, và khó định vị cũng như loại bỏ hơn nhiều so với domainLock.
Nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi tùy chọn này, trình duyệt sẽ được chuyển hướng đến URL được truyền cho vmDomainLockRedirectUrl, và các lệnh gọi được bảo vệ tiếp theo sẽ trả về kết quả không chính xác ngay cả khi việc chuyển hướng bị chặn.
Nhiều tên miền và tên miền phụ
Bạn có thể khóa mã của mình cho nhiều hơn một tên miền hoặc tên miền phụ. Ví dụ, để khóa sao cho mã chỉ chạy trên www.example.com, hãy thêm www.example.com. Để mã hoạt động trên tên miền gốc bao gồm mọi tên miền phụ (example.com, sub.example.com), hãy dùng .example.com.
vmDomainLockRedirectUrl
Type: string Default: about:blank
⚠️ Tùy chọn này không hoạt động với target: 'node', target: 'service-worker' hoặc target: 'bytenode'
Cho phép chuyển hướng trình duyệt đến một URL được truyền vào nếu mã nguồn không được chạy trên các tên miền được chỉ định bởi vmDomainLock.
Preset Options
Làm rối cao, hiệu năng thấp
Hiệu năng sẽ chậm hơn nhiều so với khi không làm rối
{
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,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true
}
Làm rối trung bình, hiệu năng tối ưu
Hiệu năng sẽ chậm hơn so với khi không làm rối
{
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,
strictMode: null,
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
}
Làm rối thấp, hiệu năng cao
Hiệu năng sẽ ở mức tương đối bình thường
{
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,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Preset mặc định, hiệu năng cao
{
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,
strictMode: null,
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
}
VM Ultra High obfuscation (Maximum Security)
Preset này bật làm rối bytecode dựa trên VM với tất cả các tính năng gia cố bao gồm cả điều phối gián tiếp (indirect dispatch). Cung cấp mức bảo vệ mạnh nhất nhưng với kích thước đầu ra lớn hơn và tốc độ thực thi chậm hơn nhiều.
{
optionsPreset: 'vm-ultra-high-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.5,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.5,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.5,
transformObjectKeys: true
}
VM Anti-LLM (AI Agent Protection)
Preset này được thiết kế riêng để ngăn các AI agent và LLM dịch ngược mã đã được VM dịch thành bytecode. Dựa trên vm-default với self-defending và debug protection được bật. Nhẹ hơn vm-high-obfuscation nhưng được gia cố riêng để chống lại phân tích tự động.
{
optionsPreset: 'vm-anti-llm'
}
Bao gồm:
- Làm rối bytecode VM cùng với string array (từ
vm-default) vmSelfDefending— phát hiện chống hook, hash toàn vẹn, fingerprint mã nguồn, xác minh realm sạch bằng iframe, dẫn xuất khóa cipher ARXvmDebugProtection— các kiểm tra chống gỡ lỗi trong vòng lặp điều phối của VMdebugProtection: false— không dùng debug protection cũ (debug protection của VM ưu việt hơn)
VM High obfuscation (Highest Security)
Preset này bật làm rối bytecode dựa trên VM với hầu hết các tính năng gia cố. Cung cấp bảo vệ mạnh với hiệu năng tốt hơn preset ultra-high.
{
optionsPreset: 'vm-high-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: false
}
VM Medium obfuscation (Balanced Security)
Preset này bật làm rối bytecode dựa trên VM với một tập các tính năng gia cố cân bằng. Là sự thỏa hiệp tốt giữa bảo mật và hiệu năng.
{
optionsPreset: 'vm-medium-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Low obfuscation (Basic Security, Better Performance)
Preset này bật làm rối bytecode dựa trên VM cơ bản mà không có các tính năng gia cố bổ sung. Là sự cân bằng tốt giữa bảo mật và kích thước đầu ra.
{
optionsPreset: 'vm-low-obfuscation'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: false,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Default (VM + String Array Protection)
Preset này kết hợp làm rối bytecode dựa trên VM cơ bản với bảo vệ string array. Điểm khởi đầu tốt cho việc làm rối VM kèm bảo vệ chuỗi.
{
optionsPreset: 'vm-default'
}
Hoặc cấu hình từng phần:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: true,
vmStringArrayBytecodeOnly: true,
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false,
stringArray: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayThreshold: 1,
stringArrayIndexShift: true,
stringArrayIndexesType: ['hexadecimal-number'],
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1,
stringArrayWrappersCount: 3,
stringArrayWrappersType: 'function',
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayEncoding: ['base64'],
splitStrings: true,
splitStringsChunkLength: 6
}
