Dokumentacja opcji

Spis treści

compact

config

controlFlowFlattening

controlFlowFlatteningThreshold

deadCodeInjection

deadCodeInjectionThreshold

debugProtection

debugProtectionInterval

disableConsoleOutput

domainLock

Wiele domen i subdomen

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

Wiele domen i subdomen

vmDomainLockRedirectUrl

Preset Options

Wysoka obfuskacja, niska wydajność

Średnia obfuskacja, optymalna wydajność

Niska obfuskacja, wysoka wydajność

Preset domyślny, wysoka wydajność

VM Ultra High – bardzo wysoka obfuskacja (maksymalne bezpieczeństwo)

VM Anti-LLM (ochrona przed agentami AI)

VM High – wysoka obfuskacja (najwyższe bezpieczeństwo)

VM Medium – średnia obfuskacja (zrównoważone bezpieczeństwo)

VM Low – niska obfuskacja (podstawowe bezpieczeństwo, lepsza wydajność)

VM Default (VM + ochrona tablicą ciągów)

compact

Type: boolean Default: true

Kompaktowy kod wynikowy w jednej linii.

config

Type: string Default: ``

Nazwa pliku konfiguracyjnego JS/JSON zawierającego opcje obfuskatora. Zostaną one nadpisane przez opcje przekazane bezpośrednio do CLI

controlFlowFlattening

Type: boolean Default: false

⚠️ Ta opcja znacząco wpływa na wydajność – szybkość działania może spaść nawet 1,5-krotnie. Za pomocą opcji controlFlowFlatteningThreshold można ustawić procent węzłów, których dotyczy spłaszczanie przepływu sterowania.

Włącza spłaszczanie przepływu sterowania w kodzie. Spłaszczanie przepływu sterowania to transformacja struktury kodu źródłowego, która utrudnia zrozumienie programu.

Przykład:

// 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

Prawdopodobieństwo, że transformacja controlFlowFlattening zostanie zastosowana do danego węzła.

To ustawienie jest szczególnie przydatne przy dużym rozmiarze kodu, ponieważ duża liczba transformacji przepływu sterowania może spowolnić kod i zwiększyć jego rozmiar.

controlFlowFlatteningThreshold: 0 jest równoznaczne z controlFlowFlattening: false.

deadCodeInjection

Type: boolean Default: false

⚠️ Drastycznie zwiększa rozmiar zobfuskowanego kodu (nawet o 200%) – należy stosować tylko wtedy, gdy rozmiar zobfuskowanego kodu nie ma znaczenia. Za pomocą opcji deadCodeInjectionThreshold można ustawić procent węzłów, których dotyczy wstrzykiwanie martwego kodu.
⚠️ Ta opcja wymusza włączenie opcji stringArray.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation.

Przy tej opcji do zobfuskowanego kodu dodawane są losowe bloki martwego kodu.

Przykład:

// 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

Pozwala ustawić procent węzłów, których dotyczy deadCodeInjection.

debugProtection

Type: boolean Default: false

⚠️ Może zawiesić przeglądarkę po otwarciu narzędzi deweloperskich.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmDebugProtection.

Ta opcja sprawia, że korzystanie z funkcji debugger w narzędziach deweloperskich staje się niemal niemożliwe (zarówno w przeglądarkach opartych na WebKit, jak i w Mozilla Firefox).

debugProtectionInterval

Type: number Default: 0

⚠️ Może zawiesić przeglądarkę! Stosowanie na własne ryzyko.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmDebugProtection.

Jeśli ta opcja jest ustawiona, wykorzystywany jest interwał w milisekundach wymuszający tryb debugowania w karcie Console, co utrudnia korzystanie z pozostałych funkcji narzędzi deweloperskich. Działa, gdy włączona jest opcja debugProtection. Zalecana wartość mieści się w przedziale od 2000 do 4000 milisekund.

disableConsoleOutput

Type: boolean Default: false

⚠️ Ta opcja globalnie wyłącza wywołania console dla wszystkich skryptów

Wyłącza możliwość korzystania z console.log, console.info, console.error, console.warn, console.debug, console.exception i console.trace, zastępując je pustymi funkcjami. Utrudnia to korzystanie z debuggera.

domainLock

Type: string[] Default: []

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala uruchamiać zobfuskowany kod źródłowy wyłącznie w określonych domenach i/lub subdomenach. Bardzo utrudnia to skopiowanie kodu źródłowego i uruchomienie go w innym miejscu.

Jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w tej opcji, przeglądarka zostanie przekierowana pod adres URL przekazany w opcji domainLockRedirectUrl.

Wiele domen i subdomen

Kod można zablokować do więcej niż jednej domeny lub subdomeny. Na przykład, aby zablokować go tak, by działał wyłącznie w www.example.com, należy dodać www.example.com. Aby działał w domenie głównej wraz ze wszystkimi subdomenami (example.com, sub.example.com), należy użyć .example.com.

domainLockRedirectUrl

Type: string Default: about:blank

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala przekierować przeglądarkę pod przekazany adres URL, jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w opcji domainLock

exclude

Type: string[] Default: []

Nazwy plików lub wzorce glob wskazujące pliki wykluczone z obfuskacji.

forceTransformStrings

Type: string[] Default: []

Włącza wymuszoną transformację literałów tekstowych pasujących do przekazanych wzorców RegExp.

⚠️ Ta opcja dotyczy wyłącznie ciągów, które nie powinny zostać przekształcone zgodnie z opcją stringArrayThreshold (lub, być może, innymi progami w przyszłości)

Opcja ma priorytet nad opcją reservedStrings, ale nie ma priorytetu nad conditional comments.

Przykład:

	{
		forceTransformStrings: [
			'some-important-value',
			'some-string_\d'
		]
	}

identifierNamesCache

Type: Object | null Default: null

Głównym celem tej opcji jest możliwość używania tych samych nazw identyfikatorów podczas obfuskacji wielu źródeł/plików.

Obecnie obsługiwane są dwa rodzaje identyfikatorów:

  • Identyfikatory globalne:
    • wszystkie identyfikatory globalne zostaną zapisane w pamięci podręcznej;
    • wszystkie dopasowane niezadeklarowane identyfikatory globalne zostaną zastąpione wartościami z pamięci podręcznej.
  • Identyfikatory właściwości, tylko gdy włączona jest opcja renameProperties:
    • wszystkie identyfikatory właściwości zostaną zapisane w pamięci podręcznej;
    • wszystkie dopasowane identyfikatory właściwości zostaną zastąpione wartościami z pamięci podręcznej.

Node.js API

Przekazanie wartości null całkowicie wyłącza pamięć podręczną.

Przekazanie pustego obiektu ({}) włącza zapisywanie nazw identyfikatorów do obiektu pamięci podręcznej (typ TIdentifierNamesCache). Dostęp do tego obiektu uzyskuje się przez wywołanie metody getIdentifierNamesCache obiektu ObfuscationResult.

Powstały obiekt pamięci podręcznej można następnie przekazać jako wartość opcji identifierNamesGenerator, aby użyć tych nazw podczas obfuskacji wszystkich dopasowanych nazw identyfikatorów w kolejnych źródłach.

Przykład:

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 udostępnia inną opcję – --identifier-names-cache-path – która pozwala wskazać ścieżkę do istniejącego pliku .json używanego do odczytu i zapisu pamięci podręcznej nazw identyfikatorów.

Jeśli zostanie przekazana ścieżka do pustego pliku, pamięć podręczna nazw identyfikatorów zostanie zapisana do tego pliku.

Ten plik z istniejącą pamięcią podręczną można ponownie wykorzystać jako wartość opcji --identifier-names-cache-path, aby użyć tych nazw podczas obfuskacji wszystkich dopasowanych nazw identyfikatorów w kolejnych plikach.

identifierNamesGenerator

Type: string Default: hexadecimal

Ustawia generator nazw identyfikatorów.

Dostępne wartości:

  • dictionary: nazwy identyfikatorów z listy identifiersDictionary
  • hexadecimal: nazwy identyfikatorów w rodzaju _0xabc123
  • mangled: krótkie nazwy identyfikatorów, takie jak a, b, c
  • mangled-shuffled: to samo co mangled, ale z przetasowanym alfabetem

identifiersDictionary

Type: string[] Default: []

Ustawia słownik identyfikatorów dla opcji identifierNamesGenerator: dictionary. Każdy identyfikator ze słownika zostanie użyty w kilku wariantach różniących się wielkością poszczególnych znaków. Liczba identyfikatorów w słowniku powinna zatem zależeć od liczby identyfikatorów w oryginalnym kodzie źródłowym.

identifiersPrefix

Type: string Default: ''

Ustawia prefiks dla wszystkich identyfikatorów globalnych.

Tej opcji należy używać przy obfuskacji wielu plików. Pomaga ona uniknąć konfliktów między identyfikatorami globalnymi tych plików. Prefiks powinien być inny dla każdego pliku.

randomIdentifiersPrefix

Type: boolean Default: false

Dodaje do wszystkich identyfikatorów globalnych losowy prefiks (6 znaków alfanumerycznych) generowany na podstawie ziarna. Tej opcji należy używać, aby uniknąć kolizji między osobno zobfuskowanymi bundle’ami ładowanymi do tego samego zasięgu globalnego — dzięki niej nie trzeba ręcznie dobierać unikalnej wartości identifiersPrefix dla każdego bundle’a.

  • Wartość losowa jest wyprowadzana z opcji seed oraz skrótu kodu źródłowego, więc powtarzalne kompilacje z tym samym ziarnem dają ten sam prefiks.
  • W połączeniu z identifiersPrefix losowe znaki są dopisywane na końcu prefiksu podanego przez użytkownika (np. myApp + losowe aBc123myAppaBc123).
  • W połączeniu z vmObfuscation wartość losowa zastępuje domyślny prefiks vm — losowość i tak gwarantuje unikalność.

ignoreImports

Type: boolean Default: false

Zapobiega obfuskacji importów require. Może się przydać w sytuacjach, gdy środowisko uruchomieniowe z jakiegoś powodu wymaga, aby te importy zawierały wyłącznie statyczne ciągi znaków.

inputFileName

Type: string Default: ''

Pozwala ustawić nazwę pliku wejściowego z kodem źródłowym. Nazwa ta będzie używana wewnętrznie podczas generowania mapy źródeł. Wymagana przy korzystaniu z API NodeJS, gdy opcja sourceMapSourcesMode ma wartość sources.

log

Type: boolean Default: false

Włącza wypisywanie informacji do konsoli.

numbersToExpressions

Type: boolean Default: false

Włącza zamianę liczb na wyrażenia

Przykład:

// input
const foo = 1234;

// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;

optionsPreset

Type: string Default: default

Pozwala ustawić preset opcji.

Dostępne wartości:

  • 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.

Wszystkie dodatkowe opcje zostaną scalone z wybranym presetem opcji.

parseHtml

Type: boolean Default: false

Włącza obfuskację kodu JavaScript wewnątrz znaczników <script> w plikach HTML.

Po włączeniu obfuskator:

  • Automatycznie wykrywa, czy wejście jest kodem HTML (sprawdzając znaczniki <!DOCTYPE, <html>, <head>, <body> lub <script>)
  • Wyodrębnia kod JavaScript ze znaczników <script> oznaczonych atrybutem data-javascript-obfuscator
  • Obfuskuje każdy oznaczony skrypt osobno, zachowując strukturę HTML
  • Wstawia zobfuskowany kod z powrotem w pierwotne miejsca

Ważne: obfuskowane są wyłącznie skrypty z atrybutem data-javascript-obfuscator. Każdy oznaczony skrypt jest obfuskowany osobno i niezależnie. Oznacza to, że:

  • Kod wewnątrz oznaczonych znaczników skryptu musi być odizolowany – nie może odwoływać się do zmiennych, funkcji ani klas zdefiniowanych w innych oznaczonych znacznikach skryptu
  • Nieoznaczone skrypty nadal mają dostęp do zmiennych globalnych zdefiniowanych przez oznaczone skrypty (przez deklaracje var lub jawne przypisania do globalThis)
  • Daje to jawną kontrolę nad tym, które skrypty są chronione

Obfuskowane (muszą mieć atrybut data-javascript-obfuscator):

  • <script data-javascript-obfuscator> – zwykłe skrypty
  • <script type="text/javascript" data-javascript-obfuscator> – skrypty z jawnie podanym typem
  • Skrypty z dowolnymi dodatkowymi atrybutami (id, class, inne data-* itd.)

Pomijane (pozostają bez zmian):

  • Skrypty bez atrybutu data-javascript-obfuscator
  • <script type="module"> – moduły ES (nawet z tym atrybutem)
  • <script src="..."> – skrypty zewnętrzne (nawet z tym atrybutem)
  • Puste znaczniki skryptu

Uwaga: przy włączonej opcji parseHtml mapy źródeł nie są generowane, ponieważ nie odwzorowywałyby poprawnie wyniku w formacie HTML.

Przykład:

// 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

⚠️ ta opcja może zepsuć kod. Należy ją włączać tylko wtedy, gdy wiadomo, do czego służy!

Włącza obfuskację nazw zmiennych i funkcji globalnych wraz z deklaracją.

Gdy ta opcja jest wyłączona, a kod wejściowy deklaruje funkcje lub klasy w zasięgu globalnym (tzn. nie jest opakowany w IIFE), ich nazwy pozostają w zobfuskowanym wyniku bez zmian — inne skrypty mogą odwoływać się do nich po nazwie. Przy włączonej opcji vmObfuscation zgłaszane jest ostrzeżenie VMGlobalFunctionNamesNotRenamed z listą tych nazw, ponieważ ciało funkcji jest ukryte w postaci kodu bajtowego, ale czytelna nazwa najwyższego poziomu nadal zdradza, co robi kod (np. modelowi LLM). Aby uniknąć tego ujawnienia, należy opakować kod w IIFE albo włączyć tę opcję.

renameProperties

Type: boolean Default: false

⚠️ ta opcja MOŻE zepsuć kod. Należy ją włączać tylko wtedy, gdy wiadomo, do czego służy!

Włącza zmianę nazw właściwości. Wszystkie wbudowane właściwości DOM oraz właściwości podstawowych klas JavaScriptu zostaną pominięte.

Do przełączania między trybem safe i unsafe tej opcji służy opcja renamePropertiesMode.

Format zmienionych nazw właściwości ustawia się opcją identifierNamesGenerator.

Tym, którym właściwościom zostaną zmienione nazwy, steruje opcja reservedNames.

Przykład:

// 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

⚠️ Nawet w trybie safe opcja renameProperties MOŻE zepsuć kod.

Określa tryb opcji renameProperties:

  • safe – domyślne zachowanie po wydaniu 2.11.0. Próbuje zmieniać nazwy właściwości w bezpieczniejszy sposób, aby zapobiec błędom w czasie wykonania. W tym trybie część właściwości zostanie wykluczona ze zmiany nazw.
  • unsafe – domyślne zachowanie przed wydaniem 2.11.0. Zmienia nazwy właściwości w niebezpieczny sposób, bez żadnych ograniczeń.

Jeśli jeden plik korzysta z właściwości pochodzących z innego pliku, należy użyć opcji identifierNamesCache, aby zachować te same nazwy właściwości w obu plikach.

reservedNames

Type: string[] Default: []

Wyłącza obfuskację i generowanie identyfikatorów pasujących do przekazanych wzorców RegExp.

Przykład:

	{
		reservedNames: [
			'^someVariable',
			'functionParameter_\d'
		]
	}

reservedStrings

Type: string[] Default: []

Wyłącza transformację literałów tekstowych pasujących do przekazanych wzorców RegExp. Dopasowane ciągi pozostaną widoczne w zobfuskowanym wyniku.

Przy obfuskacji VM zarezerwowane ciągi są przechowywane w osobnej, niezaszyfrowanej tablicy, aby pozostały widoczne. Jest to przydatne dla ciągów, które muszą pozostać czytelne, takich jak adresy endpointów API używanych do monitorowania czy identyfikatory bibliotek.

Przykład:

	{
		reservedStrings: [
			'react-native',
			'\.\/src\/test',
			'some-string_\d'
		]
	}

seed

Type: string|number Default: 0

Ta opcja ustawia ziarno (seed) generatora liczb losowych. Przydaje się do uzyskiwania powtarzalnych wyników.

Jeśli ziarno wynosi 0, generator liczb losowych działa bez ziarna.

selfDefending

Type: boolean Default: false

⚠️ Po obfuskacji z tą opcją nie wolno w żaden sposób modyfikować zobfuskowanego kodu, ponieważ każda zmiana, na przykład minifikacja, może uruchomić mechanizm samoobrony i kod przestanie działać!
⚠️ Ta opcja wymusza ustawienie wartości compact na true
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmSelfDefending.

Ta opcja sprawia, że kod wynikowy jest odporny na formatowanie i zmianę nazw zmiennych. Jeśli ktoś spróbuje użyć na zobfuskowanym kodzie narzędzia upiększającego JavaScript, kod przestanie działać, co utrudnia jego zrozumienie i modyfikację.

simplify

Type: boolean Default: true

Włącza dodatkową obfuskację kodu poprzez upraszczanie.

⚠️ w przyszłych wydaniach obfuskacja literałów boolean (true => !![]) zostanie przeniesiona pod tę opcję.

Przykład:

// 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

Włącza generowanie mapy źródeł dla zobfuskowanego kodu.

Mapy źródeł ułatwiają debugowanie zobfuskowanego kodu źródłowego JavaScript. Jeśli konieczne jest debugowanie na produkcji, osobny plik mapy źródeł można umieścić w niejawnej lokalizacji, a następnie wskazać ją przeglądarce.

sourceMapBaseUrl

Type: string Default: ``

Ustawia bazowy adres URL dla adresu importu mapy źródeł przy sourceMapMode: 'separate'.

Przykład CLI:

javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'

Wynik:

//# sourceMappingURL=http://localhost:9000/out.js.map

sourceMapFileName

Type: string Default: ``

Ustawia nazwę pliku wynikowej mapy źródeł przy sourceMapMode: 'separate'.

Przykład CLI:

javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example

Wynik:

//# sourceMappingURL=http://localhost:9000/example.js.map

sourceMapMode

Type: string Default: separate

Określa tryb generowania mapy źródeł:

  • inline – dodaje mapę źródeł na końcu każdego pliku .js;
  • separate – generuje odpowiadający plik '.map' z mapą źródeł. W przypadku uruchamiania obfuskatora przez CLI dodaje na końcu pliku z zobfuskowanym kodem odnośnik do pliku mapy źródeł //# sourceMappingUrl=file.js.map.

sourceMapSourcesMode

Type: string Default: sources-content

Pozwala sterować polami sources i sourcesContent mapy źródeł:

  • sources-content – dodaje atrapę pola sources oraz pole sourcesContent z oryginalnym kodem źródłowym;
  • sources – dodaje pole sources z poprawnym opisem źródeł i nie dodaje pola sourcesContent. Przy korzystaniu z API NodeJS wymagane jest zdefiniowanie opcji inputFileName, której wartość zostanie użyta jako wartość pola sources.

splitStrings

Type: boolean Default: false

Dzieli literały tekstowe na fragmenty o długości określonej wartością opcji splitStringsChunkLength.

Przykład:

// input
(function(){
    var test = 'abcdefg';
})();

// output
(function(){
    var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();

splitStringsChunkLength

Type: number Default: 10

Ustawia długość fragmentu dla opcji splitStrings.

stringArray

Type: boolean Default: true

Usuwa literały tekstowe i umieszcza je w specjalnej tablicy. Na przykład ciąg "Hello World" w var m = "Hello World"; zostanie zastąpiony czymś w rodzaju var m = _0x12c456[0x1];

stringArrayCallsTransform

Type: boolean Default: false

⚠️ Opcja stringArray musi być włączona

Włącza transformację wywołań do stringArray. Wszystkie argumenty tych wywołań mogą zostać wyodrębnione do osobnego obiektu, w zależności od wartości opcji stringArrayCallsTransformThreshold. Dzięki temu automatyczne wyszukiwanie wywołań tablicy ciągów staje się jeszcze trudniejsze.

Przykład:

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

⚠️ Opcje stringArray i stringArrayCallsTransformThreshold muszą być włączone

Za pomocą tego ustawienia można dostosować prawdopodobieństwo (od 0 do 1) przekształcenia wywołań tablicy ciągów.

stringArrayEncoding

Type: string[] Default: []

⚠️ Opcja stringArray musi być włączona

Ta opcja może spowolnić skrypt.

Koduje wszystkie literały tekstowe z stringArray przy użyciu base64 lub rc4 i wstawia specjalny kod, który dekoduje je z powrotem w czasie wykonania.

Każda wartość stringArray zostanie zakodowana losowo wybranym kodowaniem z przekazanej listy. Umożliwia to jednoczesne stosowanie wielu kodowań.

Dostępne wartości:

  • 'none' (boolean): nie koduje wartości stringArray
  • 'base64' (string): koduje wartość stringArray przy użyciu base64
  • 'rc4' (string): koduje wartość stringArray przy użyciu rc4. Około 30–50% wolniejsze niż base64, ale trudniej odtworzyć pierwotne wartości.

Na przykład przy poniższych wartościach opcji część wartości stringArray nie zostanie zakodowana, a pozostałe zostaną zakodowane kodowaniem base64 oraz rc4:

stringArrayEncoding: [
    'none',
    'base64',
    'rc4'
]

stringArrayIndexesType

Type: string[] Default: ['hexadecimal-number']

⚠️ Opcja stringArray musi być włączona

Pozwala sterować typem indeksów wywołań tablicy ciągów.

Każdy indeks wywołania stringArray zostanie przekształcony zgodnie z losowo wybranym typem z przekazanej listy. Umożliwia to jednoczesne stosowanie wielu typów.

Dostępne wartości:

  • 'hexadecimal-number' (default): przekształca indeksy wywołań tablicy ciągów w liczby szesnastkowe
  • 'hexadecimal-numeric-string': przekształca indeksy wywołań tablicy ciągów w szesnastkowe ciągi liczbowe

Przed wydaniem 2.9.0 javascript-obfuscator przekształcał wszystkie indeksy wywołań tablicy ciągów zgodnie z typem hexadecimal-numeric-string. Utrudnia to nieco ręczną deobfuskację, ale pozwala automatycznym deobfuskatorom łatwo wykrywać takie wywołania.

Nowy typ hexadecimal-number ma na celu utrudnienie automatycznego wykrywania wzorców wywołań tablicy ciągów w kodzie.

W przyszłości zostaną dodane kolejne typy.

stringArrayIndexShift

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Włącza dodatkowe przesunięcie indeksu dla wszystkich wywołań tablicy ciągów

stringArrayRotate

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Przesuwa tablicę stringArray o stałą, losowo wyznaczoną (podczas obfuskacji kodu) liczbę pozycji. Utrudnia to dopasowanie kolejności usuniętych ciągów do ich pierwotnych miejsc.

stringArrayShuffle

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Losowo tasuje elementy tablicy stringArray.

stringArrayWrappersCount

Type: number Default: 1

⚠️ Opcja stringArray musi być włączona

Ustawia liczbę wrapperów dla string array wewnątrz zasięgu głównego oraz każdego zasięgu funkcji. Faktyczna liczba wrapperów w danym zasięgu jest ograniczona liczbą węzłów literal w tym zasięgu.

Przykład:

// 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

⚠️ Opcje stringArray i stringArrayWrappersCount muszą być włączone

Włącza łańcuchowe wywołania między wrapperami string array.

Przykład:

// 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

⚠️ Opcja stringArray musi być włączona
⚠️ Obecnie ta opcja dotyczy wyłącznie wrapperów dodawanych przy wartości function opcji stringArrayWrappersType

Pozwala sterować maksymalną liczbą parametrów wrapperów tablicy ciągów. Wartość domyślna i minimalna to 2. Zalecana wartość mieści się w przedziale od 2 do 5.

stringArrayWrappersType

Type: string Default: variable

⚠️ Opcje stringArray i stringArrayWrappersCount muszą być włączone

Pozwala wybrać typ wrapperów dodawanych przez opcję stringArrayWrappersCount.

Dostępne wartości:

  • 'variable': dodaje wrappery w postaci zmiennych na początku każdego zasięgu. Wysoka wydajność.
  • 'function': dodaje wrappery w postaci funkcji w losowych miejscach wewnątrz każdego zasięgu. Wydajność niższa niż przy variable, ale obfuskacja jest ostrzejsza.

Zdecydowanie zaleca się stosowanie wrapperów function dla silniejszej obfuskacji, o ile spadek wydajności nie ma dużego wpływu na zobfuskowaną aplikację.

Przykład dla wartości opcji '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

⚠️ Opcja stringArray musi być włączona

Za pomocą tego ustawienia można dostosować prawdopodobieństwo (od 0 do 1), że literał tekstowy zostanie umieszczony w stringArray.

To ustawienie jest szczególnie przydatne przy dużym rozmiarze kodu, ponieważ powoduje ono wielokrotne wywołania string array i może spowolnić kod.

stringArrayThreshold: 0 jest równoznaczne z stringArray: false.

strictMode

Type: boolean | null Default: null

Pozwala określić, jak obfuskator ma traktować kod w kontekście trybu ścisłego (strict mode) JavaScriptu.

Dostępne wartości:

  • null (domyślnie) – automatycznie wykrywa tryb ścisły na podstawie kodu. Jeśli kod zawiera jawną dyrektywę 'use strict', składnię modułów ES lub metody klas, jest traktowany jako kod w trybie ścisłym. W przeciwnym razie zakładany jest tryb swobodny (sloppy mode).
  • true – wymusza traktowanie całego kodu jako kodu w trybie ścisłym, nawet bez jawnej dyrektywy 'use strict'. Należy stosować, gdy kod będzie uruchamiany w kontekście trybu ścisłego (np. w modułach ES, bundlerach lub nowoczesnych frameworkach).
  • false – jako kod w trybie ścisłym traktowane są wyłącznie fragmenty z jawnymi wskaźnikami trybu ścisłego ('use strict', moduły ES, metody klas). Dziedziczenie z zasięgu nadrzędnego nadal obowiązuje zgodnie ze specyfikacją JS.

target

Type: string Default: browser

Pozwala ustawić środowisko docelowe zobfuskowanego kodu.

Dostępne wartości:

  • browser (domyślnie) — standardowe środowisko strony internetowej. Kod wynikowy jest identyczny jak dla node, ale niektórych opcji przeznaczonych dla przeglądarki nie można używać ze środowiskiem node
  • browser-no-eval — tak samo jak browser, ale kod wynikowy nie używa eval(). Należy stosować, gdy strona docelowa ma politykę Content Security Policy zabraniającą eval/unsafe-eval.
  • node — środowisko Node.js. Opcje przeznaczone dla przeglądarki są wyłączone (wymagają window/document, a w Node nie robiłyby nic lub zgłaszałyby błąd). Część mechanizmów obronnych vmSelfDefending opartych na API dostępnych wyłącznie w przeglądarce — wykrywanie przeglądarki headless, odtwarzanie czystego realmu przy użyciu iframe, kontrole antyinspektorowe i sprawdzanie DOM — nie jest generowana dla tego środowiska.
  • service-worker — kontekst Service Workera. Brak window, brak document, inny obiekt globalny self.
  • userscript — piaskownica menedżera userscriptów (np. Tampermonkey). Mechanizmy obronne vmSelfDefending są odpowiednio dostosowywane.
  • bytenode — kod Node.js, który po obfuskacji zostanie skompilowany loaderem bytenode (kod bajtowy V8 z pamięci podręcznej, .jsc). Sam obfuskator nie uruchamia bytenode; generuje kod JavaScript po obfuskacji VM, którego środowisko uruchomieniowe jest zbudowane tak, aby przetrwało etap kompilacji przez bytenode, a mechanizmy obronne vmSelfDefending są odpowiednio dostosowywane. Aby otrzymać końcowy plik .jsc, należy samodzielnie uruchomić bytenode na zobfuskowanym kodzie wynikowym.

transformObjectKeys

Type: boolean Default: false

Włącza transformację kluczy obiektów.

Przykład:

// 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

Określa, które nieblokujące ostrzeżenia obfuskacji są zwracane przez metodę ObfuscationResult.getWarnings().

Dostępne wartości:

  • 'all' (domyślnie) — zwracane są wszystkie ostrzeżenia.
  • 'none' — wszystkie ostrzeżenia są pomijane.
  • obiekt mapujący typy ostrzeżeń na wartości logiczne — typ przypisany do false jest pomijany; każdy typ nieobecny w mapie (lub przypisany do true) pozostaje włączony. Na przykład { "VMGlobalFunctionNamesNotRenamed": false } zachowuje wszystkie ostrzeżenia z wyjątkiem tego jednego.

Typy ostrzeżeń:

  • VMGlobalFunctionNamesNotRenamed — przy włączonej opcji vmObfuscation nazwy deklaracji funkcji i klas najwyższego poziomu oraz zmiennych, którym przypisano wyrażenie funkcyjne, funkcję strzałkową lub wyrażenie klasowe, pozostały bez zmian (opcja renameGlobals jest wyłączona, a kod nie jest opakowany w IIFE), więc pozostają czytelne w wyniku, mimo że ciała funkcji są ukryte w postaci kodu bajtowego. Nazwy eksportowane nie są zgłaszane.
  • VMTopLevelInitializerNotVirtualized — inicjalizatory zmiennych najwyższego poziomu pozostały przy obfuskacji VM zwykłym kodem JavaScript, ponieważ opcja vmWrapTopLevelInitializers jest wyłączona lub nie zdołała ich zwirtualizować.
  • DynamicCodeRenameRisk — kod tworzy funkcję z ciągu znaków w czasie wykonania (bezpośredni eval, konstruktor Function lub fn.toString() wstrzyknięty do znacznika <script>/Workera), przez co może odwoływać się do identyfikatorów, których nazwy zmienił obfuskator.
  • VMDynamicCodeSkipped — funkcja została pominięta przy generowaniu kodu bajtowego VM, ponieważ zawiera bezpośredni eval, dynamiczne new Function albo Function (zob. vmForceCompileDynamicCode).
  • VMSyncFunctionSkippedInAsyncMode — przy włączonej opcji vmAsyncExecutor funkcja jawnie oznaczona w trybie comment okazała się synchroniczna i została pominięta (w tym trybie wirtualizowane są wyłącznie funkcje asynchroniczne).
  • VMAsyncGeneratorSkippedInAsyncMode — przy włączonej opcji vmAsyncExecutor i aktywnym asynchronicznym getterze klucza nie udało się zwirtualizować oznaczonego generatora asynchronicznego (musi on zwracać swój iterator synchronicznie).
  • BrowserTargetWithNodeStyleCode — kod wygląda na przeznaczony dla Node.js (np. require('fs'), __dirname, process.argv), podczas gdy opcja target jest ustawiona na środowisko przeglądarkowe.

vmObfuscation

Type: boolean Default: false

Włącza obfuskację opartą na kodzie bajtowym VM. Po jej włączeniu funkcje JavaScript są kompilowane do niestandardowego kodu bajtowego wykonywanego przez osadzoną maszynę wirtualną. Zapewnia to najwyższy poziom ochrony, ponieważ pierwotna logika kodu zostaje całkowicie przekształcona.

Przykład: Czytelny kod w rodzaju return qty * price zamienia się w listę liczb, na przykład [0x15,0x03,0x17,...], którą potrafi wykonać wyłącznie osadzony interpreter VM. Pierwotna logika nie jest już widoczna jako kod JavaScript.

vmTargetFunctions

Type: string[] Default: []

Pozwala wskazać po nazwie dokładnie te funkcje najwyższego poziomu, które mają zostać objęte ochroną VM.

Przykład:

{
    vmObfuscation: true,
    vmTargetFunctions: ['someFunctionName']
}

Wynik: ochroną VM zostaną objęte wyłącznie te trzy funkcje. Cała reszta pozostanie zwykłym (choć nadal zobfuskowanym) kodem JavaScript. Idealne rozwiązanie do ochrony wrażliwej weryfikacji licencji lub logiki uwierzytelniania przy zachowaniu lekkości pozostałej części kodu.

vmExcludeFunctions

Type: string[] Default: []

Pozwala wskazać funkcje najwyższego poziomu, które nigdy nie mają być objęte ochroną VM. Ma pierwszeństwo przed pozostałymi ustawieniami.

Przykład:

{
    vmObfuscation: true,
    vmExcludeFunctions: ['someFunctionName']
}

Kiedy stosować: funkcje najwyższego poziomu krytyczne dla wydajności (pętle animacji, przetwarzanie danych w czasie rzeczywistym) można wykluczyć, aby uniknąć narzutu VM, chroniąc jednocześnie całą resztę.

vmTargetFunctionsMode

Type: string Default: root

Określa sposób wyboru funkcji i metod do obfuskacji VM.

TrybOpis
rootZachowanie domyślne. Do obfuskacji VM brane są pod uwagę wyłącznie funkcje najwyższego poziomu. Do filtrowania służą lista dozwolonych vmTargetFunctions oraz lista wykluczeń vmExcludeFunctions.
commentObfuskacji VM podlegają wyłącznie funkcje i metody oznaczone komentarzem /* javascript-obfuscator:vm */. Działa dla funkcji i metod na dowolnym poziomie zagnieżdżenia.

Przykład – tryb 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'
}

Kiedy stosować: gdy potrzebna jest chirurgiczna kontrola nad tym, które dokładnie funkcje zostaną objęte ochroną VM, zwłaszcza funkcje zagnieżdżone zawierające wrażliwą logikę. W przeciwieństwie do vmTargetFunctions, które działa wyłącznie dla nazwanych funkcji najwyższego poziomu, tryb comment pozwala chronić dowolną funkcję w dowolnym miejscu kodu.

vmForceCompileDynamicCode

Type: boolean Default: false

Określa, co obfuskacja VM robi z funkcją zawierającą bezpośrednie wywołanie eval, new Function(...) lub Function(...).

Domyślnie taka funkcja (oraz każda funkcja zdefiniowana w jej wnętrzu) jest pomijana przy generowaniu kodu bajtowego VM, a w result.getWarnings() zgłaszane jest ostrzeżenie VMDynamicCodeSkipped. Dzieje się tak dlatego, że kod źródłowy budowany w czasie wykonania może odwoływać się do identyfikatorów z otaczającego łańcucha zasięgów — identyfikatorów, których nazwy zmienił obfuskator.

Po ustawieniu wartości true funkcja mimo wszystko zostaje przekształcona w kod bajtowy, a ostrzeżenie VMDynamicCodeSkipped nie jest już zgłaszane.

Osobne ostrzeżenie DynamicCodeRenameRisk jest zgłaszane niezależnie od tej opcji, ponieważ opisywane przez nie ryzyko związane ze zmianą nazw nie ma związku z pomijaniem funkcji przez VM — włączenie tej opcji w żaden sposób nie czyni tego wzorca bezpieczniejszym.

// Source code
function loadConfig(src) {
    return eval(src);
}
loadConfig('1 + 2');
// Options
{
    vmObfuscation: true,
    vmForceCompileDynamicCode: true
}

Przy wyłączonej opcji (domyślnie) loadConfig pozostaje zwykłym kodem JavaScript. Przy włączonej opcji loadConfig jest kompilowana do kodu bajtowego VM jak każda inna funkcja. Należy z tego korzystać po sprawdzeniu miejsca wywołania i upewnieniu się, że kod budowany w czasie wykonania nie zależy od identyfikatorów z domknięcia, których nazwy zostały zmienione.

vmWrapTopLevelInitializers

Type: boolean Default: false

Opakowuje część inicjalizatorów zmiennych najwyższego poziomu w IIFE (natychmiast wywoływane wyrażenia funkcyjne), dzięki czemu mogą zostać poddane obfuskacji VM.

Co robi: Bez tej opcji stałe i zmienne najwyższego poziomu pozostają widoczne w wyniku:

// Input
const MY_STRING = "my-string";

// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string";  // String is visible!

Po włączeniu tej opcji inicjalizator zostaje opakowany w IIFE, które podlega obfuskacji VM:

// Input
const MY_STRING = "my-string";

// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })();  // String hidden in bytecode

Uwaga: ta opcja działa wyłącznie wtedy, gdy vmTargetFunctionsMode ma wartość 'root' (domyślną).

Ostrzeżenia: za każdym razem, gdy przy obfuskacji VM inicjalizator najwyższego poziomu pozostanie zwykłym kodem JavaScript, zgłaszane jest ostrzeżenie VMTopLevelInitializerNotVirtualized z listą nazw zmiennych, których to dotyczy. Obejmuje ono: wyłączenie tej opcji, inicjalizatory, które opcja musiała pominąć (każdy wraz z powodem — np. inicjalizator odwołuje się do sąsiedniego deklaratora albo zawiera await najwyższego poziomu), oraz tryb vmAsyncExecutor, w którym synchronicznych wrapperów w ogóle nie da się zwirtualizować.

vmDynamicOpcodes

Type: boolean Default: false

Sprawia, że interpreter VM jest mniejszy i unikalny dla każdej kompilacji.

Co robi:

  1. Odfiltrowuje nieużywane instrukcje – jeśli kod nie korzysta z klas, instrukcje związane z klasami są całkowicie usuwane
  2. Losuje strukturę – kolejność procedur obsługi instrukcji jest tasowana przy każdej kompilacji

W efekcie wynik jest mniejszy, a każda kompilacja wygląda inaczej.

vmBytecodeEncoding

Type: boolean Default: false

Koduje każdą instrukcję kodu bajtowego. Instrukcje są dekodowane pojedynczo w trakcie wykonywania.

vmBytecodeArrayEncoding

Type: boolean Default: false

Koduje całą tablicę kodu bajtowego jako pojedynczy blok. Tablica jest dekodowana jednorazowo przy starcie, zanim rozpocznie się wykonywanie. Warto stosować razem z vmBytecodeEncoding, aby uzyskać dwie warstwy ochrony.

vmBytecodeArrayEncodingKey

Type: string Default: ''

Własny klucz szyfrujący dla kodowania tablicy kodu bajtowego. Po ustawieniu używany jest ten klucz zamiast domyślnego klucza wyprowadzanego ze środowiska. Klucz musi zostać dostarczony w czasie wykonania przez vmBytecodeArrayEncodingKeyGetter.

Ta opcja wynosi klucz szyfrujący na zewnątrz — nie jest on osadzony w samym zobfuskowanym kodzie. Klucz jest wprawdzie nadal dostępny w czasie wykonania (a więc nie jest naprawdę tajny), ale takie rozdzielenie uniemożliwia narzędziom do analizy statycznej znalezienie go na podstawie samego kodu.

Ważne: klucz musi być dostępny synchronicznie w momencie ładowania zobfuskowanego kodu. Należy korzystać z synchronicznych źródeł danych, takich jak ciasteczka, localStorage, sessionStorage, zmienne globalne lub elementy DOM (np. znaczniki meta wstrzykiwane przez serwer). Metod asynchronicznych, takich jak fetch(), nie można użyć bezpośrednio w wyrażeniu gettera klucza.

vmBytecodeArrayEncodingKeyGetter

Type: string Default: ''

Synchroniczne wyrażenie JavaScript, które zwraca klucz szyfrujący w czasie wykonania. Wyrażenie to jest obliczane w momencie załadowania zobfuskowanego kodu i musi zwrócić dokładnie ten sam klucz, który podano w vmBytecodeArrayEncodingKey. Aby uzyskiwać klucz asynchronicznie (jako Promise), należy włączyć opcję vmAsyncExecutor.

Uwaga: getter zwracający obiekt Promise wymaga opcji vmAsyncExecutor. Nie da się tego sprawdzić na etapie kompilacji, więc getter zwracający Promise przy wyłączonej opcji vmAsyncExecutor zawiedzie w czasie wykonania — dekoder otrzyma obiekt Promise zamiast klucza.

Zobfuskowany kod zadziała wyłącznie wtedy, gdy getter klucza zwróci dokładnie ten sam klucz, którego użyto podczas obfuskacji. Jeśli klucze się nie zgadzają, odszyfrowanie się nie powiedzie, a kod będzie generował śmieci lub błędy. Jeśli getter klucza zwróci undefined, null albo pusty ciąg, kod zgłosi błąd: „VM decryption key not available”.

Ważne: klucz należy trzymać poza tym samym plikiem/skryptem co zobfuskowany kod — umieszczenie go tam pozwala odzyskać go nawet czysto statycznym przeskanowaniem bundle’a. Zamiast tego należy przechowywać go w osobnym źródle: w ciasteczkach ustawianych przez serwer, w localStorage wypełnianym przez inny skrypt, w znaczniku meta HTML wstrzykiwanym przez serwer, w zmiennej globalnej ustawianej przez inny skrypt lub (przy włączonej opcji vmAsyncExecutor) pobierać go w czasie wykonania z własnego backendu.

Gdy klucz jest pobierany z backendu (przez vmAsyncExecutor), warto dodać na tym endpoincie kontrole oparte na sesji lub źródle żądania: prawdziwym użytkownikom (ważna sesja, oczekiwane nagłówki Origin/Referer) należy zwracać poprawny klucz, a podejrzanym żądaniom (np. z localhost lub nieoczekiwanego źródła, bez sesji) — klucz-śmieć. Prawdziwi użytkownicy pracują normalnie, natomiast kopia uruchomiona poza Twoim środowiskiem otrzymuje klucz, który niczego nie odszyfruje. Konkretna logika zależy od danej witryny.

Przykłady:

// 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())'

Przykład użycia:

// 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

Włącza asynchroniczny executor VM, dzięki któremu vmBytecodeArrayEncodingKeyGetter może zwracać obiekt Promise (asynchroniczny getter klucza) — klucz deszyfrujący może więc być pobierany w czasie wykonania (żądanie sieciowe, IndexedDB itp.), zamiast być dostępny synchronicznie w momencie ładowania kodu.

Zdecydowanie zalecane dla w pełni asynchronicznych baz kodu. W tym trybie wirtualizowane są wyłącznie funkcje async — funkcji synchronicznej nie da się uczynić asynchroniczną bez zamiany jej wartości zwracanej w Promise i zepsucia kodu wywołującego — więc kod asynchroniczny w całości uzyskuje największe pokrycie. Tryb działa również wtedy, gdy poziom główny jest synchroniczny (np. synchroniczne IIFE lub wrapper UMD): chronione są najbardziej zewnętrzne funkcje async znajdujące się w środku, a części synchroniczne pozostają bez zmian.

Co podlega transformacji: każda najbardziej zewnętrzna funkcja async, gdziekolwiek się pojawia (również zagnieżdżona w synchronicznych wrapperach). Najbardziej zewnętrzna funkcja async w każdym łańcuchu jest chronioną jednostką — wszystko w jej wnętrzu, zarówno synchroniczne, jak i asynchroniczne, zostaje skompilowane razem z nią. Funkcje synchroniczne i zwykłe generatory pozostają bez obfuskacji.

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

Pominięcia i ostrzeżenia. Generatory asynchroniczne również pozostają bez obfuskacji, gdy aktywny jest asynchroniczny getter klucza (generator asynchroniczny musi zwrócić swój iterator synchronicznie i nie może czekać na klucz). W domyślnym trybie vmTargetFunctionsMode: 'root' pominięcia są ciche (wybór jest automatyczny); w trybie comment za każdym razem, gdy jawnie oznaczonej funkcji nie da się zwirtualizować — okazała się synchroniczna albo jest generatorem asynchronicznym przy asynchronicznym getterze klucza — zgłaszane jest ostrzeżenie przez ObfuscationResult.getWarnings().

Asynchroniczny getter klucza wymaga dodatkowo opcji vmBytecodeArrayEncoding wraz z vmBytecodeArrayEncodingKeyGetter.

Przykład użycia:

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

Koduje cele skoków w kodzie bajtowym. Przesunięcia skoków są obliczane w czasie wykonania, co ukrywa strukturę przepływu sterowania (if/else, pętle itd.) przed analizą statyczną.

vmMacroOps

Type: boolean Default: false

Łączy typowe sekwencje instrukcji w pojedyncze opkody „makro”. Na przykład LOAD + ADD + STORE może stać się jedną instrukcją MACRO_ADD_TO_VAR. Utrudnia to rozpoznawanie wzorców i może poprawić wydajność.

vmDebugProtection

Type: boolean Default: false

Dodaje do środowiska uruchomieniowego VM wielowarstwowe zabezpieczenia przed debugowaniem, analizą oraz działaniem modeli LLM. Działa najlepiej ze środowiskami browser/browser-no-eval.

vmSelfDefending

Type: boolean Default: false

Dodaje do środowiska uruchomieniowego VM wielowarstwową ochronę: wykrywanie manipulacji, ochronę przed hookowaniem oraz przed inżynierią wsteczną.

⚠️ Ta opcja wymusza włączenie opcji vmBytecodeArrayEncoding.

⚠️ Wykrywanie wrażliwego środowiska. Ta opcja wiąże zobfuskowany kod z docelowym środowiskiem uruchomieniowym i wykorzystuje zaawansowany fingerprinting przeglądarki do wykrywania narzędzi automatyzujących. Kod chroniony tą opcją celowo przestanie działać, gdy zostanie uruchomiony w:

  • Przeglądarkach headless (headless Chrome/Chromium, PhantomJS)
  • Narzędziach do automatyzacji przeglądarek (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
  • Node.js (gdy target jest ustawiony na browser)
  • jsdom lub podobnych serwerowych emulacjach DOM
  • Środowiskach, w których natywne wbudowane funkcje przeglądarki zostały podhaczone (hooked) lub podmienione

Kod będzie działał poprawnie w zwykłych przeglądarkach (Chrome, Firefox, Safari, Edge), w tym po załadowaniu wewnątrz elementów iframe, w rozszerzeniach przeglądarki (content scripts) oraz w Web Workerach. Jeśli konieczne jest uruchamianie automatycznych testów na chronionym kodzie, w kompilacjach testowych należy wyłączyć vmSelfDefending — ta opcja została zaprojektowana tak, aby uniemożliwiać automatyczną analizę, i nie może być bezpiecznie używana z żadnym frameworkiem automatyzującym.

Zdecydowanie zaleca się stosowanie jej wraz z vmDebugProtection, vmBytecodeArrayEncodingKey oraz vmBytecodeArrayEncodingKeyGetter.

vmDefenseHook

Type: { name: string, aliases?: object } Default: ''

vmDefenseHook przyjmuje obiekt z dwoma kluczami: name (wymagany) i aliases (opcjonalny).

name to globalna funkcja definiowana przez Twoją stronę hostującą, którą mechanizm obronny VM (vmDebugProtection / vmSelfDefending) wywołuje z obiektem sygnału po wykryciu wrogiego sygnału — debuggera lub inspektora, przeglądarki headless / automatyzującej, procesu agenta AI programującego kod, niedozwolonej domeny itp. Służy do raportowania zdarzenia do własnego backendu (np. przez navigator.sendBeacon). Hook jest czystym odbiornikiem telemetrii: jego wartość zwracana jest ignorowana, a brakujący lub zgłaszający wyjątek hook to cichy brak działania, który nigdy nie może wyłączyć mechanizmu obronnego. Aby zmienić to, co mechanizm obronny robi po wykryciu, należy użyć opcji vmDefenseReaction.

aliases opcjonalnie zmienia nazwy pól tego obiektu sygnału — opisano to poniżej w części Zmiana nazw pól sygnału.

Obiekt sygnału. Hook otrzymuje jeden signal:

  • source — konkretny detektor, który zadziałał (zob. tabelę).
  • category — grupa, w ramach której raportuje: automation (przeglądarki nieobsługiwane przez człowieka), debugger (aktywny debugger/inspektor), sandbox (instrumentowany/fałszywy host), domain (naruszenie blokady domeny), tamper (wbudowane funkcje podmienione w czasie wykonania) lub integrity (zmieniono kod samej VM).
  • score / threshold — jak silnie zadziałał detektor oraz wartość, którą musiał osiągnąć; hook zadziała dopiero wtedy, gdy score >= threshold. Większość kontroli działa na zasadzie „wszystko albo nic” (pojedynczy rozstrzygający sygnał); headless sumuje kilka sygnałów dotyczących kształtu przeglądarki, więc jego score jest zwykle wyższy niż threshold.
sourcewykrywacategory
integritysam zobfuskowany kod VM został zmodyfikowanyintegrity
nodekod przeznaczony dla przeglądarki uruchamiany pod Node.jsdebugger
debuggerdołączona lub aktywna sesja debuggera bądź inspektora albo środowisko debugowaniadebugger
headlesskod uruchamiany w przeglądarce headlessautomation
agentkod uruchamiany przez agenta AI programującego kodautomation
timingzatrzymanie wykonania sugerujące punkt przerwania lub debugger krokowydebugger
sandboxkod uruchamiany w piaskownicy lub sfałszowanym środowisku hostasandbox
domainźródło strony nie znajduje się na liście dozwolonych vmDomainLockdomain
nativeHooknatywna wbudowana funkcja została podmieniona lub podhaczonatamper

Rejestrowanie hooka. Należy zdefiniować go jako zwykłą zmienną globalną przed załadowaniem zobfuskowanego bundle’a — środowisko uruchomieniowe VM i jego mechanizmy obronne działają przed Twoim (chronionym) programem, więc wiele detekcji zachodzi już podczas startu:

// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }

Hook zdefiniowany wewnątrz zobfuskowanego kodu źródłowego jest rejestrowany zbyt późno, aby wychwycić detekcje zachodzące podczas startu, a jeśli zostanie skompilowany do VM, nie da się do niego dotrzeć, dopóki nie uruchomi się Twój program. Jest on bezpieczny w obu przypadkach (brakujący hook nie robi nic, a zabezpieczenie przed ponownym wejściem zapobiega niekontrolowanemu działaniu), ale dla pełnego pokrycia należy rejestrować go z wyprzedzeniem. Aby mimo to chronić własną logikę raportowania, rejestrowany hook warto ograniczyć do jednolinijkowego bufora ((window.__vmDet = window.__vmDet || []).push(signal)) i odczytywać/wysyłać ten bufor z poziomu zobfuskowanego kodu.

Zmiana nazw pól sygnału (aliases). Domyślne wartości source/category to opisowe nazwy, więc każdy, kto instrumentuje callback (lub czyta wynik), może rozpoznać zabezpieczenie i wskazać, który detektor zadziałał. aliases zmienia nazwy pól sygnału na wybrane przez Ciebie nieprzejrzyste tokeny, stosowane wewnątrz VM przed wyemitowaniem sygnału, dzięki czemu te nazwy nigdy nie pojawiają się w wyniku ani nie docierają do callbacku. Twoja aplikacja zna własne odwzorowanie i przekazuje tokeny do backendu.

Aliasy działają per pole, rozdzielając zmianę nazw kluczy i wartości: każde pole przyjmuje key (nazwę właściwości otrzymywaną przez callback); tekstowe pola nazw source i category przyjmują też mapę values, natomiast score/threshold są liczbami i przyjmują wyłącznie key. Nazwy, które można odwzorować (wszystko inne jest odrzucane na etapie kompilacji):

  • klucze pólsource, category, score, threshold
  • wartości sourceheadless, agent, node, debugger, timing, sandbox, domain, nativeHook, integrity
  • wartości categoryautomation, 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> }
}

To zabezpieczenie przed fingerprintingiem, a nie utajnianie — odwzorowanie wciąż da się wywnioskować przez wielokrotne testowanie — więc jego jedyną korzyścią jest nieujawnianie stałych, samoopisujących się nazw. Nieustawione wpisy zachowują swoje domyślne nazwy.

Zwykły ciąg znaków (vmDefenseHook: '__vmDetection') jest akceptowany jako skrót dla { name: '__vmDetection' }, ale jest przestarzały — należy preferować postać obiektową.

vmDefenseReaction

Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }

Konfiguruje sposób reakcji każdej kategorii detekcji. Nie włącza niczego — same mechanizmy obronne uruchamiają opcje vmSelfDefending, vmDebugProtection oraz vmDomainLock; ta opcja wybiera jedynie, jak włączony mechanizm obronny reaguje. Jednostką kontroli jest kategoria — każdy detektor w kategorii wprowadza reakcję przypisaną tej kategorii.

Każda kategoria grupuje detektory czuwające nad jednym rodzajem wrogiego warunku. Kategoria reaguje tylko wtedy, gdy włączona jest opcja emitująca jej detektory:

KategoriaWłączana przezReaguje, gdy
automationvmSelfDefending lub vmDebugProtectionKodem steruje oprogramowanie zamiast człowieka: przeglądarka headless lub automatyzująca, framework do scrapingu / testowania albo agent AI programujący kod krokowo przechodzący przez stronę.
debuggervmDebugProtection lub vmSelfDefendingKtoś ma otwarty debugger lub inspektor narzędzi deweloperskich przeglądarki i krok po kroku przechodzi przez działający kod, aby go zrozumieć.
sandboxvmDebugProtectionKod w ogóle nie działa w prawdziwej przeglądarce — został przeniesiony do emulowanego lub skryptowego środowiska JavaScript, aby wykonać go i przeanalizować offline.
domainvmDomainLockKod działa w witrynie, na którą nie wyrażono zgody: host spoza listy dozwolonych vmDomainLock (na przykład Twój bundle skopiowany do cudzej domeny).
tampervmSelfDefendingŚrodowisko JavaScript wokół VM zostało zmodyfikowane, aby ją obserwować lub przejąć, na przykład natywne wbudowane funkcje przeglądarki podmieniono na wersje instrumentowane.
integrityvmSelfDefendingKod samego chronionego bundle’a został zmieniony lub załatany od czasu jego wygenerowania.

Każda kategoria odwzorowuje się na co najmniej jedną z opcji vmSelfDefending, vmDebugProtection i vmDomainLock; nie istnieje kategoria poza tymi trzema opcjami, a reakcja ustawiona dla kategorii, której opcja jest wyłączona, po prostu nie ma żadnego efektu.

Kluczami są te sześć nazw kategorii lub default (rozwiązanie awaryjne dla nieokreślonych kategorii). Wartości to:

  • break — natychmiast przerwij działanie
  • decoy — kontynuuj działanie na zatrutym stanie, po cichu generując błędne wyniki
  • none — nie rób nic lokalnie (tylko telemetria)

Domyślne wartości poszczególnych kategorii pokazano powyżej; kategoria, której nie ustawisz (lub ustawisz na jej wartość domyślną), korzysta z tej wartości domyślnej. default obejmuje każdą kategorię, w tym te poprawne z założenia (integrity, tamper), więc { default: 'none' } to naprawdę nieprzerywająca kompilacja wyłącznie z telemetrią:

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

Sprawia, że znaczenie opkodów zależy od pozycji w kodzie bajtowym. Każda pozycja ma inne odwzorowanie opkodu na procedurę obsługi, wyprowadzane z ziarna, więc ten sam numer opkodu wykonuje różne operacje na różnych pozycjach.

vmCallContextOpcodes

Type: boolean Default: false

Sprawia, że chroniona funkcja zależy od miejsca, z którego jest wywoływana, dzięki czemu nie da się jej wyodrębnić z kodu i uruchomić ani przeanalizować samodzielnie — działa poprawnie wyłącznie wtedy, gdy jest wywoływana przez swoje rzeczywiste miejsca wywołań w programie. Ta opcja wpływa na wydajność w czasie wykonania.

Obecnie obsługiwane są wyłącznie następujące konstrukcje:

  • deklaracje funkcji (function f() {});
  • wyrażenia funkcyjne i funkcje strzałkowe przypisane do zmiennej (const f = () => {});
  • prywatne metody instancji (this.#m()).

W każdym przypadku funkcja musi być zawsze osiągana przez bezpośrednie wywołanie (f(), this.#m()). Jeśli zostanie zapisana w innej zmiennej, przekazana jako argument lub w inny sposób użyta jako wartość, pozostanie niechroniona. Funkcje asynchroniczne są obsługiwane; generatory — nie.

Ta opcja jest eksperymentalna i może zepsuć kod, dlatego przed użyciem należy dokładnie przetestować wynik.

vmStackEncoding

Type: boolean Default: false

Szyfruje wartości na stosie VM w trakcie wykonywania. Wartości są kodowane przy odkładaniu na stos i dekodowane przy zdejmowaniu, więc inspekcja pamięci pokazuje zaszyfrowane dane zamiast rzeczywistych wartości.

Ta opcja mocno wpływa na wydajność.

vmCompactDispatcher

Type: boolean Default: false

Używa pojedynczego executora VM zamiast dwóch (synchronicznego + generatorowego). Zmniejsza rozmiar zobfuskowanego kodu, ale dodaje około 20% narzutu wydajnościowego przy kodzie intensywnie korzystającym z rekurencji.

  • false (domyślnie): dwa executory — optymalna wydajność, większy wynik
  • true: pojedynczy executor — mniejszy wynik, nieco wolniej

vmStringArrayBytecodeOnly

Type: boolean Default: false

Po włączeniu tablica ciągów wyłącznie wyodrębnia ciągi z danych kodu bajtowego — żadne inne ciągi w kodzie nie są przekształcane. Wymusza to włączenie stringArray, nawet jeśli nie ustawiono jej jawnie.

Dlaczego warto: wyodrębnianie wszystkich ciągów środowiska uruchomieniowego VM do tablicy ciągów jest powolne. Ta opcja obejmuje wyodrębnianiem do tablicy ciągów wyłącznie zawartość kodu bajtowego, poprawiając wydajność i chroniąc jednocześnie stałe kodu bajtowego.

  • Gdy vmBytecodeArrayEncoding: false — wyodrębniane są ciągi z pul stałych kodu bajtowego (tablice c)
  • Gdy vmBytecodeArrayEncoding: true — wyodrębniane są zakodowane w base64 ciągi kodu bajtowego najwyższego poziomu
  • stringArrayThreshold nadal steruje tym, jaki procent tych ciągów kodu bajtowego jest wyodrębniany

vmDomainLock

Type: string[] Default: []

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Ogranicza działanie zobfuskowanego kodu do określonych domen i/lub subdomen i jest znacznie trudniejsza do zlokalizowania i usunięcia niż domainLock.

Jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w tej opcji, przeglądarka zostanie przekierowana pod adres URL przekazany w opcji vmDomainLockRedirectUrl, a kolejne chronione wywołania będą zwracać nieprawidłowe wyniki, nawet jeśli przekierowanie zostanie zablokowane.

Wiele domen i subdomen

Kod można zablokować do więcej niż jednej domeny lub subdomeny. Na przykład, aby zablokować go tak, by działał wyłącznie w www.example.com, należy dodać www.example.com. Aby działał w domenie głównej wraz ze wszystkimi subdomenami (example.com, sub.example.com), należy użyć .example.com.

vmDomainLockRedirectUrl

Type: string Default: about:blank

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala przekierować przeglądarkę pod przekazany adres URL, jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w opcji vmDomainLock.

Preset Options

Wysoka obfuskacja, niska wydajność

Wydajność będzie znacznie niższa niż bez obfuskacji

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

Średnia obfuskacja, optymalna wydajność

Wydajność będzie niższa niż bez obfuskacji

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

Niska obfuskacja, wysoka wydajność

Wydajność pozostanie na względnie normalnym poziomie

{
    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 domyślny, wysoka wydajność

{
    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 – bardzo wysoka obfuskacja (maksymalne bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM ze wszystkimi funkcjami wzmacniającymi ochronę, w tym z pośrednim dyspozytorem (indirect dispatch). Zapewnia najsilniejszą ochronę, ale kosztem większego rozmiaru wyniku i znacznie wolniejszego wykonywania.

{
    optionsPreset: 'vm-ultra-high-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 (ochrona przed agentami AI)

Ten preset został zaprojektowany specjalnie tak, aby uniemożliwiać agentom AI i modelom LLM inżynierię wsteczną kodu bajtowego VM. Oparty na vm-default z włączoną samoobroną i ochroną przed debugowaniem. Lżejszy niż vm-high-obfuscation, ale specjalnie utwardzony przeciwko automatycznej analizie.

{
    optionsPreset: 'vm-anti-llm'
}

Obejmuje:

  • Obfuskację kodu bajtowego VM z tablicą ciągów (z vm-default)
  • vmSelfDefending — wykrywanie hooków, hash integralności, fingerprint kodu źródłowego, weryfikację czystego realmu przez iframe, wyprowadzanie klucza szyfrem ARX
  • vmDebugProtection — kontrole antydebugujące w pętli dyspozytora VM
  • debugProtection: false — brak przestarzałej ochrony przed debugowaniem (ochrona przed debugowaniem VM jest lepsza)

VM High – wysoka obfuskacja (najwyższe bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM z większością funkcji wzmacniających ochronę. Zapewnia silną ochronę przy lepszej wydajności niż preset ultra-high.

{
    optionsPreset: 'vm-high-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 – średnia obfuskacja (zrównoważone bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM ze zrównoważonym zestawem funkcji wzmacniających ochronę. Dobry kompromis między bezpieczeństwem a wydajnością.

{
    optionsPreset: 'vm-medium-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 – niska obfuskacja (podstawowe bezpieczeństwo, lepsza wydajność)

Ten preset włącza podstawową obfuskację opartą na kodzie bajtowym VM bez dodatkowych funkcji wzmacniających ochronę. Dobra równowaga między bezpieczeństwem a rozmiarem wyniku.

{
    optionsPreset: 'vm-low-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 + ochrona tablicą ciągów)

Ten preset łączy podstawową obfuskację opartą na kodzie bajtowym VM z ochroną tablicą ciągów. Dobry punkt wyjścia do obfuskacji VM z ochroną ciągów.

{
    optionsPreset: 'vm-default'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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

Kompaktowy kod wynikowy w jednej linii.

config

Type: string Default: ``

Nazwa pliku konfiguracyjnego JS/JSON zawierającego opcje obfuskatora. Zostaną one nadpisane przez opcje przekazane bezpośrednio do CLI

controlFlowFlattening

Type: boolean Default: false

⚠️ Ta opcja znacząco wpływa na wydajność – szybkość działania może spaść nawet 1,5-krotnie. Za pomocą opcji controlFlowFlatteningThreshold można ustawić procent węzłów, których dotyczy spłaszczanie przepływu sterowania.

Włącza spłaszczanie przepływu sterowania w kodzie. Spłaszczanie przepływu sterowania to transformacja struktury kodu źródłowego, która utrudnia zrozumienie programu.

Przykład:

// 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

Prawdopodobieństwo, że transformacja controlFlowFlattening zostanie zastosowana do danego węzła.

To ustawienie jest szczególnie przydatne przy dużym rozmiarze kodu, ponieważ duża liczba transformacji przepływu sterowania może spowolnić kod i zwiększyć jego rozmiar.

controlFlowFlatteningThreshold: 0 jest równoznaczne z controlFlowFlattening: false.

deadCodeInjection

Type: boolean Default: false

⚠️ Drastycznie zwiększa rozmiar zobfuskowanego kodu (nawet o 200%) – należy stosować tylko wtedy, gdy rozmiar zobfuskowanego kodu nie ma znaczenia. Za pomocą opcji deadCodeInjectionThreshold można ustawić procent węzłów, których dotyczy wstrzykiwanie martwego kodu.
⚠️ Ta opcja wymusza włączenie opcji stringArray.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation.

Przy tej opcji do zobfuskowanego kodu dodawane są losowe bloki martwego kodu.

Przykład:

// 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

Pozwala ustawić procent węzłów, których dotyczy deadCodeInjection.

debugProtection

Type: boolean Default: false

⚠️ Może zawiesić przeglądarkę po otwarciu narzędzi deweloperskich.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmDebugProtection.

Ta opcja sprawia, że korzystanie z funkcji debugger w narzędziach deweloperskich staje się niemal niemożliwe (zarówno w przeglądarkach opartych na WebKit, jak i w Mozilla Firefox).

debugProtectionInterval

Type: number Default: 0

⚠️ Może zawiesić przeglądarkę! Stosowanie na własne ryzyko.
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmDebugProtection.

Jeśli ta opcja jest ustawiona, wykorzystywany jest interwał w milisekundach wymuszający tryb debugowania w karcie Console, co utrudnia korzystanie z pozostałych funkcji narzędzi deweloperskich. Działa, gdy włączona jest opcja debugProtection. Zalecana wartość mieści się w przedziale od 2000 do 4000 milisekund.

disableConsoleOutput

Type: boolean Default: false

⚠️ Ta opcja globalnie wyłącza wywołania console dla wszystkich skryptów

Wyłącza możliwość korzystania z console.log, console.info, console.error, console.warn, console.debug, console.exception i console.trace, zastępując je pustymi funkcjami. Utrudnia to korzystanie z debuggera.

domainLock

Type: string[] Default: []

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala uruchamiać zobfuskowany kod źródłowy wyłącznie w określonych domenach i/lub subdomenach. Bardzo utrudnia to skopiowanie kodu źródłowego i uruchomienie go w innym miejscu.

Jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w tej opcji, przeglądarka zostanie przekierowana pod adres URL przekazany w opcji domainLockRedirectUrl.

Wiele domen i subdomen

Kod można zablokować do więcej niż jednej domeny lub subdomeny. Na przykład, aby zablokować go tak, by działał wyłącznie w www.example.com, należy dodać www.example.com. Aby działał w domenie głównej wraz ze wszystkimi subdomenami (example.com, sub.example.com), należy użyć .example.com.

domainLockRedirectUrl

Type: string Default: about:blank

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala przekierować przeglądarkę pod przekazany adres URL, jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w opcji domainLock

exclude

Type: string[] Default: []

Nazwy plików lub wzorce glob wskazujące pliki wykluczone z obfuskacji.

forceTransformStrings

Type: string[] Default: []

Włącza wymuszoną transformację literałów tekstowych pasujących do przekazanych wzorców RegExp.

⚠️ Ta opcja dotyczy wyłącznie ciągów, które nie powinny zostać przekształcone zgodnie z opcją stringArrayThreshold (lub, być może, innymi progami w przyszłości)

Opcja ma priorytet nad opcją reservedStrings, ale nie ma priorytetu nad conditional comments.

Przykład:

	{
		forceTransformStrings: [
			'some-important-value',
			'some-string_\d'
		]
	}

identifierNamesCache

Type: Object | null Default: null

Głównym celem tej opcji jest możliwość używania tych samych nazw identyfikatorów podczas obfuskacji wielu źródeł/plików.

Obecnie obsługiwane są dwa rodzaje identyfikatorów:

  • Identyfikatory globalne:
    • wszystkie identyfikatory globalne zostaną zapisane w pamięci podręcznej;
    • wszystkie dopasowane niezadeklarowane identyfikatory globalne zostaną zastąpione wartościami z pamięci podręcznej.
  • Identyfikatory właściwości, tylko gdy włączona jest opcja renameProperties:
    • wszystkie identyfikatory właściwości zostaną zapisane w pamięci podręcznej;
    • wszystkie dopasowane identyfikatory właściwości zostaną zastąpione wartościami z pamięci podręcznej.

Node.js API

Przekazanie wartości null całkowicie wyłącza pamięć podręczną.

Przekazanie pustego obiektu ({}) włącza zapisywanie nazw identyfikatorów do obiektu pamięci podręcznej (typ TIdentifierNamesCache). Dostęp do tego obiektu uzyskuje się przez wywołanie metody getIdentifierNamesCache obiektu ObfuscationResult.

Powstały obiekt pamięci podręcznej można następnie przekazać jako wartość opcji identifierNamesGenerator, aby użyć tych nazw podczas obfuskacji wszystkich dopasowanych nazw identyfikatorów w kolejnych źródłach.

Przykład:

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 udostępnia inną opcję – --identifier-names-cache-path – która pozwala wskazać ścieżkę do istniejącego pliku .json używanego do odczytu i zapisu pamięci podręcznej nazw identyfikatorów.

Jeśli zostanie przekazana ścieżka do pustego pliku, pamięć podręczna nazw identyfikatorów zostanie zapisana do tego pliku.

Ten plik z istniejącą pamięcią podręczną można ponownie wykorzystać jako wartość opcji --identifier-names-cache-path, aby użyć tych nazw podczas obfuskacji wszystkich dopasowanych nazw identyfikatorów w kolejnych plikach.

identifierNamesGenerator

Type: string Default: hexadecimal

Ustawia generator nazw identyfikatorów.

Dostępne wartości:

  • dictionary: nazwy identyfikatorów z listy identifiersDictionary
  • hexadecimal: nazwy identyfikatorów w rodzaju _0xabc123
  • mangled: krótkie nazwy identyfikatorów, takie jak a, b, c
  • mangled-shuffled: to samo co mangled, ale z przetasowanym alfabetem

identifiersDictionary

Type: string[] Default: []

Ustawia słownik identyfikatorów dla opcji identifierNamesGenerator: dictionary. Każdy identyfikator ze słownika zostanie użyty w kilku wariantach różniących się wielkością poszczególnych znaków. Liczba identyfikatorów w słowniku powinna zatem zależeć od liczby identyfikatorów w oryginalnym kodzie źródłowym.

identifiersPrefix

Type: string Default: ''

Ustawia prefiks dla wszystkich identyfikatorów globalnych.

Tej opcji należy używać przy obfuskacji wielu plików. Pomaga ona uniknąć konfliktów między identyfikatorami globalnymi tych plików. Prefiks powinien być inny dla każdego pliku.

randomIdentifiersPrefix

Type: boolean Default: false

Dodaje do wszystkich identyfikatorów globalnych losowy prefiks (6 znaków alfanumerycznych) generowany na podstawie ziarna. Tej opcji należy używać, aby uniknąć kolizji między osobno zobfuskowanymi bundle’ami ładowanymi do tego samego zasięgu globalnego — dzięki niej nie trzeba ręcznie dobierać unikalnej wartości identifiersPrefix dla każdego bundle’a.

  • Wartość losowa jest wyprowadzana z opcji seed oraz skrótu kodu źródłowego, więc powtarzalne kompilacje z tym samym ziarnem dają ten sam prefiks.
  • W połączeniu z identifiersPrefix losowe znaki są dopisywane na końcu prefiksu podanego przez użytkownika (np. myApp + losowe aBc123myAppaBc123).
  • W połączeniu z vmObfuscation wartość losowa zastępuje domyślny prefiks vm — losowość i tak gwarantuje unikalność.

ignoreImports

Type: boolean Default: false

Zapobiega obfuskacji importów require. Może się przydać w sytuacjach, gdy środowisko uruchomieniowe z jakiegoś powodu wymaga, aby te importy zawierały wyłącznie statyczne ciągi znaków.

inputFileName

Type: string Default: ''

Pozwala ustawić nazwę pliku wejściowego z kodem źródłowym. Nazwa ta będzie używana wewnętrznie podczas generowania mapy źródeł. Wymagana przy korzystaniu z API NodeJS, gdy opcja sourceMapSourcesMode ma wartość sources.

log

Type: boolean Default: false

Włącza wypisywanie informacji do konsoli.

numbersToExpressions

Type: boolean Default: false

Włącza zamianę liczb na wyrażenia

Przykład:

// input
const foo = 1234;

// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;

optionsPreset

Type: string Default: default

Pozwala ustawić preset opcji.

Dostępne wartości:

  • 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.

Wszystkie dodatkowe opcje zostaną scalone z wybranym presetem opcji.

parseHtml

Type: boolean Default: false

Włącza obfuskację kodu JavaScript wewnątrz znaczników <script> w plikach HTML.

Po włączeniu obfuskator:

  • Automatycznie wykrywa, czy wejście jest kodem HTML (sprawdzając znaczniki <!DOCTYPE, <html>, <head>, <body> lub <script>)
  • Wyodrębnia kod JavaScript ze znaczników <script> oznaczonych atrybutem data-javascript-obfuscator
  • Obfuskuje każdy oznaczony skrypt osobno, zachowując strukturę HTML
  • Wstawia zobfuskowany kod z powrotem w pierwotne miejsca

Ważne: obfuskowane są wyłącznie skrypty z atrybutem data-javascript-obfuscator. Każdy oznaczony skrypt jest obfuskowany osobno i niezależnie. Oznacza to, że:

  • Kod wewnątrz oznaczonych znaczników skryptu musi być odizolowany – nie może odwoływać się do zmiennych, funkcji ani klas zdefiniowanych w innych oznaczonych znacznikach skryptu
  • Nieoznaczone skrypty nadal mają dostęp do zmiennych globalnych zdefiniowanych przez oznaczone skrypty (przez deklaracje var lub jawne przypisania do globalThis)
  • Daje to jawną kontrolę nad tym, które skrypty są chronione

Obfuskowane (muszą mieć atrybut data-javascript-obfuscator):

  • <script data-javascript-obfuscator> – zwykłe skrypty
  • <script type="text/javascript" data-javascript-obfuscator> – skrypty z jawnie podanym typem
  • Skrypty z dowolnymi dodatkowymi atrybutami (id, class, inne data-* itd.)

Pomijane (pozostają bez zmian):

  • Skrypty bez atrybutu data-javascript-obfuscator
  • <script type="module"> – moduły ES (nawet z tym atrybutem)
  • <script src="..."> – skrypty zewnętrzne (nawet z tym atrybutem)
  • Puste znaczniki skryptu

Uwaga: przy włączonej opcji parseHtml mapy źródeł nie są generowane, ponieważ nie odwzorowywałyby poprawnie wyniku w formacie HTML.

Przykład:

// 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

⚠️ ta opcja może zepsuć kod. Należy ją włączać tylko wtedy, gdy wiadomo, do czego służy!

Włącza obfuskację nazw zmiennych i funkcji globalnych wraz z deklaracją.

Gdy ta opcja jest wyłączona, a kod wejściowy deklaruje funkcje lub klasy w zasięgu globalnym (tzn. nie jest opakowany w IIFE), ich nazwy pozostają w zobfuskowanym wyniku bez zmian — inne skrypty mogą odwoływać się do nich po nazwie. Przy włączonej opcji vmObfuscation zgłaszane jest ostrzeżenie VMGlobalFunctionNamesNotRenamed z listą tych nazw, ponieważ ciało funkcji jest ukryte w postaci kodu bajtowego, ale czytelna nazwa najwyższego poziomu nadal zdradza, co robi kod (np. modelowi LLM). Aby uniknąć tego ujawnienia, należy opakować kod w IIFE albo włączyć tę opcję.

renameProperties

Type: boolean Default: false

⚠️ ta opcja MOŻE zepsuć kod. Należy ją włączać tylko wtedy, gdy wiadomo, do czego służy!

Włącza zmianę nazw właściwości. Wszystkie wbudowane właściwości DOM oraz właściwości podstawowych klas JavaScriptu zostaną pominięte.

Do przełączania między trybem safe i unsafe tej opcji służy opcja renamePropertiesMode.

Format zmienionych nazw właściwości ustawia się opcją identifierNamesGenerator.

Tym, którym właściwościom zostaną zmienione nazwy, steruje opcja reservedNames.

Przykład:

// 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

⚠️ Nawet w trybie safe opcja renameProperties MOŻE zepsuć kod.

Określa tryb opcji renameProperties:

  • safe – domyślne zachowanie po wydaniu 2.11.0. Próbuje zmieniać nazwy właściwości w bezpieczniejszy sposób, aby zapobiec błędom w czasie wykonania. W tym trybie część właściwości zostanie wykluczona ze zmiany nazw.
  • unsafe – domyślne zachowanie przed wydaniem 2.11.0. Zmienia nazwy właściwości w niebezpieczny sposób, bez żadnych ograniczeń.

Jeśli jeden plik korzysta z właściwości pochodzących z innego pliku, należy użyć opcji identifierNamesCache, aby zachować te same nazwy właściwości w obu plikach.

reservedNames

Type: string[] Default: []

Wyłącza obfuskację i generowanie identyfikatorów pasujących do przekazanych wzorców RegExp.

Przykład:

	{
		reservedNames: [
			'^someVariable',
			'functionParameter_\d'
		]
	}

reservedStrings

Type: string[] Default: []

Wyłącza transformację literałów tekstowych pasujących do przekazanych wzorców RegExp. Dopasowane ciągi pozostaną widoczne w zobfuskowanym wyniku.

Przy obfuskacji VM zarezerwowane ciągi są przechowywane w osobnej, niezaszyfrowanej tablicy, aby pozostały widoczne. Jest to przydatne dla ciągów, które muszą pozostać czytelne, takich jak adresy endpointów API używanych do monitorowania czy identyfikatory bibliotek.

Przykład:

	{
		reservedStrings: [
			'react-native',
			'\.\/src\/test',
			'some-string_\d'
		]
	}

seed

Type: string|number Default: 0

Ta opcja ustawia ziarno (seed) generatora liczb losowych. Przydaje się do uzyskiwania powtarzalnych wyników.

Jeśli ziarno wynosi 0, generator liczb losowych działa bez ziarna.

selfDefending

Type: boolean Default: false

⚠️ Po obfuskacji z tą opcją nie wolno w żaden sposób modyfikować zobfuskowanego kodu, ponieważ każda zmiana, na przykład minifikacja, może uruchomić mechanizm samoobrony i kod przestanie działać!
⚠️ Ta opcja wymusza ustawienie wartości compact na true
⚠️ Ta opcja jest po cichu wyłączana, gdy włączona jest opcja vmObfuscation. Należy wtedy użyć opcji vmSelfDefending.

Ta opcja sprawia, że kod wynikowy jest odporny na formatowanie i zmianę nazw zmiennych. Jeśli ktoś spróbuje użyć na zobfuskowanym kodzie narzędzia upiększającego JavaScript, kod przestanie działać, co utrudnia jego zrozumienie i modyfikację.

simplify

Type: boolean Default: true

Włącza dodatkową obfuskację kodu poprzez upraszczanie.

⚠️ w przyszłych wydaniach obfuskacja literałów boolean (true => !![]) zostanie przeniesiona pod tę opcję.

Przykład:

// 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

Włącza generowanie mapy źródeł dla zobfuskowanego kodu.

Mapy źródeł ułatwiają debugowanie zobfuskowanego kodu źródłowego JavaScript. Jeśli konieczne jest debugowanie na produkcji, osobny plik mapy źródeł można umieścić w niejawnej lokalizacji, a następnie wskazać ją przeglądarce.

sourceMapBaseUrl

Type: string Default: ``

Ustawia bazowy adres URL dla adresu importu mapy źródeł przy sourceMapMode: 'separate'.

Przykład CLI:

javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'

Wynik:

//# sourceMappingURL=http://localhost:9000/out.js.map

sourceMapFileName

Type: string Default: ``

Ustawia nazwę pliku wynikowej mapy źródeł przy sourceMapMode: 'separate'.

Przykład CLI:

javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example

Wynik:

//# sourceMappingURL=http://localhost:9000/example.js.map

sourceMapMode

Type: string Default: separate

Określa tryb generowania mapy źródeł:

  • inline – dodaje mapę źródeł na końcu każdego pliku .js;
  • separate – generuje odpowiadający plik '.map' z mapą źródeł. W przypadku uruchamiania obfuskatora przez CLI dodaje na końcu pliku z zobfuskowanym kodem odnośnik do pliku mapy źródeł //# sourceMappingUrl=file.js.map.

sourceMapSourcesMode

Type: string Default: sources-content

Pozwala sterować polami sources i sourcesContent mapy źródeł:

  • sources-content – dodaje atrapę pola sources oraz pole sourcesContent z oryginalnym kodem źródłowym;
  • sources – dodaje pole sources z poprawnym opisem źródeł i nie dodaje pola sourcesContent. Przy korzystaniu z API NodeJS wymagane jest zdefiniowanie opcji inputFileName, której wartość zostanie użyta jako wartość pola sources.

splitStrings

Type: boolean Default: false

Dzieli literały tekstowe na fragmenty o długości określonej wartością opcji splitStringsChunkLength.

Przykład:

// input
(function(){
    var test = 'abcdefg';
})();

// output
(function(){
    var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();

splitStringsChunkLength

Type: number Default: 10

Ustawia długość fragmentu dla opcji splitStrings.

stringArray

Type: boolean Default: true

Usuwa literały tekstowe i umieszcza je w specjalnej tablicy. Na przykład ciąg "Hello World" w var m = "Hello World"; zostanie zastąpiony czymś w rodzaju var m = _0x12c456[0x1];

stringArrayCallsTransform

Type: boolean Default: false

⚠️ Opcja stringArray musi być włączona

Włącza transformację wywołań do stringArray. Wszystkie argumenty tych wywołań mogą zostać wyodrębnione do osobnego obiektu, w zależności od wartości opcji stringArrayCallsTransformThreshold. Dzięki temu automatyczne wyszukiwanie wywołań tablicy ciągów staje się jeszcze trudniejsze.

Przykład:

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

⚠️ Opcje stringArray i stringArrayCallsTransformThreshold muszą być włączone

Za pomocą tego ustawienia można dostosować prawdopodobieństwo (od 0 do 1) przekształcenia wywołań tablicy ciągów.

stringArrayEncoding

Type: string[] Default: []

⚠️ Opcja stringArray musi być włączona

Ta opcja może spowolnić skrypt.

Koduje wszystkie literały tekstowe z stringArray przy użyciu base64 lub rc4 i wstawia specjalny kod, który dekoduje je z powrotem w czasie wykonania.

Każda wartość stringArray zostanie zakodowana losowo wybranym kodowaniem z przekazanej listy. Umożliwia to jednoczesne stosowanie wielu kodowań.

Dostępne wartości:

  • 'none' (boolean): nie koduje wartości stringArray
  • 'base64' (string): koduje wartość stringArray przy użyciu base64
  • 'rc4' (string): koduje wartość stringArray przy użyciu rc4. Około 30–50% wolniejsze niż base64, ale trudniej odtworzyć pierwotne wartości.

Na przykład przy poniższych wartościach opcji część wartości stringArray nie zostanie zakodowana, a pozostałe zostaną zakodowane kodowaniem base64 oraz rc4:

stringArrayEncoding: [
    'none',
    'base64',
    'rc4'
]

stringArrayIndexesType

Type: string[] Default: ['hexadecimal-number']

⚠️ Opcja stringArray musi być włączona

Pozwala sterować typem indeksów wywołań tablicy ciągów.

Każdy indeks wywołania stringArray zostanie przekształcony zgodnie z losowo wybranym typem z przekazanej listy. Umożliwia to jednoczesne stosowanie wielu typów.

Dostępne wartości:

  • 'hexadecimal-number' (default): przekształca indeksy wywołań tablicy ciągów w liczby szesnastkowe
  • 'hexadecimal-numeric-string': przekształca indeksy wywołań tablicy ciągów w szesnastkowe ciągi liczbowe

Przed wydaniem 2.9.0 javascript-obfuscator przekształcał wszystkie indeksy wywołań tablicy ciągów zgodnie z typem hexadecimal-numeric-string. Utrudnia to nieco ręczną deobfuskację, ale pozwala automatycznym deobfuskatorom łatwo wykrywać takie wywołania.

Nowy typ hexadecimal-number ma na celu utrudnienie automatycznego wykrywania wzorców wywołań tablicy ciągów w kodzie.

W przyszłości zostaną dodane kolejne typy.

stringArrayIndexShift

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Włącza dodatkowe przesunięcie indeksu dla wszystkich wywołań tablicy ciągów

stringArrayRotate

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Przesuwa tablicę stringArray o stałą, losowo wyznaczoną (podczas obfuskacji kodu) liczbę pozycji. Utrudnia to dopasowanie kolejności usuniętych ciągów do ich pierwotnych miejsc.

stringArrayShuffle

Type: boolean Default: true

⚠️ Opcja stringArray musi być włączona

Losowo tasuje elementy tablicy stringArray.

stringArrayWrappersCount

Type: number Default: 1

⚠️ Opcja stringArray musi być włączona

Ustawia liczbę wrapperów dla string array wewnątrz zasięgu głównego oraz każdego zasięgu funkcji. Faktyczna liczba wrapperów w danym zasięgu jest ograniczona liczbą węzłów literal w tym zasięgu.

Przykład:

// 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

⚠️ Opcje stringArray i stringArrayWrappersCount muszą być włączone

Włącza łańcuchowe wywołania między wrapperami string array.

Przykład:

// 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

⚠️ Opcja stringArray musi być włączona
⚠️ Obecnie ta opcja dotyczy wyłącznie wrapperów dodawanych przy wartości function opcji stringArrayWrappersType

Pozwala sterować maksymalną liczbą parametrów wrapperów tablicy ciągów. Wartość domyślna i minimalna to 2. Zalecana wartość mieści się w przedziale od 2 do 5.

stringArrayWrappersType

Type: string Default: variable

⚠️ Opcje stringArray i stringArrayWrappersCount muszą być włączone

Pozwala wybrać typ wrapperów dodawanych przez opcję stringArrayWrappersCount.

Dostępne wartości:

  • 'variable': dodaje wrappery w postaci zmiennych na początku każdego zasięgu. Wysoka wydajność.
  • 'function': dodaje wrappery w postaci funkcji w losowych miejscach wewnątrz każdego zasięgu. Wydajność niższa niż przy variable, ale obfuskacja jest ostrzejsza.

Zdecydowanie zaleca się stosowanie wrapperów function dla silniejszej obfuskacji, o ile spadek wydajności nie ma dużego wpływu na zobfuskowaną aplikację.

Przykład dla wartości opcji '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

⚠️ Opcja stringArray musi być włączona

Za pomocą tego ustawienia można dostosować prawdopodobieństwo (od 0 do 1), że literał tekstowy zostanie umieszczony w stringArray.

To ustawienie jest szczególnie przydatne przy dużym rozmiarze kodu, ponieważ powoduje ono wielokrotne wywołania string array i może spowolnić kod.

stringArrayThreshold: 0 jest równoznaczne z stringArray: false.

strictMode

Type: boolean | null Default: null

Pozwala określić, jak obfuskator ma traktować kod w kontekście trybu ścisłego (strict mode) JavaScriptu.

Dostępne wartości:

  • null (domyślnie) – automatycznie wykrywa tryb ścisły na podstawie kodu. Jeśli kod zawiera jawną dyrektywę 'use strict', składnię modułów ES lub metody klas, jest traktowany jako kod w trybie ścisłym. W przeciwnym razie zakładany jest tryb swobodny (sloppy mode).
  • true – wymusza traktowanie całego kodu jako kodu w trybie ścisłym, nawet bez jawnej dyrektywy 'use strict'. Należy stosować, gdy kod będzie uruchamiany w kontekście trybu ścisłego (np. w modułach ES, bundlerach lub nowoczesnych frameworkach).
  • false – jako kod w trybie ścisłym traktowane są wyłącznie fragmenty z jawnymi wskaźnikami trybu ścisłego ('use strict', moduły ES, metody klas). Dziedziczenie z zasięgu nadrzędnego nadal obowiązuje zgodnie ze specyfikacją JS.

target

Type: string Default: browser

Pozwala ustawić środowisko docelowe zobfuskowanego kodu.

Dostępne wartości:

  • browser (domyślnie) — standardowe środowisko strony internetowej. Kod wynikowy jest identyczny jak dla node, ale niektórych opcji przeznaczonych dla przeglądarki nie można używać ze środowiskiem node
  • browser-no-eval — tak samo jak browser, ale kod wynikowy nie używa eval(). Należy stosować, gdy strona docelowa ma politykę Content Security Policy zabraniającą eval/unsafe-eval.
  • node — środowisko Node.js. Opcje przeznaczone dla przeglądarki są wyłączone (wymagają window/document, a w Node nie robiłyby nic lub zgłaszałyby błąd). Część mechanizmów obronnych vmSelfDefending opartych na API dostępnych wyłącznie w przeglądarce — wykrywanie przeglądarki headless, odtwarzanie czystego realmu przy użyciu iframe, kontrole antyinspektorowe i sprawdzanie DOM — nie jest generowana dla tego środowiska.
  • service-worker — kontekst Service Workera. Brak window, brak document, inny obiekt globalny self.
  • userscript — piaskownica menedżera userscriptów (np. Tampermonkey). Mechanizmy obronne vmSelfDefending są odpowiednio dostosowywane.
  • bytenode — kod Node.js, który po obfuskacji zostanie skompilowany loaderem bytenode (kod bajtowy V8 z pamięci podręcznej, .jsc). Sam obfuskator nie uruchamia bytenode; generuje kod JavaScript po obfuskacji VM, którego środowisko uruchomieniowe jest zbudowane tak, aby przetrwało etap kompilacji przez bytenode, a mechanizmy obronne vmSelfDefending są odpowiednio dostosowywane. Aby otrzymać końcowy plik .jsc, należy samodzielnie uruchomić bytenode na zobfuskowanym kodzie wynikowym.

transformObjectKeys

Type: boolean Default: false

Włącza transformację kluczy obiektów.

Przykład:

// 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

Określa, które nieblokujące ostrzeżenia obfuskacji są zwracane przez metodę ObfuscationResult.getWarnings().

Dostępne wartości:

  • 'all' (domyślnie) — zwracane są wszystkie ostrzeżenia.
  • 'none' — wszystkie ostrzeżenia są pomijane.
  • obiekt mapujący typy ostrzeżeń na wartości logiczne — typ przypisany do false jest pomijany; każdy typ nieobecny w mapie (lub przypisany do true) pozostaje włączony. Na przykład { "VMGlobalFunctionNamesNotRenamed": false } zachowuje wszystkie ostrzeżenia z wyjątkiem tego jednego.

Typy ostrzeżeń:

  • VMGlobalFunctionNamesNotRenamed — przy włączonej opcji vmObfuscation nazwy deklaracji funkcji i klas najwyższego poziomu oraz zmiennych, którym przypisano wyrażenie funkcyjne, funkcję strzałkową lub wyrażenie klasowe, pozostały bez zmian (opcja renameGlobals jest wyłączona, a kod nie jest opakowany w IIFE), więc pozostają czytelne w wyniku, mimo że ciała funkcji są ukryte w postaci kodu bajtowego. Nazwy eksportowane nie są zgłaszane.
  • VMTopLevelInitializerNotVirtualized — inicjalizatory zmiennych najwyższego poziomu pozostały przy obfuskacji VM zwykłym kodem JavaScript, ponieważ opcja vmWrapTopLevelInitializers jest wyłączona lub nie zdołała ich zwirtualizować.
  • DynamicCodeRenameRisk — kod tworzy funkcję z ciągu znaków w czasie wykonania (bezpośredni eval, konstruktor Function lub fn.toString() wstrzyknięty do znacznika <script>/Workera), przez co może odwoływać się do identyfikatorów, których nazwy zmienił obfuskator.
  • VMDynamicCodeSkipped — funkcja została pominięta przy generowaniu kodu bajtowego VM, ponieważ zawiera bezpośredni eval, dynamiczne new Function albo Function (zob. vmForceCompileDynamicCode).
  • VMSyncFunctionSkippedInAsyncMode — przy włączonej opcji vmAsyncExecutor funkcja jawnie oznaczona w trybie comment okazała się synchroniczna i została pominięta (w tym trybie wirtualizowane są wyłącznie funkcje asynchroniczne).
  • VMAsyncGeneratorSkippedInAsyncMode — przy włączonej opcji vmAsyncExecutor i aktywnym asynchronicznym getterze klucza nie udało się zwirtualizować oznaczonego generatora asynchronicznego (musi on zwracać swój iterator synchronicznie).
  • BrowserTargetWithNodeStyleCode — kod wygląda na przeznaczony dla Node.js (np. require('fs'), __dirname, process.argv), podczas gdy opcja target jest ustawiona na środowisko przeglądarkowe.

vmObfuscation

Type: boolean Default: false

Włącza obfuskację opartą na kodzie bajtowym VM. Po jej włączeniu funkcje JavaScript są kompilowane do niestandardowego kodu bajtowego wykonywanego przez osadzoną maszynę wirtualną. Zapewnia to najwyższy poziom ochrony, ponieważ pierwotna logika kodu zostaje całkowicie przekształcona.

Przykład: Czytelny kod w rodzaju return qty * price zamienia się w listę liczb, na przykład [0x15,0x03,0x17,...], którą potrafi wykonać wyłącznie osadzony interpreter VM. Pierwotna logika nie jest już widoczna jako kod JavaScript.

vmTargetFunctions

Type: string[] Default: []

Pozwala wskazać po nazwie dokładnie te funkcje najwyższego poziomu, które mają zostać objęte ochroną VM.

Przykład:

{
    vmObfuscation: true,
    vmTargetFunctions: ['someFunctionName']
}

Wynik: ochroną VM zostaną objęte wyłącznie te trzy funkcje. Cała reszta pozostanie zwykłym (choć nadal zobfuskowanym) kodem JavaScript. Idealne rozwiązanie do ochrony wrażliwej weryfikacji licencji lub logiki uwierzytelniania przy zachowaniu lekkości pozostałej części kodu.

vmExcludeFunctions

Type: string[] Default: []

Pozwala wskazać funkcje najwyższego poziomu, które nigdy nie mają być objęte ochroną VM. Ma pierwszeństwo przed pozostałymi ustawieniami.

Przykład:

{
    vmObfuscation: true,
    vmExcludeFunctions: ['someFunctionName']
}

Kiedy stosować: funkcje najwyższego poziomu krytyczne dla wydajności (pętle animacji, przetwarzanie danych w czasie rzeczywistym) można wykluczyć, aby uniknąć narzutu VM, chroniąc jednocześnie całą resztę.

vmTargetFunctionsMode

Type: string Default: root

Określa sposób wyboru funkcji i metod do obfuskacji VM.

TrybOpis
rootZachowanie domyślne. Do obfuskacji VM brane są pod uwagę wyłącznie funkcje najwyższego poziomu. Do filtrowania służą lista dozwolonych vmTargetFunctions oraz lista wykluczeń vmExcludeFunctions.
commentObfuskacji VM podlegają wyłącznie funkcje i metody oznaczone komentarzem /* javascript-obfuscator:vm */. Działa dla funkcji i metod na dowolnym poziomie zagnieżdżenia.

Przykład – tryb 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'
}

Kiedy stosować: gdy potrzebna jest chirurgiczna kontrola nad tym, które dokładnie funkcje zostaną objęte ochroną VM, zwłaszcza funkcje zagnieżdżone zawierające wrażliwą logikę. W przeciwieństwie do vmTargetFunctions, które działa wyłącznie dla nazwanych funkcji najwyższego poziomu, tryb comment pozwala chronić dowolną funkcję w dowolnym miejscu kodu.

vmForceCompileDynamicCode

Type: boolean Default: false

Określa, co obfuskacja VM robi z funkcją zawierającą bezpośrednie wywołanie eval, new Function(...) lub Function(...).

Domyślnie taka funkcja (oraz każda funkcja zdefiniowana w jej wnętrzu) jest pomijana przy generowaniu kodu bajtowego VM, a w result.getWarnings() zgłaszane jest ostrzeżenie VMDynamicCodeSkipped. Dzieje się tak dlatego, że kod źródłowy budowany w czasie wykonania może odwoływać się do identyfikatorów z otaczającego łańcucha zasięgów — identyfikatorów, których nazwy zmienił obfuskator.

Po ustawieniu wartości true funkcja mimo wszystko zostaje przekształcona w kod bajtowy, a ostrzeżenie VMDynamicCodeSkipped nie jest już zgłaszane.

Osobne ostrzeżenie DynamicCodeRenameRisk jest zgłaszane niezależnie od tej opcji, ponieważ opisywane przez nie ryzyko związane ze zmianą nazw nie ma związku z pomijaniem funkcji przez VM — włączenie tej opcji w żaden sposób nie czyni tego wzorca bezpieczniejszym.

// Source code
function loadConfig(src) {
    return eval(src);
}
loadConfig('1 + 2');
// Options
{
    vmObfuscation: true,
    vmForceCompileDynamicCode: true
}

Przy wyłączonej opcji (domyślnie) loadConfig pozostaje zwykłym kodem JavaScript. Przy włączonej opcji loadConfig jest kompilowana do kodu bajtowego VM jak każda inna funkcja. Należy z tego korzystać po sprawdzeniu miejsca wywołania i upewnieniu się, że kod budowany w czasie wykonania nie zależy od identyfikatorów z domknięcia, których nazwy zostały zmienione.

vmWrapTopLevelInitializers

Type: boolean Default: false

Opakowuje część inicjalizatorów zmiennych najwyższego poziomu w IIFE (natychmiast wywoływane wyrażenia funkcyjne), dzięki czemu mogą zostać poddane obfuskacji VM.

Co robi: Bez tej opcji stałe i zmienne najwyższego poziomu pozostają widoczne w wyniku:

// Input
const MY_STRING = "my-string";

// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string";  // String is visible!

Po włączeniu tej opcji inicjalizator zostaje opakowany w IIFE, które podlega obfuskacji VM:

// Input
const MY_STRING = "my-string";

// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })();  // String hidden in bytecode

Uwaga: ta opcja działa wyłącznie wtedy, gdy vmTargetFunctionsMode ma wartość 'root' (domyślną).

Ostrzeżenia: za każdym razem, gdy przy obfuskacji VM inicjalizator najwyższego poziomu pozostanie zwykłym kodem JavaScript, zgłaszane jest ostrzeżenie VMTopLevelInitializerNotVirtualized z listą nazw zmiennych, których to dotyczy. Obejmuje ono: wyłączenie tej opcji, inicjalizatory, które opcja musiała pominąć (każdy wraz z powodem — np. inicjalizator odwołuje się do sąsiedniego deklaratora albo zawiera await najwyższego poziomu), oraz tryb vmAsyncExecutor, w którym synchronicznych wrapperów w ogóle nie da się zwirtualizować.

vmDynamicOpcodes

Type: boolean Default: false

Sprawia, że interpreter VM jest mniejszy i unikalny dla każdej kompilacji.

Co robi:

  1. Odfiltrowuje nieużywane instrukcje – jeśli kod nie korzysta z klas, instrukcje związane z klasami są całkowicie usuwane
  2. Losuje strukturę – kolejność procedur obsługi instrukcji jest tasowana przy każdej kompilacji

W efekcie wynik jest mniejszy, a każda kompilacja wygląda inaczej.

vmBytecodeEncoding

Type: boolean Default: false

Koduje każdą instrukcję kodu bajtowego. Instrukcje są dekodowane pojedynczo w trakcie wykonywania.

vmBytecodeArrayEncoding

Type: boolean Default: false

Koduje całą tablicę kodu bajtowego jako pojedynczy blok. Tablica jest dekodowana jednorazowo przy starcie, zanim rozpocznie się wykonywanie. Warto stosować razem z vmBytecodeEncoding, aby uzyskać dwie warstwy ochrony.

vmBytecodeArrayEncodingKey

Type: string Default: ''

Własny klucz szyfrujący dla kodowania tablicy kodu bajtowego. Po ustawieniu używany jest ten klucz zamiast domyślnego klucza wyprowadzanego ze środowiska. Klucz musi zostać dostarczony w czasie wykonania przez vmBytecodeArrayEncodingKeyGetter.

Ta opcja wynosi klucz szyfrujący na zewnątrz — nie jest on osadzony w samym zobfuskowanym kodzie. Klucz jest wprawdzie nadal dostępny w czasie wykonania (a więc nie jest naprawdę tajny), ale takie rozdzielenie uniemożliwia narzędziom do analizy statycznej znalezienie go na podstawie samego kodu.

Ważne: klucz musi być dostępny synchronicznie w momencie ładowania zobfuskowanego kodu. Należy korzystać z synchronicznych źródeł danych, takich jak ciasteczka, localStorage, sessionStorage, zmienne globalne lub elementy DOM (np. znaczniki meta wstrzykiwane przez serwer). Metod asynchronicznych, takich jak fetch(), nie można użyć bezpośrednio w wyrażeniu gettera klucza.

vmBytecodeArrayEncodingKeyGetter

Type: string Default: ''

Synchroniczne wyrażenie JavaScript, które zwraca klucz szyfrujący w czasie wykonania. Wyrażenie to jest obliczane w momencie załadowania zobfuskowanego kodu i musi zwrócić dokładnie ten sam klucz, który podano w vmBytecodeArrayEncodingKey. Aby uzyskiwać klucz asynchronicznie (jako Promise), należy włączyć opcję vmAsyncExecutor.

Uwaga: getter zwracający obiekt Promise wymaga opcji vmAsyncExecutor. Nie da się tego sprawdzić na etapie kompilacji, więc getter zwracający Promise przy wyłączonej opcji vmAsyncExecutor zawiedzie w czasie wykonania — dekoder otrzyma obiekt Promise zamiast klucza.

Zobfuskowany kod zadziała wyłącznie wtedy, gdy getter klucza zwróci dokładnie ten sam klucz, którego użyto podczas obfuskacji. Jeśli klucze się nie zgadzają, odszyfrowanie się nie powiedzie, a kod będzie generował śmieci lub błędy. Jeśli getter klucza zwróci undefined, null albo pusty ciąg, kod zgłosi błąd: „VM decryption key not available”.

Ważne: klucz należy trzymać poza tym samym plikiem/skryptem co zobfuskowany kod — umieszczenie go tam pozwala odzyskać go nawet czysto statycznym przeskanowaniem bundle’a. Zamiast tego należy przechowywać go w osobnym źródle: w ciasteczkach ustawianych przez serwer, w localStorage wypełnianym przez inny skrypt, w znaczniku meta HTML wstrzykiwanym przez serwer, w zmiennej globalnej ustawianej przez inny skrypt lub (przy włączonej opcji vmAsyncExecutor) pobierać go w czasie wykonania z własnego backendu.

Gdy klucz jest pobierany z backendu (przez vmAsyncExecutor), warto dodać na tym endpoincie kontrole oparte na sesji lub źródle żądania: prawdziwym użytkownikom (ważna sesja, oczekiwane nagłówki Origin/Referer) należy zwracać poprawny klucz, a podejrzanym żądaniom (np. z localhost lub nieoczekiwanego źródła, bez sesji) — klucz-śmieć. Prawdziwi użytkownicy pracują normalnie, natomiast kopia uruchomiona poza Twoim środowiskiem otrzymuje klucz, który niczego nie odszyfruje. Konkretna logika zależy od danej witryny.

Przykłady:

// 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())'

Przykład użycia:

// 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

Włącza asynchroniczny executor VM, dzięki któremu vmBytecodeArrayEncodingKeyGetter może zwracać obiekt Promise (asynchroniczny getter klucza) — klucz deszyfrujący może więc być pobierany w czasie wykonania (żądanie sieciowe, IndexedDB itp.), zamiast być dostępny synchronicznie w momencie ładowania kodu.

Zdecydowanie zalecane dla w pełni asynchronicznych baz kodu. W tym trybie wirtualizowane są wyłącznie funkcje async — funkcji synchronicznej nie da się uczynić asynchroniczną bez zamiany jej wartości zwracanej w Promise i zepsucia kodu wywołującego — więc kod asynchroniczny w całości uzyskuje największe pokrycie. Tryb działa również wtedy, gdy poziom główny jest synchroniczny (np. synchroniczne IIFE lub wrapper UMD): chronione są najbardziej zewnętrzne funkcje async znajdujące się w środku, a części synchroniczne pozostają bez zmian.

Co podlega transformacji: każda najbardziej zewnętrzna funkcja async, gdziekolwiek się pojawia (również zagnieżdżona w synchronicznych wrapperach). Najbardziej zewnętrzna funkcja async w każdym łańcuchu jest chronioną jednostką — wszystko w jej wnętrzu, zarówno synchroniczne, jak i asynchroniczne, zostaje skompilowane razem z nią. Funkcje synchroniczne i zwykłe generatory pozostają bez obfuskacji.

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

Pominięcia i ostrzeżenia. Generatory asynchroniczne również pozostają bez obfuskacji, gdy aktywny jest asynchroniczny getter klucza (generator asynchroniczny musi zwrócić swój iterator synchronicznie i nie może czekać na klucz). W domyślnym trybie vmTargetFunctionsMode: 'root' pominięcia są ciche (wybór jest automatyczny); w trybie comment za każdym razem, gdy jawnie oznaczonej funkcji nie da się zwirtualizować — okazała się synchroniczna albo jest generatorem asynchronicznym przy asynchronicznym getterze klucza — zgłaszane jest ostrzeżenie przez ObfuscationResult.getWarnings().

Asynchroniczny getter klucza wymaga dodatkowo opcji vmBytecodeArrayEncoding wraz z vmBytecodeArrayEncodingKeyGetter.

Przykład użycia:

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

Koduje cele skoków w kodzie bajtowym. Przesunięcia skoków są obliczane w czasie wykonania, co ukrywa strukturę przepływu sterowania (if/else, pętle itd.) przed analizą statyczną.

vmMacroOps

Type: boolean Default: false

Łączy typowe sekwencje instrukcji w pojedyncze opkody „makro”. Na przykład LOAD + ADD + STORE może stać się jedną instrukcją MACRO_ADD_TO_VAR. Utrudnia to rozpoznawanie wzorców i może poprawić wydajność.

vmDebugProtection

Type: boolean Default: false

Dodaje do środowiska uruchomieniowego VM wielowarstwowe zabezpieczenia przed debugowaniem, analizą oraz działaniem modeli LLM. Działa najlepiej ze środowiskami browser/browser-no-eval.

vmSelfDefending

Type: boolean Default: false

Dodaje do środowiska uruchomieniowego VM wielowarstwową ochronę: wykrywanie manipulacji, ochronę przed hookowaniem oraz przed inżynierią wsteczną.

⚠️ Ta opcja wymusza włączenie opcji vmBytecodeArrayEncoding.

⚠️ Wykrywanie wrażliwego środowiska. Ta opcja wiąże zobfuskowany kod z docelowym środowiskiem uruchomieniowym i wykorzystuje zaawansowany fingerprinting przeglądarki do wykrywania narzędzi automatyzujących. Kod chroniony tą opcją celowo przestanie działać, gdy zostanie uruchomiony w:

  • Przeglądarkach headless (headless Chrome/Chromium, PhantomJS)
  • Narzędziach do automatyzacji przeglądarek (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
  • Node.js (gdy target jest ustawiony na browser)
  • jsdom lub podobnych serwerowych emulacjach DOM
  • Środowiskach, w których natywne wbudowane funkcje przeglądarki zostały podhaczone (hooked) lub podmienione

Kod będzie działał poprawnie w zwykłych przeglądarkach (Chrome, Firefox, Safari, Edge), w tym po załadowaniu wewnątrz elementów iframe, w rozszerzeniach przeglądarki (content scripts) oraz w Web Workerach. Jeśli konieczne jest uruchamianie automatycznych testów na chronionym kodzie, w kompilacjach testowych należy wyłączyć vmSelfDefending — ta opcja została zaprojektowana tak, aby uniemożliwiać automatyczną analizę, i nie może być bezpiecznie używana z żadnym frameworkiem automatyzującym.

Zdecydowanie zaleca się stosowanie jej wraz z vmDebugProtection, vmBytecodeArrayEncodingKey oraz vmBytecodeArrayEncodingKeyGetter.

vmDefenseHook

Type: { name: string, aliases?: object } Default: ''

vmDefenseHook przyjmuje obiekt z dwoma kluczami: name (wymagany) i aliases (opcjonalny).

name to globalna funkcja definiowana przez Twoją stronę hostującą, którą mechanizm obronny VM (vmDebugProtection / vmSelfDefending) wywołuje z obiektem sygnału po wykryciu wrogiego sygnału — debuggera lub inspektora, przeglądarki headless / automatyzującej, procesu agenta AI programującego kod, niedozwolonej domeny itp. Służy do raportowania zdarzenia do własnego backendu (np. przez navigator.sendBeacon). Hook jest czystym odbiornikiem telemetrii: jego wartość zwracana jest ignorowana, a brakujący lub zgłaszający wyjątek hook to cichy brak działania, który nigdy nie może wyłączyć mechanizmu obronnego. Aby zmienić to, co mechanizm obronny robi po wykryciu, należy użyć opcji vmDefenseReaction.

aliases opcjonalnie zmienia nazwy pól tego obiektu sygnału — opisano to poniżej w części Zmiana nazw pól sygnału.

Obiekt sygnału. Hook otrzymuje jeden signal:

  • source — konkretny detektor, który zadziałał (zob. tabelę).
  • category — grupa, w ramach której raportuje: automation (przeglądarki nieobsługiwane przez człowieka), debugger (aktywny debugger/inspektor), sandbox (instrumentowany/fałszywy host), domain (naruszenie blokady domeny), tamper (wbudowane funkcje podmienione w czasie wykonania) lub integrity (zmieniono kod samej VM).
  • score / threshold — jak silnie zadziałał detektor oraz wartość, którą musiał osiągnąć; hook zadziała dopiero wtedy, gdy score >= threshold. Większość kontroli działa na zasadzie „wszystko albo nic” (pojedynczy rozstrzygający sygnał); headless sumuje kilka sygnałów dotyczących kształtu przeglądarki, więc jego score jest zwykle wyższy niż threshold.
sourcewykrywacategory
integritysam zobfuskowany kod VM został zmodyfikowanyintegrity
nodekod przeznaczony dla przeglądarki uruchamiany pod Node.jsdebugger
debuggerdołączona lub aktywna sesja debuggera bądź inspektora albo środowisko debugowaniadebugger
headlesskod uruchamiany w przeglądarce headlessautomation
agentkod uruchamiany przez agenta AI programującego kodautomation
timingzatrzymanie wykonania sugerujące punkt przerwania lub debugger krokowydebugger
sandboxkod uruchamiany w piaskownicy lub sfałszowanym środowisku hostasandbox
domainźródło strony nie znajduje się na liście dozwolonych vmDomainLockdomain
nativeHooknatywna wbudowana funkcja została podmieniona lub podhaczonatamper

Rejestrowanie hooka. Należy zdefiniować go jako zwykłą zmienną globalną przed załadowaniem zobfuskowanego bundle’a — środowisko uruchomieniowe VM i jego mechanizmy obronne działają przed Twoim (chronionym) programem, więc wiele detekcji zachodzi już podczas startu:

// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }

Hook zdefiniowany wewnątrz zobfuskowanego kodu źródłowego jest rejestrowany zbyt późno, aby wychwycić detekcje zachodzące podczas startu, a jeśli zostanie skompilowany do VM, nie da się do niego dotrzeć, dopóki nie uruchomi się Twój program. Jest on bezpieczny w obu przypadkach (brakujący hook nie robi nic, a zabezpieczenie przed ponownym wejściem zapobiega niekontrolowanemu działaniu), ale dla pełnego pokrycia należy rejestrować go z wyprzedzeniem. Aby mimo to chronić własną logikę raportowania, rejestrowany hook warto ograniczyć do jednolinijkowego bufora ((window.__vmDet = window.__vmDet || []).push(signal)) i odczytywać/wysyłać ten bufor z poziomu zobfuskowanego kodu.

Zmiana nazw pól sygnału (aliases). Domyślne wartości source/category to opisowe nazwy, więc każdy, kto instrumentuje callback (lub czyta wynik), może rozpoznać zabezpieczenie i wskazać, który detektor zadziałał. aliases zmienia nazwy pól sygnału na wybrane przez Ciebie nieprzejrzyste tokeny, stosowane wewnątrz VM przed wyemitowaniem sygnału, dzięki czemu te nazwy nigdy nie pojawiają się w wyniku ani nie docierają do callbacku. Twoja aplikacja zna własne odwzorowanie i przekazuje tokeny do backendu.

Aliasy działają per pole, rozdzielając zmianę nazw kluczy i wartości: każde pole przyjmuje key (nazwę właściwości otrzymywaną przez callback); tekstowe pola nazw source i category przyjmują też mapę values, natomiast score/threshold są liczbami i przyjmują wyłącznie key. Nazwy, które można odwzorować (wszystko inne jest odrzucane na etapie kompilacji):

  • klucze pólsource, category, score, threshold
  • wartości sourceheadless, agent, node, debugger, timing, sandbox, domain, nativeHook, integrity
  • wartości categoryautomation, 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> }
}

To zabezpieczenie przed fingerprintingiem, a nie utajnianie — odwzorowanie wciąż da się wywnioskować przez wielokrotne testowanie — więc jego jedyną korzyścią jest nieujawnianie stałych, samoopisujących się nazw. Nieustawione wpisy zachowują swoje domyślne nazwy.

Zwykły ciąg znaków (vmDefenseHook: '__vmDetection') jest akceptowany jako skrót dla { name: '__vmDetection' }, ale jest przestarzały — należy preferować postać obiektową.

vmDefenseReaction

Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }

Konfiguruje sposób reakcji każdej kategorii detekcji. Nie włącza niczego — same mechanizmy obronne uruchamiają opcje vmSelfDefending, vmDebugProtection oraz vmDomainLock; ta opcja wybiera jedynie, jak włączony mechanizm obronny reaguje. Jednostką kontroli jest kategoria — każdy detektor w kategorii wprowadza reakcję przypisaną tej kategorii.

Każda kategoria grupuje detektory czuwające nad jednym rodzajem wrogiego warunku. Kategoria reaguje tylko wtedy, gdy włączona jest opcja emitująca jej detektory:

KategoriaWłączana przezReaguje, gdy
automationvmSelfDefending lub vmDebugProtectionKodem steruje oprogramowanie zamiast człowieka: przeglądarka headless lub automatyzująca, framework do scrapingu / testowania albo agent AI programujący kod krokowo przechodzący przez stronę.
debuggervmDebugProtection lub vmSelfDefendingKtoś ma otwarty debugger lub inspektor narzędzi deweloperskich przeglądarki i krok po kroku przechodzi przez działający kod, aby go zrozumieć.
sandboxvmDebugProtectionKod w ogóle nie działa w prawdziwej przeglądarce — został przeniesiony do emulowanego lub skryptowego środowiska JavaScript, aby wykonać go i przeanalizować offline.
domainvmDomainLockKod działa w witrynie, na którą nie wyrażono zgody: host spoza listy dozwolonych vmDomainLock (na przykład Twój bundle skopiowany do cudzej domeny).
tampervmSelfDefendingŚrodowisko JavaScript wokół VM zostało zmodyfikowane, aby ją obserwować lub przejąć, na przykład natywne wbudowane funkcje przeglądarki podmieniono na wersje instrumentowane.
integrityvmSelfDefendingKod samego chronionego bundle’a został zmieniony lub załatany od czasu jego wygenerowania.

Każda kategoria odwzorowuje się na co najmniej jedną z opcji vmSelfDefending, vmDebugProtection i vmDomainLock; nie istnieje kategoria poza tymi trzema opcjami, a reakcja ustawiona dla kategorii, której opcja jest wyłączona, po prostu nie ma żadnego efektu.

Kluczami są te sześć nazw kategorii lub default (rozwiązanie awaryjne dla nieokreślonych kategorii). Wartości to:

  • break — natychmiast przerwij działanie
  • decoy — kontynuuj działanie na zatrutym stanie, po cichu generując błędne wyniki
  • none — nie rób nic lokalnie (tylko telemetria)

Domyślne wartości poszczególnych kategorii pokazano powyżej; kategoria, której nie ustawisz (lub ustawisz na jej wartość domyślną), korzysta z tej wartości domyślnej. default obejmuje każdą kategorię, w tym te poprawne z założenia (integrity, tamper), więc { default: 'none' } to naprawdę nieprzerywająca kompilacja wyłącznie z telemetrią:

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

Sprawia, że znaczenie opkodów zależy od pozycji w kodzie bajtowym. Każda pozycja ma inne odwzorowanie opkodu na procedurę obsługi, wyprowadzane z ziarna, więc ten sam numer opkodu wykonuje różne operacje na różnych pozycjach.

vmCallContextOpcodes

Type: boolean Default: false

Sprawia, że chroniona funkcja zależy od miejsca, z którego jest wywoływana, dzięki czemu nie da się jej wyodrębnić z kodu i uruchomić ani przeanalizować samodzielnie — działa poprawnie wyłącznie wtedy, gdy jest wywoływana przez swoje rzeczywiste miejsca wywołań w programie. Ta opcja wpływa na wydajność w czasie wykonania.

Obecnie obsługiwane są wyłącznie następujące konstrukcje:

  • deklaracje funkcji (function f() {});
  • wyrażenia funkcyjne i funkcje strzałkowe przypisane do zmiennej (const f = () => {});
  • prywatne metody instancji (this.#m()).

W każdym przypadku funkcja musi być zawsze osiągana przez bezpośrednie wywołanie (f(), this.#m()). Jeśli zostanie zapisana w innej zmiennej, przekazana jako argument lub w inny sposób użyta jako wartość, pozostanie niechroniona. Funkcje asynchroniczne są obsługiwane; generatory — nie.

Ta opcja jest eksperymentalna i może zepsuć kod, dlatego przed użyciem należy dokładnie przetestować wynik.

vmStackEncoding

Type: boolean Default: false

Szyfruje wartości na stosie VM w trakcie wykonywania. Wartości są kodowane przy odkładaniu na stos i dekodowane przy zdejmowaniu, więc inspekcja pamięci pokazuje zaszyfrowane dane zamiast rzeczywistych wartości.

Ta opcja mocno wpływa na wydajność.

vmCompactDispatcher

Type: boolean Default: false

Używa pojedynczego executora VM zamiast dwóch (synchronicznego + generatorowego). Zmniejsza rozmiar zobfuskowanego kodu, ale dodaje około 20% narzutu wydajnościowego przy kodzie intensywnie korzystającym z rekurencji.

  • false (domyślnie): dwa executory — optymalna wydajność, większy wynik
  • true: pojedynczy executor — mniejszy wynik, nieco wolniej

vmStringArrayBytecodeOnly

Type: boolean Default: false

Po włączeniu tablica ciągów wyłącznie wyodrębnia ciągi z danych kodu bajtowego — żadne inne ciągi w kodzie nie są przekształcane. Wymusza to włączenie stringArray, nawet jeśli nie ustawiono jej jawnie.

Dlaczego warto: wyodrębnianie wszystkich ciągów środowiska uruchomieniowego VM do tablicy ciągów jest powolne. Ta opcja obejmuje wyodrębnianiem do tablicy ciągów wyłącznie zawartość kodu bajtowego, poprawiając wydajność i chroniąc jednocześnie stałe kodu bajtowego.

  • Gdy vmBytecodeArrayEncoding: false — wyodrębniane są ciągi z pul stałych kodu bajtowego (tablice c)
  • Gdy vmBytecodeArrayEncoding: true — wyodrębniane są zakodowane w base64 ciągi kodu bajtowego najwyższego poziomu
  • stringArrayThreshold nadal steruje tym, jaki procent tych ciągów kodu bajtowego jest wyodrębniany

vmDomainLock

Type: string[] Default: []

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Ogranicza działanie zobfuskowanego kodu do określonych domen i/lub subdomen i jest znacznie trudniejsza do zlokalizowania i usunięcia niż domainLock.

Jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w tej opcji, przeglądarka zostanie przekierowana pod adres URL przekazany w opcji vmDomainLockRedirectUrl, a kolejne chronione wywołania będą zwracać nieprawidłowe wyniki, nawet jeśli przekierowanie zostanie zablokowane.

Wiele domen i subdomen

Kod można zablokować do więcej niż jednej domeny lub subdomeny. Na przykład, aby zablokować go tak, by działał wyłącznie w www.example.com, należy dodać www.example.com. Aby działał w domenie głównej wraz ze wszystkimi subdomenami (example.com, sub.example.com), należy użyć .example.com.

vmDomainLockRedirectUrl

Type: string Default: about:blank

⚠️ Ta opcja nie działa z target: 'node', target: 'service-worker' ani target: 'bytenode'

Pozwala przekierować przeglądarkę pod przekazany adres URL, jeśli kod źródłowy nie jest uruchamiany w domenach wskazanych w opcji vmDomainLock.

Preset Options

Wysoka obfuskacja, niska wydajność

Wydajność będzie znacznie niższa niż bez obfuskacji

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

Średnia obfuskacja, optymalna wydajność

Wydajność będzie niższa niż bez obfuskacji

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

Niska obfuskacja, wysoka wydajność

Wydajność pozostanie na względnie normalnym poziomie

{
    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 domyślny, wysoka wydajność

{
    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 – bardzo wysoka obfuskacja (maksymalne bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM ze wszystkimi funkcjami wzmacniającymi ochronę, w tym z pośrednim dyspozytorem (indirect dispatch). Zapewnia najsilniejszą ochronę, ale kosztem większego rozmiaru wyniku i znacznie wolniejszego wykonywania.

{
    optionsPreset: 'vm-ultra-high-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 (ochrona przed agentami AI)

Ten preset został zaprojektowany specjalnie tak, aby uniemożliwiać agentom AI i modelom LLM inżynierię wsteczną kodu bajtowego VM. Oparty na vm-default z włączoną samoobroną i ochroną przed debugowaniem. Lżejszy niż vm-high-obfuscation, ale specjalnie utwardzony przeciwko automatycznej analizie.

{
    optionsPreset: 'vm-anti-llm'
}

Obejmuje:

  • Obfuskację kodu bajtowego VM z tablicą ciągów (z vm-default)
  • vmSelfDefending — wykrywanie hooków, hash integralności, fingerprint kodu źródłowego, weryfikację czystego realmu przez iframe, wyprowadzanie klucza szyfrem ARX
  • vmDebugProtection — kontrole antydebugujące w pętli dyspozytora VM
  • debugProtection: false — brak przestarzałej ochrony przed debugowaniem (ochrona przed debugowaniem VM jest lepsza)

VM High – wysoka obfuskacja (najwyższe bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM z większością funkcji wzmacniających ochronę. Zapewnia silną ochronę przy lepszej wydajności niż preset ultra-high.

{
    optionsPreset: 'vm-high-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 – średnia obfuskacja (zrównoważone bezpieczeństwo)

Ten preset włącza obfuskację opartą na kodzie bajtowym VM ze zrównoważonym zestawem funkcji wzmacniających ochronę. Dobry kompromis między bezpieczeństwem a wydajnością.

{
    optionsPreset: 'vm-medium-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 – niska obfuskacja (podstawowe bezpieczeństwo, lepsza wydajność)

Ten preset włącza podstawową obfuskację opartą na kodzie bajtowym VM bez dodatkowych funkcji wzmacniających ochronę. Dobra równowaga między bezpieczeństwem a rozmiarem wyniku.

{
    optionsPreset: 'vm-low-obfuscation'
}

Lub skonfiguruj poszczególne opcje osobno:

{
    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 + ochrona tablicą ciągów)

Ten preset łączy podstawową obfuskację opartą na kodzie bajtowym VM z ochroną tablicą ciągów. Dobry punkt wyjścia do obfuskacji VM z ochroną ciągów.

{
    optionsPreset: 'vm-default'
}

Lub skonfiguruj poszczególne opcje osobno:

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