مرجع الخيارات

المحتويات

compact

config

controlFlowFlattening

controlFlowFlatteningThreshold

deadCodeInjection

deadCodeInjectionThreshold

debugProtection

debugProtectionInterval

disableConsoleOutput

domainLock

نطاقات ونطاقات فرعية متعددة

domainLockRedirectUrl

exclude

forceTransformStrings

identifierNamesCache

واجهة Node.js

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

نطاقات ونطاقات فرعية متعددة

vmDomainLockRedirectUrl

Preset Options

تشويش عالٍ، أداء منخفض

تشويش متوسط، أداء مثالي

تشويش منخفض، أداء عالٍ

الإعداد المسبق الافتراضي، أداء عالٍ

تشويش VM فائق العلو (أقصى أمان)

VM المضاد لنماذج LLM (حماية من وكلاء الذكاء الاصطناعي)

تشويش VM العالي (أعلى أمان)

تشويش VM المتوسط (أمان متوازن)

تشويش VM المنخفض (أمان أساسي، أداء أفضل)

VM الافتراضي (VM + حماية مصفوفة النصوص)

compact

Type: boolean Default: true

يجمع الكود الناتج في سطر واحد.

config

Type: string Default: ``

اسم ملف الإعدادات بصيغة JS/JSON الذي يحتوي على خيارات المشوِّش. تُتجاوَز هذه الخيارات بالخيارات المُمرَّرة مباشرةً إلى CLI

controlFlowFlattening

Type: boolean Default: false

⚠️ يؤثّر هذا الخيار بشدة في الأداء، إذ قد يبطّئ سرعة التشغيل حتى 1.5 ضعف. استخدم controlFlowFlatteningThreshold لتحديد نسبة العُقد التي سيطالها تسطيح تدفق التحكم.

يفعّل تسطيح تدفق التحكم في الكود. وتسطيح تدفق التحكم هو تحويل بنيوي للكود المصدري يعيق فهم البرنامج.

مثال:

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

احتمال تطبيق تحويل controlFlowFlattening على أي عقدة بعينها.

هذا الإعداد مفيد بوجه خاص مع أحجام الكود الكبيرة، لأن الكميات الكبيرة من تحويلات تدفق التحكم قد تبطّئ كودك وتزيد حجمه.

القيمة controlFlowFlatteningThreshold: 0 تكافئ controlFlowFlattening: false.

deadCodeInjection

Type: boolean Default: false

⚠️ يزيد حجم الكود المشوَّش زيادة كبيرة (حتى 200%)، فلا تستخدمه إلا إذا كان حجم الكود المشوَّش لا يهم. استخدم deadCodeInjectionThreshold لتحديد نسبة العُقد التي سيطالها حقن الكود الميت.
⚠️ يفعّل هذا الخيار قسرًا خيار stringArray.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation.

مع هذا الخيار، تُضاف كتل عشوائية من الكود الميت إلى الكود المشوَّش.

مثال:

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

يتيح تحديد نسبة العُقد التي سيطالها deadCodeInjection.

debugProtection

Type: boolean Default: false

⚠️ قد يجمّد متصفحك إذا فتحت أدوات المطور.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmDebugProtection بدلًا منه.

يجعل هذا الخيار استخدام وظيفة debugger في أدوات المطور شبه مستحيل (سواء في المتصفحات المبنية على WebKit أو في Mozilla Firefox).

debugProtectionInterval

Type: number Default: 0

⚠️ قد يجمّد متصفحك! استخدمه على مسؤوليتك الخاصة.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmDebugProtection بدلًا منه.

عند ضبطه، يُستخدَم فاصل زمني بالميلي ثانية لفرض وضع التنقيح على علامة تبويب Console، مما يصعّب استخدام ميزات أدوات المطور الأخرى. يعمل إذا كان debugProtection مفعَّلًا. القيمة المُوصى بها بين 2000 و4000 ميلي ثانية.

disableConsoleOutput

Type: boolean Default: false

⚠️ يعطّل هذا الخيار استدعاءات console عالميًا لكل السكربتات

يعطّل استخدام console.log وconsole.info وconsole.error وconsole.warn وconsole.debug وconsole.exception وconsole.trace باستبدالها بدوال فارغة. وهذا يصعّب استخدام المنقّح.

domainLock

Type: string[] Default: []

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح تشغيل الكود المصدري المشوَّش على نطاقات و/أو نطاقات فرعية بعينها فقط. وهذا يصعّب كثيرًا على أي شخص أن ينسخ كودك المصدري ويشغّله في مكان آخر.

إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بهذا الخيار، فسيُعاد توجيه المتصفح إلى عنوان URL المُمرَّر إلى خيار domainLockRedirectUrl.

نطاقات ونطاقات فرعية متعددة

يمكن قفل كودك على أكثر من نطاق أو نطاق فرعي. فمثلًا، لقفله بحيث لا يعمل الكود إلا على www.example.com أضف www.example.com. ولجعله يعمل على النطاق الجذري بما في ذلك أي نطاقات فرعية (example.com وsub.example.com)، استخدم .example.com.

domainLockRedirectUrl

Type: string Default: about:blank

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح إعادة توجيه المتصفح إلى عنوان URL مُمرَّر إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بواسطة domainLock

exclude

Type: string[] Default: []

أسماء ملفات أو أنماط glob تشير إلى الملفات المُستثناة من التشويش.

forceTransformStrings

Type: string[] Default: []

يفعّل التحويل القسري للنصوص الحرفية المطابِقة لأنماط RegExp المُمرَّرة.

⚠️ يؤثّر هذا الخيار فقط في النصوص التي لا ينبغي أن يحوّلها stringArrayThreshold (أو ربما عتبات أخرى مستقبلًا)

للخيار أولوية على خيار reservedStrings لكن لا أولوية له على conditional comments.

مثال:

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

identifierNamesCache

Type: Object | null Default: null

الهدف الأساسي من هذا الخيار هو إمكانية استخدام أسماء المعرِّفات نفسها أثناء تشويش عدة مصادر/ملفات.

يُدعَم حاليًا نوعان من المعرِّفات:

  • المعرِّفات العامة:
    • تُكتب جميع المعرِّفات العامة إلى الذاكرة المؤقتة؛
    • تُستبدل جميع المعرِّفات العامة غير المصرَّح بها المطابِقة بالقيم المأخوذة من الذاكرة المؤقتة.
  • معرِّفات الخصائص، فقط عند تفعيل خيار renameProperties:
    • تُكتب جميع معرِّفات الخصائص إلى الذاكرة المؤقتة؛
    • تُستبدل جميع معرِّفات الخصائص المطابِقة بالقيم المأخوذة من الذاكرة المؤقتة.

واجهة Node.js

إذا مُرِّرت القيمة null، تُعطَّل الذاكرة المؤقتة كليًا.

إذا مُرِّر كائن فارغ ({})، يُفعَّل كتابة أسماء المعرِّفات إلى كائن الذاكرة المؤقتة (من النوع TIdentifierNamesCache). ويمكن الوصول إلى كائن الذاكرة المؤقتة هذا عبر استدعاء التابع getIdentifierNamesCache لكائن ObfuscationResult.

يمكن بعد ذلك استخدام كائن الذاكرة المؤقتة الناتج كقيمة لخيار identifierNamesGenerator لاستعمال هذه الأسماء أثناء تشويش جميع أسماء المعرِّفات المطابِقة في المصادر التالية.

مثال:

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 خيارًا مختلفًا هو --identifier-names-cache-path يتيح تحديد مسار إلى ملف .json موجود يُستخدَم لقراءة الذاكرة المؤقتة لأسماء المعرِّفات وكتابتها.

إذا مُرِّر مسار إلى ملف فارغ، تُكتب الذاكرة المؤقتة لأسماء المعرِّفات إلى ذلك الملف.

يمكن استخدام هذا الملف الذي يحتوي على ذاكرة مؤقتة موجودة مجددًا كقيمة لخيار --identifier-names-cache-path لاستعمال هذه الأسماء أثناء تشويش جميع أسماء المعرِّفات المطابِقة في الملفات التالية.

identifierNamesGenerator

Type: string Default: hexadecimal

يضبط مولِّد أسماء المعرِّفات.

القيم المتاحة:

  • dictionary: أسماء معرِّفات من قائمة identifiersDictionary
  • hexadecimal: أسماء معرِّفات مثل _0xabc123
  • mangled: أسماء معرِّفات قصيرة مثل a وb وc
  • mangled-shuffled: مثل mangled لكن بأبجدية مخلوطة

identifiersDictionary

Type: string[] Default: []

يضبط قاموس المعرِّفات لخيار identifierNamesGenerator: dictionary. سيُستخدَم كل معرِّف من القاموس في بضع صيغ باختلاف حالة الأحرف في كل محرف. ولذلك ينبغي أن يعتمد عدد المعرِّفات في القاموس على كمية المعرِّفات في الكود المصدري الأصلي.

identifiersPrefix

Type: string Default: ''

يضبط بادئة لجميع المعرِّفات العامة.

استخدم هذا الخيار عندما تريد تشويش عدة ملفات. يساعد هذا الخيار على تجنّب التعارضات بين المعرِّفات العامة لهذه الملفات. وينبغي أن تكون البادئة مختلفة لكل ملف.

randomIdentifiersPrefix

Type: boolean Default: false

يُلحق بادئة عشوائية مبنية على بذرة (6 محارف أبجدية رقمية) بجميع المعرِّفات العامة. استخدم هذا الخيار لتجنّب التصادمات بين الحزم المشوَّشة على حدة والمُحمَّلة في النطاق العام نفسه — فهو يغني عن الحاجة إلى اختيار identifiersPrefix فريد لكل حزمة يدويًا.

  • تُشتق القيمة العشوائية من خيار seed ومن بصمة تجزئة الكود المصدري، لذا تُنتج عمليات البناء القابلة للتكرار بالبذرة نفسها البادئة نفسها.
  • عند دمجه مع identifiersPrefix، تُلحق المحارف العشوائية بالبادئة التي قدّمها المستخدم (مثلًا myApp + العشوائي aBc123myAppaBc123).
  • عند دمجه مع vmObfuscation، تحلّ القيمة العشوائية محل البادئة الافتراضية vm — فالعشوائية تضمن التفرّد أصلًا.

ignoreImports

Type: boolean Default: false

يمنع تشويش عمليات الاستيراد عبر require. قد يكون مفيدًا في بعض الحالات عندما تتطلب بيئة التشغيل لسبب ما أن تكون عمليات الاستيراد هذه بنصوص ثابتة فقط.

inputFileName

Type: string Default: ''

يتيح تحديد اسم ملف المُدخل الذي يحتوي على الكود المصدري. يُستخدَم هذا الاسم داخليًا لتوليد خريطة المصدر. مطلوب عند استخدام واجهة NodeJS وامتلاك خيار sourceMapSourcesMode القيمة sources.

log

Type: boolean Default: false

يفعّل تسجيل المعلومات في وحدة التحكم.

numbersToExpressions

Type: boolean Default: false

يفعّل تحويل الأرقام إلى تعبيرات

مثال:

// input
const foo = 1234;

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

optionsPreset

Type: string Default: default

يتيح ضبط إعداد الخيارات المسبق.

القيم المتاحة:

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

ستُدمَج جميع الخيارات الإضافية مع إعداد الخيارات المسبق المُحدَّد.

parseHtml

Type: boolean Default: false

يفعّل تشويش JavaScript داخل وسوم <script> في HTML.

عند التفعيل، سيقوم المشوِّش بما يلي:

  • الكشف التلقائي عمّا إذا كان المُدخل HTML (بالتحقق من وجود وسوم <!DOCTYPE أو <html> أو <head> أو <body> أو <script>)
  • استخراج JavaScript من وسوم <script> المُعلَّمة بالسمة data-javascript-obfuscator
  • تشويش كل سكربت مُعلَّم على حدة مع الحفاظ على بنية HTML
  • إعادة حقن الكود المشوَّش في مواضعه الأصلية

مهم: لا يُشوَّش سوى السكربتات التي تحمل السمة data-javascript-obfuscator. ويُشوَّش كل سكربت مُعلَّم على حدة وباستقلال. وهذا يعني:

  • يجب أن يكون الكود داخل وسوم السكربت المُعلَّمة معزولًا - يجب ألّا يشير إلى متغيرات أو دوال أو أصناف معرَّفة في وسوم سكربت مُعلَّمة أخرى
  • لا يزال بإمكان السكربتات غير المُعلَّمة الوصول إلى المتغيرات العامة التي تعرّفها السكربتات المُعلَّمة (عبر تصريحات var أو إسنادات globalThis الصريحة)
  • يمنحك هذا تحكمًا صريحًا في السكربتات التي تريد حمايتها

يُشوَّش (يجب أن يحمل السمة data-javascript-obfuscator):

  • <script data-javascript-obfuscator> - السكربتات العادية
  • <script type="text/javascript" data-javascript-obfuscator> - السكربتات المُحدَّد نوعها صراحةً
  • السكربتات ذات أي سمات إضافية (id أو class أو data-* أخرى، إلخ.)

يُتخطّى (يُترَك دون تغيير):

  • السكربتات التي لا تحمل السمة data-javascript-obfuscator
  • <script type="module"> - وحدات ES (حتى مع السمة)
  • <script src="..."> - السكربتات الخارجية (حتى مع السمة)
  • وسوم السكربت الفارغة

ملاحظة: لا تُولَّد خرائط المصدر عند تفعيل parseHtml، لأنها لن تُطابِق ناتج HTML بشكل صحيح.

مثال:

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

⚠️ قد يعطّل هذا الخيار عمل كودك. لا تفعّله إلا إذا كنت تعرف ما يفعله!

يفعّل تشويش أسماء المتغيرات والدوال العامة مع تصريحها.

عندما يكون هذا الخيار معطَّلًا ويصرّح كود المُدخل عن دوال أو أصناف في النطاق العام (أي أن الكود غير مغلَّف داخل IIFE)، تُبقى أسماؤها كما هي في الكود المشوَّش — فقد تشير إليها سكربتات أخرى بالاسم. وتحت vmObfuscation يُبلَّغ عن تحذير VMGlobalFunctionNamesNotRenamed يسرد هذه الأسماء، إذ إن جسم الدالة مخفي كبايت كود لكن الاسم القابل للقراءة على المستوى الأعلى لا يزال يكشف ما يفعله الكود (لنموذج LLM مثلًا). ولتجنّب هذا الكشف، غلّف الكود داخل IIFE أو فعّل هذا الخيار.

renameProperties

Type: boolean Default: false

⚠️ قد يعطّل هذا الخيار عمل كودك. لا تفعّله إلا إذا كنت تعرف ما يفعله!

يفعّل إعادة تسمية أسماء الخصائص. وسيُتجاهَل جميع خصائص DOM المدمجة والخصائص في أصناف JavaScript الأساسية.

للتبديل بين الوضعين safe وunsafe لهذا الخيار استخدم خيار renamePropertiesMode.

لضبط صيغة أسماء الخصائص المُعاد تسميتها استخدم خيار identifierNamesGenerator.

للتحكم في الخصائص التي سيُعاد تسميتها استخدم خيار reservedNames.

مثال:

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

⚠️ حتى في الوضع safe، قد يعطّل خيار renameProperties عمل كودك.

يحدّد وضع خيار renameProperties:

  • safe - السلوك الافتراضي بعد الإصدار 2.11.0. يحاول إعادة تسمية الخصائص بطريقة أكثر أمانًا لمنع أخطاء التشغيل. مع هذا الوضع، تُستثنى بعض الخصائص من إعادة التسمية.
  • unsafe - السلوك الافتراضي قبل الإصدار 2.11.0. يعيد تسمية الخصائص بطريقة غير آمنة دون أي قيود.

إذا كان أحد الملفات يستخدم خصائص من ملف آخر، فاستخدم خيار identifierNamesCache للحفاظ على أسماء الخصائص نفسها بين هذه الملفات.

reservedNames

Type: string[] Default: []

يعطّل تشويش وتوليد المعرِّفات المطابِقة لأنماط RegExp المُمرَّرة.

مثال:

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

reservedStrings

Type: string[] Default: []

يعطّل تحويل النصوص الحرفية المطابِقة لأنماط RegExp المُمرَّرة. وتبقى النصوص المطابِقة ظاهرة في الناتج المشوَّش.

عند استخدام تشويش VM، تُخزَّن النصوص المحجوزة في مصفوفة منفصلة غير مشفَّرة لإبقائها ظاهرة. وهذا مفيد للنصوص التي يجب أن تبقى قابلة للقراءة، مثل نقاط نهاية API للمراقبة أو معرِّفات المكتبات.

مثال:

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

seed

Type: string|number Default: 0

يضبط هذا الخيار بذرة مولِّد الأرقام العشوائية. وهذا مفيد لإنشاء نتائج قابلة للتكرار.

إذا كانت البذرة 0، فسيعمل مولِّد الأرقام العشوائية بلا بذرة.

selfDefending

Type: boolean Default: false

⚠️ لا تغيّر الكود المشوَّش بأي شكل بعد التشويش بهذا الخيار، لأن أي تغيير مثل ضغط الكود قد يفعّل الدفاع الذاتي فيتوقف الكود عن العمل!
⚠️ يضبط هذا الخيار قسرًا قيمة compact إلى true
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmSelfDefending بدلًا منه.

يجعل هذا الخيار الكود الناتج صامدًا أمام إعادة التنسيق وإعادة تسمية المتغيرات. فإذا حاول أحد استخدام مُجمِّل JavaScript على الكود المشوَّش، فسيتوقف الكود عن العمل، مما يصعّب فهمه وتعديله.

simplify

Type: boolean Default: true

يفعّل تشويشًا إضافيًا للكود عبر التبسيط.

⚠️ في الإصدارات المستقبلية سيُنقَل تشويش النصوص الحرفية من نوع boolean (true => !![]) ليكون ضمن هذا الخيار.

مثال:

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

يفعّل توليد خريطة المصدر للكود المشوَّش.

قد تكون خرائط المصدر مفيدة لمساعدتك على تنقيح كود JavaScript المصدري المشوَّش. فإذا أردت أو احتجت إلى التنقيح في بيئة الإنتاج، يمكنك رفع ملف خريطة المصدر المنفصل إلى موقع سرّي ثم توجيه متصفحك إليه.

sourceMapBaseUrl

Type: string Default: ``

يضبط عنوان URL الأساسي لعنوان استيراد خريطة المصدر عند sourceMapMode: 'separate'.

مثال CLI:

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

النتيجة:

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

sourceMapFileName

Type: string Default: ``

يضبط اسم ملف خريطة المصدر الناتجة عند sourceMapMode: 'separate'.

مثال CLI:

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

النتيجة:

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

sourceMapMode

Type: string Default: separate

يحدّد وضع توليد خريطة المصدر:

  • inline - يضيف خريطة المصدر في نهاية كل ملف ‎.js؛
  • separate - يولّد ملف '.map' مقابلًا يحتوي على خريطة المصدر. وفي حال تشغيل المشوِّش عبر CLI، يضيف رابطًا إلى ملف خريطة المصدر في نهاية ملف الكود المشوَّش //# sourceMappingUrl=file.js.map.

sourceMapSourcesMode

Type: string Default: sources-content

يتيح التحكم في الحقلين sources وsourcesContent لخريطة المصدر:

  • sources-content - يضيف حقل sources وهميًا، ويضيف حقل sourcesContent مع الكود المصدري الأصلي؛
  • sources - يضيف حقل sources مع وصف مصدر صالح، ولا يضيف حقل sourcesContent. وعند استخدام واجهة NodeJS يلزم تحديد خيار inputFileName الذي سيُستخدَم كقيمة لحقل sources.

splitStrings

Type: boolean Default: false

يقسّم النصوص الحرفية إلى أجزاء بطول قيمة خيار splitStringsChunkLength.

مثال:

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

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

splitStringsChunkLength

Type: number Default: 10

يضبط طول أجزاء خيار splitStrings.

stringArray

Type: boolean Default: true

يزيل النصوص الحرفية ويضعها في مصفوفة خاصة. فمثلًا، النص "Hello World" في var m = "Hello World"; سيُستبدَل بشيء مثل var m = _0x12c456[0x1];

stringArrayCallsTransform

Type: boolean Default: false

⚠️ يجب تفعيل خيار stringArray

يفعّل تحويل الاستدعاءات إلى stringArray. قد تُستخرَج جميع وسائط هذه الاستدعاءات إلى كائن مختلف اعتمادًا على قيمة stringArrayCallsTransformThreshold. وهذا يزيد صعوبة العثور تلقائيًا على الاستدعاءات إلى مصفوفة النصوص.

مثال:

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

⚠️ يجب تفعيل خياري stringArray وstringArrayCallsTransformThreshold

يمكنك استخدام هذا الإعداد لضبط الاحتمال (من 0 إلى 1) بأن تُحوَّل الاستدعاءات إلى مصفوفة النصوص.

stringArrayEncoding

Type: string[] Default: []

⚠️ يجب تفعيل خيار stringArray

قد يبطّئ هذا الخيار سكربتك.

يرمّز جميع النصوص الحرفية في stringArray باستخدام base64 أو rc4 ويُدرج كودًا خاصًا يُستخدَم لفك ترميزها مجددًا أثناء التشغيل.

سيُرمَّز كل قيمة من stringArray بالترميز المُنتقى عشوائيًا من القائمة المُمرَّرة. وهذا يتيح استخدام عدة ترميزات.

القيم المتاحة:

  • 'none' (boolean): لا يرمّز قيمة stringArray
  • 'base64' (string): يرمّز قيمة stringArray باستخدام base64
  • 'rc4' (string): يرمّز قيمة stringArray باستخدام rc4. أبطأ من base64 بنحو 30-50%، لكنه يصعّب الحصول على القيم الأولية.

فمثلًا، مع قيم الخيار التالية لن يُرمَّز بعض قيم stringArray، وسيُرمَّز بعضها الآخر بترميز base64 وrc4:

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

stringArrayIndexesType

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

⚠️ يجب تفعيل خيار stringArray

يتيح التحكم في نوع فهارس استدعاء مصفوفة النصوص.

سيُحوَّل كل فهرس استدعاء لـ stringArray بالنوع المُنتقى عشوائيًا من القائمة المُمرَّرة. وهذا يتيح استخدام عدة أنواع.

القيم المتاحة:

  • 'hexadecimal-number' (default): يحوّل فهارس استدعاء مصفوفة النصوص كأرقام ست عشرية
  • 'hexadecimal-numeric-string': يحوّل فهارس استدعاء مصفوفة النصوص كنص عددي ست عشري

قبل الإصدار 2.9.0 كان javascript-obfuscator يحوّل جميع فهارس استدعاء مصفوفة النصوص بالنوع hexadecimal-numeric-string. وهذا يصعّب بعض إزالة التشويش اليدوية قليلًا، لكنه يتيح كشف هذه الاستدعاءات بسهولة بواسطة أدوات إزالة التشويش التلقائية.

يهدف النوع الجديد hexadecimal-number إلى تصعيب الكشف التلقائي عن أنماط استدعاء مصفوفة النصوص في الكود.

سيُضاف مزيد من الأنواع مستقبلًا.

stringArrayIndexShift

Type: boolean Default: true

⚠️ يجب تفعيل خيار stringArray

يفعّل إزاحة فهرس إضافية لجميع استدعاءات مصفوفة النصوص

stringArrayRotate

Type: boolean Default: true

⚠️ يجب تفعيل stringArray

يزيح مصفوفة stringArray بمقدار ثابت وعشوائي (يُولَّد عند تشويش الكود) من المواضع. وهذا يصعّب مطابقة ترتيب النصوص المُزالة بمواضعها الأصلية.

stringArrayShuffle

Type: boolean Default: true

⚠️ يجب تفعيل stringArray

يخلط عناصر مصفوفة stringArray عشوائيًا.

stringArrayWrappersCount

Type: number Default: 1

⚠️ يجب تفعيل خيار stringArray

يضبط عدد المغلِّفات لـ string array داخل كل نطاق جذري أو نطاق دالة. والعدد الفعلي للمغلِّفات داخل كل نطاق محدود بعدد عُقد literal ضمن هذا النطاق.

مثال:

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

⚠️ يجب تفعيل خياري stringArray وstringArrayWrappersCount

يفعّل الاستدعاءات المتسلسلة بين مغلِّفات string array.

مثال:

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

⚠️ يجب تفعيل خيار stringArray
⚠️ يؤثّر هذا الخيار حاليًا فقط في المغلِّفات المُضافة بقيمة خيار stringArrayWrappersType المساوية function

يتيح التحكم في العدد الأقصى لمعاملات مغلِّفات مصفوفة النصوص. القيمة الافتراضية والدنيا هي 2. القيمة المُوصى بها بين 2 و5.

stringArrayWrappersType

Type: string Default: variable

⚠️ يجب تفعيل خياري stringArray وstringArrayWrappersCount

يتيح اختيار نوع المغلِّفات التي يضيفها خيار stringArrayWrappersCount.

القيم المتاحة:

  • 'variable': يضيف مغلِّفات متغيرات في أعلى كل نطاق. أداء سريع.
  • 'function': يضيف مغلِّفات دوال في مواضع عشوائية داخل كل نطاق. أداء أبطأ من variable لكنه يوفّر تشويشًا أكثر صرامة.

يُوصى بشدة باستخدام مغلِّفات function لتشويش أعلى عندما لا يكون لخسارة الأداء تأثير كبير على التطبيق المشوَّش.

مثال على قيمة الخيار '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

⚠️ يجب تفعيل خيار stringArray

يمكنك استخدام هذا الإعداد لضبط الاحتمال (من 0 إلى 1) بأن يُدرَج نص حرفي في stringArray.

هذا الإعداد مفيد بوجه خاص مع أحجام الكود الكبيرة لأنه يستدعي string array مرارًا وقد يبطّئ كودك.

القيمة stringArrayThreshold: 0 تكافئ stringArray: false.

strictMode

Type: boolean | null Default: null

يتيح تحديد كيف ينبغي للمشوِّش أن يعامل الكود فيما يخص الوضع الصارم في JavaScript.

القيم المتاحة:

  • null (افتراضي) - كشف الوضع الصارم تلقائيًا من الكود. إذا كان الكود يحتوي على توجيه 'use strict' صريح، أو بنية وحدة ES، أو توابع أصناف، فيُعامَل على أنه وضع صارم. وإلا يُفترَض الوضع المتساهل.
  • true - فرض معاملة الوضع الصارم لكل الكود، حتى دون توجيه 'use strict' صريح. استخدم هذا عندما يعمل كودك في سياق وضع صارم (مثلًا في وحدات ES أو أدوات التحزيم أو أطر العمل الحديثة).
  • false - لا يُعامَل على أنه صارم إلا مؤشرات الوضع الصارم الصريحة ('use strict'، وحدات ES، توابع الأصناف). ولا يزال توريث نطاق الأب مطبَّقًا وفق مواصفة JS.

target

Type: string Default: browser

يتيح ضبط البيئة الهدف للكود المشوَّش.

القيم المتاحة:

  • browser (افتراضي) — بيئة صفحة ويب قياسية. الكود الناتج مطابق لـ node، لكن لا يُسمح باستخدام بعض الخيارات الخاصة بالمتصفح مع الهدف node
  • browser-no-eval — مثل browser، لكن الناتج لا يستخدم eval(). استخدمه عندما تفرض الصفحة الهدف سياسة أمان محتوى تمنع eval/unsafe-eval.
  • node — بيئة Node.js. تُعطَّل الخيارات الخاصة بالمتصفح (فهي تتطلب window/document وستكون بلا أثر أو ستطلق استثناءً في Node). ولا تُصدَر لهذا الهدف بعض دفاعات vmSelfDefending التي تعتمد على واجهات برمجية خاصة بالمتصفح — كشف المتصفح مقطوع الرأس، والتعافي عبر عالَم نظيف قائم على iframe، وفحوصات مضادة للمفتِّش/DOM.
  • service-worker — سياق Service Worker. لا window، ولا document، ومتغيّر self عام مختلف.
  • userscript — صندوق حماية مدير سكربتات المستخدم (مثل Tampermonkey). تُعدَّل دفاعات vmSelfDefending تبعًا لذلك.
  • bytenode — كود Node.js سيُترجَم بواسطة مُحمِّل bytenode (بايت كود V8 المُخزَّن .jsc) بعد التشويش. لا يستدعي المشوِّش نفسه bytenode؛ بل يُصدر JavaScript مشوَّشًا بـ VM بُنيت بيئة تشغيله لتصمد أمام خطوة ترجمة bytenode، وتُعدَّل دفاعات vmSelfDefending تبعًا لذلك. شغّل bytenode بنفسك على الناتج المشوَّش لإنتاج ملف .jsc النهائي.

transformObjectKeys

Type: boolean Default: false

يفعّل تحويل مفاتيح الكائنات.

مثال:

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

يتحكم في تحذيرات التشويش غير القاتلة التي تُصدَر عبر التابع ObfuscationResult.getWarnings().

القيم المتاحة:

  • 'all' (افتراضي) — يُصدَر كل تحذير.
  • 'none' — تُكتَم كل التحذيرات.
  • كائن يربط أنواع التحذيرات بقيم منطقية — النوع المربوط بـ false يُكتَم؛ وكل نوع غير موجود (أو مربوط بـ true) يبقى مفعَّلًا. فمثلًا، { "VMGlobalFunctionNamesNotRenamed": false } يبقي كل تحذير عدا ذاك.

أنواع التحذيرات:

  • VMGlobalFunctionNamesNotRenamed — تحت vmObfuscation، بقيت أسماء تصريحات الدوال على المستوى الأعلى، وتصريحات الأصناف، والمتغيرات المُسنَد إليها تعبير دالة/سهمية/صنف كما هي (خيار renameGlobals معطَّل والكود غير مغلَّف داخل IIFE)، فتبقى قابلة للقراءة في الناتج رغم إخفاء الأجسام كبايت كود. ولا يُبلَّغ عن الأسماء المُصدَّرة.
  • VMTopLevelInitializerNotVirtualized — بقيت مُهيّئات المتغيرات على المستوى الأعلى بصيغة JavaScript عادية تحت تشويش VM لأن vmWrapTopLevelInitializers معطَّل أو تعذّر عليه محاكاتها افتراضيًا.
  • DynamicCodeRenameRisk — يبني الكود دالة من نص أثناء التشغيل (عبر eval المباشر، أو باني Function، أو fn.toString() المحقون في <script>/Worker)، وقد يشير ذلك إلى معرِّفات أعاد المشوِّش تسميتها.
  • VMDynamicCodeSkipped — تُخطّي دالة من ترميز بايت كود VM لأنها تحتوي على eval مباشر / new Function ديناميكي / Function (انظر vmForceCompileDynamicCode).
  • VMSyncFunctionSkippedInAsyncMode — مع تفعيل vmAsyncExecutor، تبيّن أن دالة علّمتها صراحةً في وضع comment متزامنة فتُخطّيت (لا يُحاكى افتراضيًا في ذلك الوضع سوى الدوال غير المتزامنة).
  • VMAsyncGeneratorSkippedInAsyncMode — مع تفعيل vmAsyncExecutor وجالِب مفتاح غير متزامن نشط، تعذّرت محاكاة مولِّد غير متزامن مُعلَّم افتراضيًا (يجب أن يُعيد مُكرِّره بشكل متزامن).
  • BrowserTargetWithNodeStyleCode — يبدو أن الكود يستهدف Node.js (مثل require('fs') أو __dirname أو process.argv) بينما خيار target مضبوط على بيئة شبيهة بالمتصفح.

vmObfuscation

Type: boolean Default: false

يفعّل تشويش البايت كود القائم على VM. عند التفعيل، تُترجَم دوال JavaScript إلى بايت كود مخصص يعمل على آلة افتراضية مضمَّنة. وهذا يوفّر أعلى مستوى من الحماية إذ يُحوَّل منطق الكود الأصلي بالكامل.

مثال: كودك القابل للقراءة مثل return qty * price يصبح قائمة من الأرقام مثل [0x15,0x03,0x17,...] لا يستطيع تنفيذها سوى مفسِّر VM المضمَّن. ولم يعد المنطق الأصلي ظاهرًا بصيغة JavaScript.

vmTargetFunctions

Type: string[] Default: []

حدّد بدقّة أيّ دوال على المستوى الجذري ينبغي أن تحصل على حماية VM بالاسم.

مثال:

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

النتيجة: هذه الدوال الثلاث فقط تحصل على حماية VM. وكل ما عداها يبقى JavaScript عاديًا (لكنه مشوَّش مع ذلك). مثالي لحماية فحوصات التراخيص الحساسة أو منطق المصادقة مع إبقاء بقية كودك رشيقًا.

vmExcludeFunctions

Type: string[] Default: []

حدّد الدوال على المستوى الجذري التي ينبغي ألّا تحصل أبدًا على حماية VM. له الأسبقية على الإعدادات الأخرى.

مثال:

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

متى تستخدمه: يمكن استثناء الدوال الحرجة للأداء على المستوى الجذري (حلقات الرسوم المتحركة، ومعالجة البيانات الفورية) لتجنّب حِمل VM مع الاستمرار في حماية كل شيء آخر.

vmTargetFunctionsMode

Type: string Default: root

يتحكم في كيفية اختيار الدوال/التوابع لتشويش VM.

الوضعالوصف
rootالسلوك الافتراضي. تُؤخَذ الدوال على المستوى الجذري فقط بعين الاعتبار لتشويش VM. يستخدم قائمة السماح vmTargetFunctions وقائمة المنع vmExcludeFunctions للتصفية.
commentلا يُشوَّش بـ VM سوى الدوال/التوابع المُزيَّنة بتعليق /* javascript-obfuscator:vm */. يعمل مع الدوال/التوابع عند أي مستوى تداخل.

مثال - وضع 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'
}

متى تستخدمه: عندما تحتاج إلى تحكم دقيق في الدوال التي تحصل تحديدًا على حماية VM، خصوصًا الدوال المتداخلة التي تحتوي على منطق حساس. فخلافًا لـ vmTargetFunctions الذي لا يعمل إلا مع الدوال المُسمّاة على المستوى الجذري، يتيح لك وضع comment حماية أي دالة في أي مكان من كودك.

vmForceCompileDynamicCode

Type: boolean Default: false

يتحكم فيما يفعله تشويش VM مع دالة تحتوي على استدعاء eval مباشر، أو new Function(...)، أو Function(...).

افتراضيًا، تُخطّى مثل هذه الدالة (وكل دالة معرَّفة داخلها) من ترميز بايت كود VM ويُبلَّغ عن تحذير VMDynamicCodeSkipped في result.getWarnings(). وذلك لأن المصدر المبني أثناء التشغيل قد يشير إلى معرِّفات من سلسلة النطاقات المحيطة — معرِّفات أعاد المشوِّش تسميتها.

عند ضبطه على true، تُرمَّز الدالة إلى بايت كود على أي حال ولا يُصدَر تحذير VMDynamicCodeSkipped بعد ذلك.

ويستمر إطلاق تحذير DynamicCodeRenameRisk المنفصل بصرف النظر عن هذا الخيار، لأن خطر إعادة التسمية الذي يصفه مستقل عن تخطّي VM — فتفعيل هذا الخيار لا يجعل النمط الأساسي أكثر أمانًا.

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

مع إيقاف الخيار (الافتراضي)، تُترَك loadConfig بصيغة JavaScript عادية. ومع تفعيله، تُترجَم loadConfig إلى بايت كود VM مثل أي دالة أخرى. استخدم هذا عندما تكون قد راجعت موضع الاستدعاء وتعرف أن الكود المبني أثناء التشغيل لا يعتمد على معرِّفات مُعاد تسميتها في الإغلاق.

vmWrapTopLevelInitializers

Type: boolean Default: false

يغلّف بعض مُهيّئات المتغيرات على المستوى الأعلى داخل IIFE (تعبيرات دوال مُستدعاة فورًا) حتى يمكن تشويشها بـ VM.

ما يفعله: دون هذا الخيار، تبقى الثوابت والمتغيرات على المستوى الأعلى ظاهرة في الناتج:

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

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

مع تفعيل هذا الخيار، يُغلَّف المُهيّئ داخل IIFE يُشوَّش بـ VM:

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

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

ملاحظة: لا يعمل هذا الخيار إلا عندما يكون vmTargetFunctionsMode بقيمة 'root' (الافتراضي).

vmDynamicOpcodes

Type: boolean Default: false

يجعل مفسِّر VM أصغر وفريدًا لكل عملية بناء.

ما يفعله:

  1. يصفّي التعليمات غير المستخدمة - إذا كان كودك لا يستخدم الأصناف، تُزال التعليمات المتعلقة بالأصناف كليًا
  2. يعشوِئ البنية - يُخلَط ترتيب معالِجات التعليمات في كل عملية بناء

والنتيجة - ناتج أصغر وكل عملية بناء تبدو مختلفة.

vmBytecodeEncoding

Type: boolean Default: false

يرمّز كل تعليمة بايت كود. تُفكّ ترميز التعليمات واحدة تلو الأخرى أثناء التنفيذ.

vmBytecodeArrayEncoding

Type: boolean Default: false

يرمّز مصفوفة البايت كود بأكملها ككتلة واحدة. تُفكّ ترميز المصفوفة مرة واحدة عند بدء التشغيل قبل بدء التنفيذ. استخدمه مع vmBytecodeEncoding للحصول على طبقتي حماية.

vmBytecodeArrayEncodingKey

Type: string Default: ''

مفتاح تشفير مخصص لترميز مصفوفة البايت كود. عند ضبطه، يُستخدَم هذا المفتاح بدلًا من المفتاح الافتراضي المشتق من البيئة. يجب توفير المفتاح أثناء التشغيل عبر vmBytecodeArrayEncodingKeyGetter.

يُخرج هذا الخيار مفتاح التشفير خارجيًا - فهو غير مضمَّن في الكود المشوَّش نفسه. ومع أن المفتاح لا يزال متاحًا أثناء التشغيل (وبالتالي ليس سرّيًا حقًا)، فإن هذا الفصل يمنع أدوات التحليل الساكن من العثور على المفتاح بفحص الكود وحده.

مهم: يجب أن يكون المفتاح متاحًا بشكل متزامن عند تحميل الكود المشوَّش. استخدم تخزينًا متزامنًا مثل الكوكيز، أو localStorage، أو sessionStorage، أو المتغيرات العامة، أو عناصر DOM (مثل وسوم meta المحقونة من الخادم). ولا يمكن استخدام الطرق غير المتزامنة مثل fetch() مباشرةً في تعبير جالِب المفتاح.

vmBytecodeArrayEncodingKeyGetter

Type: string Default: ''

تعبير JavaScript متزامن يُعيد مفتاح التشفير أثناء التشغيل. يُقيَّم هذا التعبير عند تحميل الكود المشوَّش، ويجب أن يُعيد المفتاح نفسه الذي قُدِّم في vmBytecodeArrayEncodingKey. ولحل المفتاح بشكل غير متزامن (عبر Promise)، فعّل vmAsyncExecutor.

ملاحظة: الجالِب الذي يُعيد Promise يتطلب vmAsyncExecutor. ولا يمكن التحقق من ذلك وقت البناء، لذا فإن جالِبًا يُعيد Promise مع vmAsyncExecutor معطَّل يفشل أثناء التشغيل — إذ يتلقى فاكّ الترميز الـ Promise بدلًا من المفتاح.

لن يعمل الكود المشوَّش إلا عندما يُعيد جالِب المفتاح المفتاح نفسه تمامًا الذي استُخدِم أثناء التشويش. فإذا لم يتطابق المفتاحان، سيفشل فك التشفير وسيُنتج الكود بيانات فاسدة أو أخطاء. وإذا أعاد جالِب المفتاح undefined أو null أو نصًا فارغًا، فسيطلق الكود خطأً: "VM decryption key not available".

مهم: أبقِ المفتاح خارج الملف/السكربت نفسه الذي يحوي الكود المشوَّش — فتضمينه هناك يتيح استعادته حتى بفحص ساكن محض للحزمة. خزّنه في مصدر منفصل بدلًا من ذلك: كوكيز يضبطها الخادم، أو localStorage يملؤه سكربت آخر، أو وسم meta في HTML محقون من الخادم، أو متغير عام يضبطه سكربت مختلف، أو (مع vmAsyncExecutor) يُجلَب من خادمك الخلفي أثناء التشغيل.

عندما يُجلَب المفتاح من خادمك الخلفي (عبر vmAsyncExecutor)، أضف فحوصات قائمة على الجلسة أو الأصل على نقطة النهاية تلك: أعِد المفتاح الصحيح للمستخدمين الحقيقيين (جلسة صالحة، Origin/Referer متوقعان) ومفتاحًا فاسدًا للطلبات المشبوهة (مثل أصل localhost/غير متوقع، أو غياب الجلسة). فيعمل المستخدمون الحقيقيون بشكل طبيعي؛ أما نسخة تعمل خارج بيئتك فتحصل على مفتاح يفكّ إلى لا شيء. والمنطق الدقيق يعتمد على موقعك.

أمثلة:

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

مثال استخدام:

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

يفعّل منفِّذ VM غير المتزامن، الذي يتيح لـ vmBytecodeArrayEncodingKeyGetter أن يُعيد Promise (جالِب مفتاح غير متزامن) — بحيث يمكن جلب مفتاح فك التشفير أثناء التشغيل (طلب شبكة، IndexedDB، إلخ.) بدلًا من وجوب توفّره بشكل متزامن عند تحميل الكود.

يُوصى به بشدة للأكواد غير المتزامنة بالكامل. في هذا الوضع لا يُحاكى افتراضيًا سوى الدوال async — فلا يمكن جعل دالة متزامنة غير متزامنة دون تحويل قيمة إعادتها إلى Promise وكسر مستدعيها — لذا فإن الكود غير المتزامن كليًا يحصل على أوسع تغطية. وهو يعمل أيضًا عندما يكون الجذر متزامنًا (مثل IIFE متزامن / مغلِّف UMD): إذ تُحمى الدوال async الأبعد داخلها، وتُترَك الأجزاء المتزامنة كما هي.

ما الذي يُحوَّل: كل دالة async الأبعد، أينما ظهرت (بما في ذلك المتداخلة داخل مغلِّفات متزامنة). الدالة غير المتزامنة الأبعد في كل سلسلة هي الوحدة المحمية — فكل ما بداخلها، متزامنًا وغير متزامن، يُترجَم ضمنها. أما الدوال المتزامنة والمولِّدات العادية فتُترَك دون تشويش.

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

التخطّيات والتحذيرات. تُترَك المولِّدات غير المتزامنة أيضًا دون تشويش عندما يكون جالِب مفتاح غير متزامن نشطًا (يجب أن يُعيد المولِّد غير المتزامن مُكرِّره بشكل متزامن ولا يمكنه انتظار المفتاح). في الوضع الافتراضي vmTargetFunctionsMode: 'root' تكون التخطّيات صامتة (الاختيار تلقائي)؛ وفي وضع comment يُصدَر تحذير عبر ObfuscationResult.getWarnings() كلما تعذّرت محاكاة دالة علّمتها صراحةً — إمّا لأنها تبيّنت متزامنة، أو لأنها مولِّد غير متزامن تحت جالِب مفتاح غير متزامن.

ويتطلب جالِب المفتاح غير المتزامن إضافةً vmBytecodeArrayEncoding مع vmBytecodeArrayEncodingKeyGetter.

مثال استخدام:

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

يرمّز أهداف القفزات في البايت كود. تُحسَب إزاحات القفز أثناء التشغيل، مما يخفي بنية تدفق التحكم (if/else، الحلقات، إلخ.) عن التحليل الساكن.

vmMacroOps

Type: boolean Default: false

يدمج تسلسلات التعليمات الشائعة في أكواد عمليات "ماكرو" مفردة. فمثلًا، قد يصبح LOAD + ADD + STORE تعليمة MACRO_ADD_TO_VAR واحدة. وهذا يكسر التعرّف على الأنماط وقد يحسّن الأداء.

vmDebugProtection

Type: boolean Default: false

يضيف دفاعات متعددة الطبقات مضادة للتنقيح والتحليل ونماذج LLM إلى بيئة تشغيل VM. يعمل على أفضل نحو مع الأهداف browser/browser-no-eval.

vmSelfDefending

Type: boolean Default: false

يضيف حماية متعددة الطبقات لكشف العبث، ومنع الاعتراض، ومقاومة الهندسة العكسية إلى بيئة تشغيل VM.

⚠️ يفعّل هذا الخيار قسرًا vmBytecodeArrayEncoding.

⚠️ كشف البيئات الحساسة. يربط هذا الخيار الكود المشوَّش ببيئة التشغيل الهدف ويستخدم بصمة متصفح متقدمة لكشف أدوات الأتمتة. والكود المحمي بهذا الخيار سيتعطّل عمدًا عند تشغيله في:

  • المتصفحات مقطوعة الرأس (Chrome/Chromium مقطوع الرأس، PhantomJS)
  • أدوات أتمتة المتصفح (Puppeteer، Playwright، Cypress، Selenium/ChromeDriver، Nightmare)
  • Node.js (عندما يكون target مضبوطًا على browser)
  • jsdom أو محاكاة DOM المشابهة على جانب الخادم
  • البيئات التي اعتُرِض فيها على أدوات المتصفح المدمجة الأصلية أو استُبدلت

والكود سيعمل بشكل صحيح في المتصفحات العادية (Chrome، Firefox، Safari، Edge)، بما في ذلك عند تحميله داخل iframe، وإضافات المتصفح (سكربتات المحتوى)، وWeb Workers. إذا احتجت إلى تشغيل اختبارات آلية على كود محمي، فعطّل vmSelfDefending لعمليات بناء الاختبار — فهذا الخيار مصمَّم لمنع التحليل الآلي ولا يمكن استخدامه بأمان مع أي إطار أتمتة.

يُوصى بشدة باستخدامه مع vmDebugProtection وvmBytecodeArrayEncodingKey وvmBytecodeArrayEncodingKeyGetter.

vmDefenseHook

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

يأخذ vmDefenseHook كائنًا بمفتاحين: name (مطلوب) و**aliases** (اختياري).

name هو دالة عامة تعرّفها صفحتك المُضيفة يستدعيها دفاع VM (vmDebugProtection / vmSelfDefending) بكائن إشارة عندما يكتشف إشارة عدائية — منقّح أو مفتِّش، أو متصفح مقطوع الرأس / أتمتة، أو عملية وكيل برمجة بالذكاء الاصطناعي، أو نطاق غير مسموح، وهكذا. استخدمها للإبلاغ عن الحدث إلى خادمك الخلفي (مثل navigator.sendBeacon). والإشارة (hook) هي مصرف قياس عن بُعد محض: تُتجاهَل قيمة إعادتها، وإشارة غائبة أو تطلق استثناءً هي عملية لا شيء صامتة لا يمكنها أبدًا تعطيل دفاع. ولتغيير ما يفعله الدفاع عند الكشف، استخدم vmDefenseReaction.

aliases يعيد تسمية حقول كائن الإشارة ذاك اختياريًا — مشروح تحت إعادة تسمية حقول الإشارة أدناه.

كائن الإشارة. تتلقى الإشارة signal واحدة:

  • source — الكاشف المحدد الذي أُطلِق (انظر الجدول).
  • category — المجموعة التي يُبلَّغ ضمنها: automation (متصفحات غير بشرية)، أو debugger (منقّح/مفتِّش نشط)، أو sandbox (مُضيف مُجهَّز/مزيَّف)، أو domain (خرق قفل النطاق)، أو tamper (تعديل الأدوات المدمجة أثناء التشغيل)، أو integrity (تغيّر كود VM نفسه).
  • score / threshold — مدى قوة إطلاق الكاشف والقيمة التي كان عليه بلوغها؛ لا تُطلَق الإشارة إلا عندما يكون score >= threshold. معظم الفحوصات كل شيء أو لا شيء (إشارة حاسمة واحدة)؛ أما headless فيجمع عدة إشارات لشكل المتصفح، لذا يكون score لديه أعلى من threshold عادةً.
sourceيكشفcategory
integrityأن كود VM المشوَّش نفسه قد عُدِّلintegrity
nodeكود موجَّه للمتصفح يعمل تحت Node.jsdebugger
debuggerجلسة منقّح أو مفتِّش مرفقة أو نشطة، أو بيئة تنقيحdebugger
headlessاستخدام متصفح مقطوع الرأس لتشغيل الكودautomation
agentوكيل برمجة بالذكاء الاصطناعي يشغّل الكودautomation
timingتوقفًا في التنفيذ يوحي بنقطة توقف أو منقّح يخطو خطوة خطوةdebugger
sandboxأن الكود يعمل في صندوق حماية أو بيئة مُضيف مزيَّفةsandbox
domainأن أصل الصفحة ليس في قائمة السماح vmDomainLockdomain
nativeHookأن دالة مدمجة أصلية قد استُبدلت أو اعتُرِض عليهاtamper

تسجيل الإشارة. عرّفها كمتغير عام عادي قبل تحميل الحزمة المشوَّشة — فبيئة تشغيل VM ودفاعاتها تعمل قبل برنامجك (المحمي)، لذا تُطلَق كثير من عمليات الكشف أثناء بدء التشغيل:

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

الإشارة المعرَّفة داخل المصدر المشوَّش تُسجَّل متأخرة جدًا بحيث لا تلتقط عمليات الكشف وقت بدء التشغيل، وإذا رُمِّزت بـ VM فلا يمكن الوصول إليها حتى يعمل برنامجك. وهي آمنة على أي حال (إشارة غائبة تنفّذ لا شيء، وحارس منع إعادة الدخول يمنع أي انفلات)، لكن للتغطية الكاملة سجّلها مقدَّمًا. ولحماية منطق إبلاغك رغم ذلك، أبقِ الإشارة المسجَّلة عازلًا من سطر واحد ((window.__vmDet = window.__vmDet || []).push(signal)) واقرأ/أرسِل ذلك العازل من كودك المشوَّش.

إعادة تسمية حقول الإشارة (aliases). القيم الافتراضية لـ source/category أسماء وصفية، فيستطيع أي شخص يُجهِّز رد النداء (أو يقرأ الناتج) أن يتعرّف على الحماية وعلى الكاشف الذي أُطلِق. aliases يعيد تسمية حقول الإشارة إلى رموز مبهمة من اختيارك، تُطبَّق داخل VM قبل إصدار الإشارة، بحيث لا تظهر تلك الأسماء أبدًا في الناتج ولا تصل إلى رد النداء. ويعرف تطبيقك التعيين الخاص به ويمرّر الرموز إلى خادمك الخلفي.

الأسماء البديلة لكل حقل، مع إبقاء إعادة تسمية المفاتيح والقيم منفصلة: يأخذ كل حقل key (اسم الخاصية الذي يتلقاه رد النداء)؛ كما يأخذ الحقلان النصيان source وcategory خريطة values، بينما score/threshold رقمان ويأخذان key فقط. الأسماء التي يمكنك تعيينها (وأي شيء آخر يُرفَض وقت البناء):

  • مفاتيح الحقولsource، category، score، threshold
  • قيم sourceheadless، agent، node، debugger، timing، sandbox، domain، nativeHook، integrity
  • قيم 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> }
}

هذا تجنّبٌ للبصمة، لا سرّية — إذ لا يزال بالإمكان استنتاج التعيين بالاختبار المتكرر — فمنفعته الوحيدة هي عدم كشف أسماء ثابتة تفسّر نفسها. والمدخلات غير المضبوطة تبقى بأسمائها الافتراضية.

يُقبَل نص مجرد (vmDefenseHook: '__vmDetection') كاختصار لـ { name: '__vmDetection' } لكنه مهجور — فضّل صيغة الكائن.

vmDefenseReaction

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

يضبط كيفية تفاعل كل فئة كشف. وهو لا يفعّل أي شيء — فالدفاعات نفسها تُشغَّل بواسطة vmSelfDefending وvmDebugProtection وvmDomainLock؛ ولا يختار هذا الخيار سوى كيفية تفاعل دفاع مفعَّل. الفئة هي وحدة التحكم — فكل كاشف في فئة يُنفِّذ تفاعل تلك الفئة.

تجمع كل فئة الكواشف التي تراقب نوعًا واحدًا من الحالات العدائية. ولا تتفاعل الفئة إلا عندما يكون الخيار الذي يُصدِر كواشفها مفعَّلًا:

الفئةيفعّلهاتتفاعل عند
automationvmSelfDefending أو vmDebugProtectionتشغيل الكود ببرمجية بدلًا من شخص: متصفح مقطوع الرأس أو مؤتمت، أو إطار كشط / اختبار، أو وكيل برمجة بالذكاء الاصطناعي يخطو في الصفحة.
debuggervmDebugProtection أو vmSelfDefendingفتح أحدهم منقّحًا أو مفتِّش أدوات المطور في المتصفح وخطوه في الكود العامل لفهمه.
sandboxvmDebugProtectionألّا يعمل الكود في متصفح حقيقي إطلاقًا — إذ نُقِل إلى بيئة JavaScript مُحاكاة أو مُبرمَجة لتنفيذه ودراسته دون اتصال.
domainvmDomainLockتشغيل الكود على موقع لم تصرّح به: مُضيف ليس في قائمة السماح vmDomainLock (مثلًا حزمتك منسوخة على نطاق شخص آخر).
tampervmSelfDefendingتعديل بيئة JavaScript المحيطة بـ VM لمراقبتها أو اختطافها، مثل استبدال أدوات المتصفح المدمجة الأصلية بنسخ مُجهَّزة.
integrityvmSelfDefendingتحرير أو ترقيع كود الحزمة المحمية نفسه منذ توليدك إياه.

تُطابَق كل فئة واحدًا أو أكثر من vmSelfDefending وvmDebugProtection وvmDomainLock؛ ولا توجد فئة خارج تلك الخيارات الثلاثة، وتفاعل مضبوط لفئة خيارها معطَّل ببساطة بلا أثر.

المفاتيح هي أسماء الفئات الست هذه، أو default (احتياطي للفئات غير المحددة). والقيم هي:

  • break — يتوقف فورًا
  • decoy — يستمر في العمل على حالة مسمومة، منتجًا نتائج خاطئة بصمت
  • none — لا يفعل شيئًا محليًا (قياس عن بُعد فقط)

الافتراضيات لكل فئة مبيَّنة أعلاه؛ والفئة التي لا تضبطها (أو تضبطها على قيمتها الافتراضية) تستخدم ذلك الافتراضي. default يصل إلى كل فئة، بما في ذلك الفئات الصحيحة بحكم البناء (integrity وtamper)، لذا فإن { default: 'none' } عملية بناء غير كاسرة حقًا، للقياس عن بُعد فقط:

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

يجعل معاني أكواد العمليات تعتمد على الموضع في البايت كود. لكل موضع تعيين مختلف من كود العملية إلى المعالِج مشتق من بذرة، بحيث يؤدي رقم كود العملية نفسه عمليات مختلفة في مواضع مختلفة.

vmCallContextOpcodes

Type: boolean Default: false

يجعل الدالة المحمية تعتمد على المكان الذي تُستدعى منه، بحيث لا يمكن انتزاعها من الكود وتشغيلها أو تحليلها بمفردها — فهي لا تتصرف بشكل صحيح إلا عند استدعائها عبر مواضع استدعائها الحقيقية في البرنامج. يؤثّر هذا الخيار في أداء التشغيل.

يُدعَم حاليًا فقط التركيبات التالية:

  • تصريحات الدوال (function f() {}
  • تعبيرات الدوال والدوال السهمية المُسنَدة إلى متغير (const f = () => {}
  • التوابع الخاصة للنسخ (this.#m()).

في كل حالة، يجب أن يُوصَل إلى الدالة دائمًا عبر استدعاء مباشر (f()، this.#m()). فإذا خُزِّنت في متغير آخر، أو مُرِّرت كوسيط، أو استُخدمت بأي طريقة أخرى كقيمة، فتُترَك دون حماية. الدوال غير المتزامنة مدعومة؛ أما المولِّدات فلا.

هذا الخيار تجريبي وقد يعطّل عمل كودك، فاختبر الناتج جيدًا قبل استخدامه.

vmStackEncoding

Type: boolean Default: false

يشفّر القيم على مكدس VM أثناء التنفيذ. تُرمَّز القيم عند دفعها وتُفكّ ترميزها عند سحبها، بحيث يُظهر فحص الذاكرة بيانات مشفَّرة بدلًا من القيم الفعلية.

يؤثّر هذا الخيار في الأداء تأثيرًا كبيرًا.

vmCompactDispatcher

Type: boolean Default: false

يستخدم منفِّذ VM واحدًا بدلًا من منفِّذين مزدوجين (متزامن + مولِّد). يقلّل حجم الكود المشوَّش لكنه يضيف حِملًا على الأداء بنحو 20% في الكود كثير التعاود.

  • false (افتراضي): منفِّذان مزدوجان — أداء مثالي، ناتج أكبر
  • true: منفِّذ واحد — ناتج أصغر، أبطأ قليلًا

vmStringArrayBytecodeOnly

Type: boolean Default: false

عند التفعيل، ستستخرج مصفوفة النصوص النصوص من بيانات البايت كود فقط — ولا تُحوَّل أي نصوص أخرى في الكود. وهذا يفعّل stringArray قسرًا حتى لو لم يُضبَط صراحةً.

لماذا تستخدمه: استخراج كل نصوص بيئة تشغيل VM إلى مصفوفة نصوص بطيء. يستهدف هذا الخيار محتوى البايت كود فقط لاستخراج مصفوفة النصوص، مما يحسّن الأداء مع الاستمرار في حماية ثوابت البايت كود.

  • عند vmBytecodeArrayEncoding: false — تُستخرَج النصوص داخل مجمّعات ثوابت البايت كود (مصفوفات c)
  • عند vmBytecodeArrayEncoding: true — تُستخرَج نصوص البايت كود المُرمَّزة بـ base64 على المستوى الأعلى
  • لا يزال stringArrayThreshold يتحكم في نسبة نصوص البايت كود تلك التي تُستخرَج

vmDomainLock

Type: string[] Default: []

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يقصر الكود المشوَّش على نطاقات و/أو نطاقات فرعية بعينها، وهو أصعب بكثير في تحديد موضعه وإزالته من domainLock.

إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بهذا الخيار، فسيُعاد توجيه المتصفح إلى عنوان URL المُمرَّر إلى vmDomainLockRedirectUrl، وستُعيد الاستدعاءات المحمية اللاحقة نتائج غير صحيحة حتى لو كُبِت إعادة التوجيه.

نطاقات ونطاقات فرعية متعددة

يمكن قفل كودك على أكثر من نطاق أو نطاق فرعي. فمثلًا، لقفله بحيث لا يعمل الكود إلا على www.example.com أضف www.example.com. ولجعله يعمل على النطاق الجذري بما في ذلك أي نطاقات فرعية (example.com وsub.example.com)، استخدم .example.com.

vmDomainLockRedirectUrl

Type: string Default: about:blank

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح إعادة توجيه المتصفح إلى عنوان URL مُمرَّر إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بواسطة vmDomainLock.

Preset Options

تشويش عالٍ، أداء منخفض

سيكون الأداء أبطأ بكثير مما هو عليه دون تشويش

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

تشويش متوسط، أداء مثالي

سيكون الأداء أبطأ مما هو عليه دون تشويش

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

تشويش منخفض، أداء عالٍ

سيكون الأداء عند مستوى طبيعي نسبيًا

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

الإعداد المسبق الافتراضي، أداء عالٍ

{
    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 فائق العلو (أقصى أمان)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع كل ميزات التصليب بما في ذلك الإرسال غير المباشر. يوفّر أقوى حماية لكن بحجم ناتج أكبر وتنفيذ أبطأ بكثير.

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

أو اضبط الخيارات بشكل فردي:

{
    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 المضاد لنماذج LLM (حماية من وكلاء الذكاء الاصطناعي)

صُمِّم هذا الإعداد المسبق خصيصًا لمنع وكلاء الذكاء الاصطناعي ونماذج LLM من إجراء هندسة عكسية على الكود المُرمَّز ببايت كود VM. يستند إلى vm-default مع تفعيل الدفاع الذاتي وحماية التنقيح. أخف من vm-high-obfuscation لكنه مصلَّب خصيصًا ضد التحليل الآلي.

{
    optionsPreset: 'vm-anti-llm'
}

يشمل:

  • تشويش بايت كود VM مع مصفوفة النصوص (من vm-default)
  • vmSelfDefending — كشف الاعتراض، وتجزئة السلامة، وبصمة المصدر، والتحقق عبر عالَم iframe نظيف، واشتقاق مفتاح شيفرة ARX
  • vmDebugProtection — فحوصات مضادة للتنقيح في حلقة إرسال VM
  • debugProtection: false — لا حماية تنقيح قديمة (حماية تنقيح VM أفضل)

تشويش VM العالي (أعلى أمان)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع معظم ميزات التصليب. يوفّر حماية قوية بأداء أفضل من الإعداد المسبق فائق العلو.

{
    optionsPreset: 'vm-high-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 المتوسط (أمان متوازن)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع مجموعة متوازنة من ميزات التصليب. حل وسط جيد بين الأمان والأداء.

{
    optionsPreset: 'vm-medium-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 المنخفض (أمان أساسي، أداء أفضل)

يفعّل هذا الإعداد المسبق تشويش بايت كود VM الأساسي دون ميزات تصليب إضافية. توازن جيد بين الأمان وحجم الناتج.

{
    optionsPreset: 'vm-low-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 الافتراضي (VM + حماية مصفوفة النصوص)

يجمع هذا الإعداد المسبق بين تشويش البايت كود الأساسي القائم على VM وحماية مصفوفة النصوص. نقطة بداية جيدة لتشويش VM مع حماية النصوص.

{
    optionsPreset: 'vm-default'
}

أو اضبط الخيارات بشكل فردي:

{
    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

يجمع الكود الناتج في سطر واحد.

config

Type: string Default: ``

اسم ملف الإعدادات بصيغة JS/JSON الذي يحتوي على خيارات المشوِّش. تُتجاوَز هذه الخيارات بالخيارات المُمرَّرة مباشرةً إلى CLI

controlFlowFlattening

Type: boolean Default: false

⚠️ يؤثّر هذا الخيار بشدة في الأداء، إذ قد يبطّئ سرعة التشغيل حتى 1.5 ضعف. استخدم controlFlowFlatteningThreshold لتحديد نسبة العُقد التي سيطالها تسطيح تدفق التحكم.

يفعّل تسطيح تدفق التحكم في الكود. وتسطيح تدفق التحكم هو تحويل بنيوي للكود المصدري يعيق فهم البرنامج.

مثال:

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

احتمال تطبيق تحويل controlFlowFlattening على أي عقدة بعينها.

هذا الإعداد مفيد بوجه خاص مع أحجام الكود الكبيرة، لأن الكميات الكبيرة من تحويلات تدفق التحكم قد تبطّئ كودك وتزيد حجمه.

القيمة controlFlowFlatteningThreshold: 0 تكافئ controlFlowFlattening: false.

deadCodeInjection

Type: boolean Default: false

⚠️ يزيد حجم الكود المشوَّش زيادة كبيرة (حتى 200%)، فلا تستخدمه إلا إذا كان حجم الكود المشوَّش لا يهم. استخدم deadCodeInjectionThreshold لتحديد نسبة العُقد التي سيطالها حقن الكود الميت.
⚠️ يفعّل هذا الخيار قسرًا خيار stringArray.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation.

مع هذا الخيار، تُضاف كتل عشوائية من الكود الميت إلى الكود المشوَّش.

مثال:

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

يتيح تحديد نسبة العُقد التي سيطالها deadCodeInjection.

debugProtection

Type: boolean Default: false

⚠️ قد يجمّد متصفحك إذا فتحت أدوات المطور.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmDebugProtection بدلًا منه.

يجعل هذا الخيار استخدام وظيفة debugger في أدوات المطور شبه مستحيل (سواء في المتصفحات المبنية على WebKit أو في Mozilla Firefox).

debugProtectionInterval

Type: number Default: 0

⚠️ قد يجمّد متصفحك! استخدمه على مسؤوليتك الخاصة.
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmDebugProtection بدلًا منه.

عند ضبطه، يُستخدَم فاصل زمني بالميلي ثانية لفرض وضع التنقيح على علامة تبويب Console، مما يصعّب استخدام ميزات أدوات المطور الأخرى. يعمل إذا كان debugProtection مفعَّلًا. القيمة المُوصى بها بين 2000 و4000 ميلي ثانية.

disableConsoleOutput

Type: boolean Default: false

⚠️ يعطّل هذا الخيار استدعاءات console عالميًا لكل السكربتات

يعطّل استخدام console.log وconsole.info وconsole.error وconsole.warn وconsole.debug وconsole.exception وconsole.trace باستبدالها بدوال فارغة. وهذا يصعّب استخدام المنقّح.

domainLock

Type: string[] Default: []

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح تشغيل الكود المصدري المشوَّش على نطاقات و/أو نطاقات فرعية بعينها فقط. وهذا يصعّب كثيرًا على أي شخص أن ينسخ كودك المصدري ويشغّله في مكان آخر.

إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بهذا الخيار، فسيُعاد توجيه المتصفح إلى عنوان URL المُمرَّر إلى خيار domainLockRedirectUrl.

نطاقات ونطاقات فرعية متعددة

يمكن قفل كودك على أكثر من نطاق أو نطاق فرعي. فمثلًا، لقفله بحيث لا يعمل الكود إلا على www.example.com أضف www.example.com. ولجعله يعمل على النطاق الجذري بما في ذلك أي نطاقات فرعية (example.com وsub.example.com)، استخدم .example.com.

domainLockRedirectUrl

Type: string Default: about:blank

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح إعادة توجيه المتصفح إلى عنوان URL مُمرَّر إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بواسطة domainLock

exclude

Type: string[] Default: []

أسماء ملفات أو أنماط glob تشير إلى الملفات المُستثناة من التشويش.

forceTransformStrings

Type: string[] Default: []

يفعّل التحويل القسري للنصوص الحرفية المطابِقة لأنماط RegExp المُمرَّرة.

⚠️ يؤثّر هذا الخيار فقط في النصوص التي لا ينبغي أن يحوّلها stringArrayThreshold (أو ربما عتبات أخرى مستقبلًا)

للخيار أولوية على خيار reservedStrings لكن لا أولوية له على conditional comments.

مثال:

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

identifierNamesCache

Type: Object | null Default: null

الهدف الأساسي من هذا الخيار هو إمكانية استخدام أسماء المعرِّفات نفسها أثناء تشويش عدة مصادر/ملفات.

يُدعَم حاليًا نوعان من المعرِّفات:

  • المعرِّفات العامة:
    • تُكتب جميع المعرِّفات العامة إلى الذاكرة المؤقتة؛
    • تُستبدل جميع المعرِّفات العامة غير المصرَّح بها المطابِقة بالقيم المأخوذة من الذاكرة المؤقتة.
  • معرِّفات الخصائص، فقط عند تفعيل خيار renameProperties:
    • تُكتب جميع معرِّفات الخصائص إلى الذاكرة المؤقتة؛
    • تُستبدل جميع معرِّفات الخصائص المطابِقة بالقيم المأخوذة من الذاكرة المؤقتة.

واجهة Node.js

إذا مُرِّرت القيمة null، تُعطَّل الذاكرة المؤقتة كليًا.

إذا مُرِّر كائن فارغ ({})، يُفعَّل كتابة أسماء المعرِّفات إلى كائن الذاكرة المؤقتة (من النوع TIdentifierNamesCache). ويمكن الوصول إلى كائن الذاكرة المؤقتة هذا عبر استدعاء التابع getIdentifierNamesCache لكائن ObfuscationResult.

يمكن بعد ذلك استخدام كائن الذاكرة المؤقتة الناتج كقيمة لخيار identifierNamesGenerator لاستعمال هذه الأسماء أثناء تشويش جميع أسماء المعرِّفات المطابِقة في المصادر التالية.

مثال:

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 خيارًا مختلفًا هو --identifier-names-cache-path يتيح تحديد مسار إلى ملف .json موجود يُستخدَم لقراءة الذاكرة المؤقتة لأسماء المعرِّفات وكتابتها.

إذا مُرِّر مسار إلى ملف فارغ، تُكتب الذاكرة المؤقتة لأسماء المعرِّفات إلى ذلك الملف.

يمكن استخدام هذا الملف الذي يحتوي على ذاكرة مؤقتة موجودة مجددًا كقيمة لخيار --identifier-names-cache-path لاستعمال هذه الأسماء أثناء تشويش جميع أسماء المعرِّفات المطابِقة في الملفات التالية.

identifierNamesGenerator

Type: string Default: hexadecimal

يضبط مولِّد أسماء المعرِّفات.

القيم المتاحة:

  • dictionary: أسماء معرِّفات من قائمة identifiersDictionary
  • hexadecimal: أسماء معرِّفات مثل _0xabc123
  • mangled: أسماء معرِّفات قصيرة مثل a وb وc
  • mangled-shuffled: مثل mangled لكن بأبجدية مخلوطة

identifiersDictionary

Type: string[] Default: []

يضبط قاموس المعرِّفات لخيار identifierNamesGenerator: dictionary. سيُستخدَم كل معرِّف من القاموس في بضع صيغ باختلاف حالة الأحرف في كل محرف. ولذلك ينبغي أن يعتمد عدد المعرِّفات في القاموس على كمية المعرِّفات في الكود المصدري الأصلي.

identifiersPrefix

Type: string Default: ''

يضبط بادئة لجميع المعرِّفات العامة.

استخدم هذا الخيار عندما تريد تشويش عدة ملفات. يساعد هذا الخيار على تجنّب التعارضات بين المعرِّفات العامة لهذه الملفات. وينبغي أن تكون البادئة مختلفة لكل ملف.

randomIdentifiersPrefix

Type: boolean Default: false

يُلحق بادئة عشوائية مبنية على بذرة (6 محارف أبجدية رقمية) بجميع المعرِّفات العامة. استخدم هذا الخيار لتجنّب التصادمات بين الحزم المشوَّشة على حدة والمُحمَّلة في النطاق العام نفسه — فهو يغني عن الحاجة إلى اختيار identifiersPrefix فريد لكل حزمة يدويًا.

  • تُشتق القيمة العشوائية من خيار seed ومن بصمة تجزئة الكود المصدري، لذا تُنتج عمليات البناء القابلة للتكرار بالبذرة نفسها البادئة نفسها.
  • عند دمجه مع identifiersPrefix، تُلحق المحارف العشوائية بالبادئة التي قدّمها المستخدم (مثلًا myApp + العشوائي aBc123myAppaBc123).
  • عند دمجه مع vmObfuscation، تحلّ القيمة العشوائية محل البادئة الافتراضية vm — فالعشوائية تضمن التفرّد أصلًا.

ignoreImports

Type: boolean Default: false

يمنع تشويش عمليات الاستيراد عبر require. قد يكون مفيدًا في بعض الحالات عندما تتطلب بيئة التشغيل لسبب ما أن تكون عمليات الاستيراد هذه بنصوص ثابتة فقط.

inputFileName

Type: string Default: ''

يتيح تحديد اسم ملف المُدخل الذي يحتوي على الكود المصدري. يُستخدَم هذا الاسم داخليًا لتوليد خريطة المصدر. مطلوب عند استخدام واجهة NodeJS وامتلاك خيار sourceMapSourcesMode القيمة sources.

log

Type: boolean Default: false

يفعّل تسجيل المعلومات في وحدة التحكم.

numbersToExpressions

Type: boolean Default: false

يفعّل تحويل الأرقام إلى تعبيرات

مثال:

// input
const foo = 1234;

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

optionsPreset

Type: string Default: default

يتيح ضبط إعداد الخيارات المسبق.

القيم المتاحة:

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

ستُدمَج جميع الخيارات الإضافية مع إعداد الخيارات المسبق المُحدَّد.

parseHtml

Type: boolean Default: false

يفعّل تشويش JavaScript داخل وسوم <script> في HTML.

عند التفعيل، سيقوم المشوِّش بما يلي:

  • الكشف التلقائي عمّا إذا كان المُدخل HTML (بالتحقق من وجود وسوم <!DOCTYPE أو <html> أو <head> أو <body> أو <script>)
  • استخراج JavaScript من وسوم <script> المُعلَّمة بالسمة data-javascript-obfuscator
  • تشويش كل سكربت مُعلَّم على حدة مع الحفاظ على بنية HTML
  • إعادة حقن الكود المشوَّش في مواضعه الأصلية

مهم: لا يُشوَّش سوى السكربتات التي تحمل السمة data-javascript-obfuscator. ويُشوَّش كل سكربت مُعلَّم على حدة وباستقلال. وهذا يعني:

  • يجب أن يكون الكود داخل وسوم السكربت المُعلَّمة معزولًا - يجب ألّا يشير إلى متغيرات أو دوال أو أصناف معرَّفة في وسوم سكربت مُعلَّمة أخرى
  • لا يزال بإمكان السكربتات غير المُعلَّمة الوصول إلى المتغيرات العامة التي تعرّفها السكربتات المُعلَّمة (عبر تصريحات var أو إسنادات globalThis الصريحة)
  • يمنحك هذا تحكمًا صريحًا في السكربتات التي تريد حمايتها

يُشوَّش (يجب أن يحمل السمة data-javascript-obfuscator):

  • <script data-javascript-obfuscator> - السكربتات العادية
  • <script type="text/javascript" data-javascript-obfuscator> - السكربتات المُحدَّد نوعها صراحةً
  • السكربتات ذات أي سمات إضافية (id أو class أو data-* أخرى، إلخ.)

يُتخطّى (يُترَك دون تغيير):

  • السكربتات التي لا تحمل السمة data-javascript-obfuscator
  • <script type="module"> - وحدات ES (حتى مع السمة)
  • <script src="..."> - السكربتات الخارجية (حتى مع السمة)
  • وسوم السكربت الفارغة

ملاحظة: لا تُولَّد خرائط المصدر عند تفعيل parseHtml، لأنها لن تُطابِق ناتج HTML بشكل صحيح.

مثال:

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

⚠️ قد يعطّل هذا الخيار عمل كودك. لا تفعّله إلا إذا كنت تعرف ما يفعله!

يفعّل تشويش أسماء المتغيرات والدوال العامة مع تصريحها.

عندما يكون هذا الخيار معطَّلًا ويصرّح كود المُدخل عن دوال أو أصناف في النطاق العام (أي أن الكود غير مغلَّف داخل IIFE)، تُبقى أسماؤها كما هي في الكود المشوَّش — فقد تشير إليها سكربتات أخرى بالاسم. وتحت vmObfuscation يُبلَّغ عن تحذير VMGlobalFunctionNamesNotRenamed يسرد هذه الأسماء، إذ إن جسم الدالة مخفي كبايت كود لكن الاسم القابل للقراءة على المستوى الأعلى لا يزال يكشف ما يفعله الكود (لنموذج LLM مثلًا). ولتجنّب هذا الكشف، غلّف الكود داخل IIFE أو فعّل هذا الخيار.

renameProperties

Type: boolean Default: false

⚠️ قد يعطّل هذا الخيار عمل كودك. لا تفعّله إلا إذا كنت تعرف ما يفعله!

يفعّل إعادة تسمية أسماء الخصائص. وسيُتجاهَل جميع خصائص DOM المدمجة والخصائص في أصناف JavaScript الأساسية.

للتبديل بين الوضعين safe وunsafe لهذا الخيار استخدم خيار renamePropertiesMode.

لضبط صيغة أسماء الخصائص المُعاد تسميتها استخدم خيار identifierNamesGenerator.

للتحكم في الخصائص التي سيُعاد تسميتها استخدم خيار reservedNames.

مثال:

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

⚠️ حتى في الوضع safe، قد يعطّل خيار renameProperties عمل كودك.

يحدّد وضع خيار renameProperties:

  • safe - السلوك الافتراضي بعد الإصدار 2.11.0. يحاول إعادة تسمية الخصائص بطريقة أكثر أمانًا لمنع أخطاء التشغيل. مع هذا الوضع، تُستثنى بعض الخصائص من إعادة التسمية.
  • unsafe - السلوك الافتراضي قبل الإصدار 2.11.0. يعيد تسمية الخصائص بطريقة غير آمنة دون أي قيود.

إذا كان أحد الملفات يستخدم خصائص من ملف آخر، فاستخدم خيار identifierNamesCache للحفاظ على أسماء الخصائص نفسها بين هذه الملفات.

reservedNames

Type: string[] Default: []

يعطّل تشويش وتوليد المعرِّفات المطابِقة لأنماط RegExp المُمرَّرة.

مثال:

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

reservedStrings

Type: string[] Default: []

يعطّل تحويل النصوص الحرفية المطابِقة لأنماط RegExp المُمرَّرة. وتبقى النصوص المطابِقة ظاهرة في الناتج المشوَّش.

عند استخدام تشويش VM، تُخزَّن النصوص المحجوزة في مصفوفة منفصلة غير مشفَّرة لإبقائها ظاهرة. وهذا مفيد للنصوص التي يجب أن تبقى قابلة للقراءة، مثل نقاط نهاية API للمراقبة أو معرِّفات المكتبات.

مثال:

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

seed

Type: string|number Default: 0

يضبط هذا الخيار بذرة مولِّد الأرقام العشوائية. وهذا مفيد لإنشاء نتائج قابلة للتكرار.

إذا كانت البذرة 0، فسيعمل مولِّد الأرقام العشوائية بلا بذرة.

selfDefending

Type: boolean Default: false

⚠️ لا تغيّر الكود المشوَّش بأي شكل بعد التشويش بهذا الخيار، لأن أي تغيير مثل ضغط الكود قد يفعّل الدفاع الذاتي فيتوقف الكود عن العمل!
⚠️ يضبط هذا الخيار قسرًا قيمة compact إلى true
⚠️ يُعطَّل هذا الخيار بصمت عند تفعيل vmObfuscation. استخدم vmSelfDefending بدلًا منه.

يجعل هذا الخيار الكود الناتج صامدًا أمام إعادة التنسيق وإعادة تسمية المتغيرات. فإذا حاول أحد استخدام مُجمِّل JavaScript على الكود المشوَّش، فسيتوقف الكود عن العمل، مما يصعّب فهمه وتعديله.

simplify

Type: boolean Default: true

يفعّل تشويشًا إضافيًا للكود عبر التبسيط.

⚠️ في الإصدارات المستقبلية سيُنقَل تشويش النصوص الحرفية من نوع boolean (true => !![]) ليكون ضمن هذا الخيار.

مثال:

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

يفعّل توليد خريطة المصدر للكود المشوَّش.

قد تكون خرائط المصدر مفيدة لمساعدتك على تنقيح كود JavaScript المصدري المشوَّش. فإذا أردت أو احتجت إلى التنقيح في بيئة الإنتاج، يمكنك رفع ملف خريطة المصدر المنفصل إلى موقع سرّي ثم توجيه متصفحك إليه.

sourceMapBaseUrl

Type: string Default: ``

يضبط عنوان URL الأساسي لعنوان استيراد خريطة المصدر عند sourceMapMode: 'separate'.

مثال CLI:

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

النتيجة:

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

sourceMapFileName

Type: string Default: ``

يضبط اسم ملف خريطة المصدر الناتجة عند sourceMapMode: 'separate'.

مثال CLI:

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

النتيجة:

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

sourceMapMode

Type: string Default: separate

يحدّد وضع توليد خريطة المصدر:

  • inline - يضيف خريطة المصدر في نهاية كل ملف ‎.js؛
  • separate - يولّد ملف '.map' مقابلًا يحتوي على خريطة المصدر. وفي حال تشغيل المشوِّش عبر CLI، يضيف رابطًا إلى ملف خريطة المصدر في نهاية ملف الكود المشوَّش //# sourceMappingUrl=file.js.map.

sourceMapSourcesMode

Type: string Default: sources-content

يتيح التحكم في الحقلين sources وsourcesContent لخريطة المصدر:

  • sources-content - يضيف حقل sources وهميًا، ويضيف حقل sourcesContent مع الكود المصدري الأصلي؛
  • sources - يضيف حقل sources مع وصف مصدر صالح، ولا يضيف حقل sourcesContent. وعند استخدام واجهة NodeJS يلزم تحديد خيار inputFileName الذي سيُستخدَم كقيمة لحقل sources.

splitStrings

Type: boolean Default: false

يقسّم النصوص الحرفية إلى أجزاء بطول قيمة خيار splitStringsChunkLength.

مثال:

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

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

splitStringsChunkLength

Type: number Default: 10

يضبط طول أجزاء خيار splitStrings.

stringArray

Type: boolean Default: true

يزيل النصوص الحرفية ويضعها في مصفوفة خاصة. فمثلًا، النص "Hello World" في var m = "Hello World"; سيُستبدَل بشيء مثل var m = _0x12c456[0x1];

stringArrayCallsTransform

Type: boolean Default: false

⚠️ يجب تفعيل خيار stringArray

يفعّل تحويل الاستدعاءات إلى stringArray. قد تُستخرَج جميع وسائط هذه الاستدعاءات إلى كائن مختلف اعتمادًا على قيمة stringArrayCallsTransformThreshold. وهذا يزيد صعوبة العثور تلقائيًا على الاستدعاءات إلى مصفوفة النصوص.

مثال:

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

⚠️ يجب تفعيل خياري stringArray وstringArrayCallsTransformThreshold

يمكنك استخدام هذا الإعداد لضبط الاحتمال (من 0 إلى 1) بأن تُحوَّل الاستدعاءات إلى مصفوفة النصوص.

stringArrayEncoding

Type: string[] Default: []

⚠️ يجب تفعيل خيار stringArray

قد يبطّئ هذا الخيار سكربتك.

يرمّز جميع النصوص الحرفية في stringArray باستخدام base64 أو rc4 ويُدرج كودًا خاصًا يُستخدَم لفك ترميزها مجددًا أثناء التشغيل.

سيُرمَّز كل قيمة من stringArray بالترميز المُنتقى عشوائيًا من القائمة المُمرَّرة. وهذا يتيح استخدام عدة ترميزات.

القيم المتاحة:

  • 'none' (boolean): لا يرمّز قيمة stringArray
  • 'base64' (string): يرمّز قيمة stringArray باستخدام base64
  • 'rc4' (string): يرمّز قيمة stringArray باستخدام rc4. أبطأ من base64 بنحو 30-50%، لكنه يصعّب الحصول على القيم الأولية.

فمثلًا، مع قيم الخيار التالية لن يُرمَّز بعض قيم stringArray، وسيُرمَّز بعضها الآخر بترميز base64 وrc4:

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

stringArrayIndexesType

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

⚠️ يجب تفعيل خيار stringArray

يتيح التحكم في نوع فهارس استدعاء مصفوفة النصوص.

سيُحوَّل كل فهرس استدعاء لـ stringArray بالنوع المُنتقى عشوائيًا من القائمة المُمرَّرة. وهذا يتيح استخدام عدة أنواع.

القيم المتاحة:

  • 'hexadecimal-number' (default): يحوّل فهارس استدعاء مصفوفة النصوص كأرقام ست عشرية
  • 'hexadecimal-numeric-string': يحوّل فهارس استدعاء مصفوفة النصوص كنص عددي ست عشري

قبل الإصدار 2.9.0 كان javascript-obfuscator يحوّل جميع فهارس استدعاء مصفوفة النصوص بالنوع hexadecimal-numeric-string. وهذا يصعّب بعض إزالة التشويش اليدوية قليلًا، لكنه يتيح كشف هذه الاستدعاءات بسهولة بواسطة أدوات إزالة التشويش التلقائية.

يهدف النوع الجديد hexadecimal-number إلى تصعيب الكشف التلقائي عن أنماط استدعاء مصفوفة النصوص في الكود.

سيُضاف مزيد من الأنواع مستقبلًا.

stringArrayIndexShift

Type: boolean Default: true

⚠️ يجب تفعيل خيار stringArray

يفعّل إزاحة فهرس إضافية لجميع استدعاءات مصفوفة النصوص

stringArrayRotate

Type: boolean Default: true

⚠️ يجب تفعيل stringArray

يزيح مصفوفة stringArray بمقدار ثابت وعشوائي (يُولَّد عند تشويش الكود) من المواضع. وهذا يصعّب مطابقة ترتيب النصوص المُزالة بمواضعها الأصلية.

stringArrayShuffle

Type: boolean Default: true

⚠️ يجب تفعيل stringArray

يخلط عناصر مصفوفة stringArray عشوائيًا.

stringArrayWrappersCount

Type: number Default: 1

⚠️ يجب تفعيل خيار stringArray

يضبط عدد المغلِّفات لـ string array داخل كل نطاق جذري أو نطاق دالة. والعدد الفعلي للمغلِّفات داخل كل نطاق محدود بعدد عُقد literal ضمن هذا النطاق.

مثال:

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

⚠️ يجب تفعيل خياري stringArray وstringArrayWrappersCount

يفعّل الاستدعاءات المتسلسلة بين مغلِّفات string array.

مثال:

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

⚠️ يجب تفعيل خيار stringArray
⚠️ يؤثّر هذا الخيار حاليًا فقط في المغلِّفات المُضافة بقيمة خيار stringArrayWrappersType المساوية function

يتيح التحكم في العدد الأقصى لمعاملات مغلِّفات مصفوفة النصوص. القيمة الافتراضية والدنيا هي 2. القيمة المُوصى بها بين 2 و5.

stringArrayWrappersType

Type: string Default: variable

⚠️ يجب تفعيل خياري stringArray وstringArrayWrappersCount

يتيح اختيار نوع المغلِّفات التي يضيفها خيار stringArrayWrappersCount.

القيم المتاحة:

  • 'variable': يضيف مغلِّفات متغيرات في أعلى كل نطاق. أداء سريع.
  • 'function': يضيف مغلِّفات دوال في مواضع عشوائية داخل كل نطاق. أداء أبطأ من variable لكنه يوفّر تشويشًا أكثر صرامة.

يُوصى بشدة باستخدام مغلِّفات function لتشويش أعلى عندما لا يكون لخسارة الأداء تأثير كبير على التطبيق المشوَّش.

مثال على قيمة الخيار '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

⚠️ يجب تفعيل خيار stringArray

يمكنك استخدام هذا الإعداد لضبط الاحتمال (من 0 إلى 1) بأن يُدرَج نص حرفي في stringArray.

هذا الإعداد مفيد بوجه خاص مع أحجام الكود الكبيرة لأنه يستدعي string array مرارًا وقد يبطّئ كودك.

القيمة stringArrayThreshold: 0 تكافئ stringArray: false.

strictMode

Type: boolean | null Default: null

يتيح تحديد كيف ينبغي للمشوِّش أن يعامل الكود فيما يخص الوضع الصارم في JavaScript.

القيم المتاحة:

  • null (افتراضي) - كشف الوضع الصارم تلقائيًا من الكود. إذا كان الكود يحتوي على توجيه 'use strict' صريح، أو بنية وحدة ES، أو توابع أصناف، فيُعامَل على أنه وضع صارم. وإلا يُفترَض الوضع المتساهل.
  • true - فرض معاملة الوضع الصارم لكل الكود، حتى دون توجيه 'use strict' صريح. استخدم هذا عندما يعمل كودك في سياق وضع صارم (مثلًا في وحدات ES أو أدوات التحزيم أو أطر العمل الحديثة).
  • false - لا يُعامَل على أنه صارم إلا مؤشرات الوضع الصارم الصريحة ('use strict'، وحدات ES، توابع الأصناف). ولا يزال توريث نطاق الأب مطبَّقًا وفق مواصفة JS.

target

Type: string Default: browser

يتيح ضبط البيئة الهدف للكود المشوَّش.

القيم المتاحة:

  • browser (افتراضي) — بيئة صفحة ويب قياسية. الكود الناتج مطابق لـ node، لكن لا يُسمح باستخدام بعض الخيارات الخاصة بالمتصفح مع الهدف node
  • browser-no-eval — مثل browser، لكن الناتج لا يستخدم eval(). استخدمه عندما تفرض الصفحة الهدف سياسة أمان محتوى تمنع eval/unsafe-eval.
  • node — بيئة Node.js. تُعطَّل الخيارات الخاصة بالمتصفح (فهي تتطلب window/document وستكون بلا أثر أو ستطلق استثناءً في Node). ولا تُصدَر لهذا الهدف بعض دفاعات vmSelfDefending التي تعتمد على واجهات برمجية خاصة بالمتصفح — كشف المتصفح مقطوع الرأس، والتعافي عبر عالَم نظيف قائم على iframe، وفحوصات مضادة للمفتِّش/DOM.
  • service-worker — سياق Service Worker. لا window، ولا document، ومتغيّر self عام مختلف.
  • userscript — صندوق حماية مدير سكربتات المستخدم (مثل Tampermonkey). تُعدَّل دفاعات vmSelfDefending تبعًا لذلك.
  • bytenode — كود Node.js سيُترجَم بواسطة مُحمِّل bytenode (بايت كود V8 المُخزَّن .jsc) بعد التشويش. لا يستدعي المشوِّش نفسه bytenode؛ بل يُصدر JavaScript مشوَّشًا بـ VM بُنيت بيئة تشغيله لتصمد أمام خطوة ترجمة bytenode، وتُعدَّل دفاعات vmSelfDefending تبعًا لذلك. شغّل bytenode بنفسك على الناتج المشوَّش لإنتاج ملف .jsc النهائي.

transformObjectKeys

Type: boolean Default: false

يفعّل تحويل مفاتيح الكائنات.

مثال:

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

يتحكم في تحذيرات التشويش غير القاتلة التي تُصدَر عبر التابع ObfuscationResult.getWarnings().

القيم المتاحة:

  • 'all' (افتراضي) — يُصدَر كل تحذير.
  • 'none' — تُكتَم كل التحذيرات.
  • كائن يربط أنواع التحذيرات بقيم منطقية — النوع المربوط بـ false يُكتَم؛ وكل نوع غير موجود (أو مربوط بـ true) يبقى مفعَّلًا. فمثلًا، { "VMGlobalFunctionNamesNotRenamed": false } يبقي كل تحذير عدا ذاك.

أنواع التحذيرات:

  • VMGlobalFunctionNamesNotRenamed — تحت vmObfuscation، بقيت أسماء تصريحات الدوال على المستوى الأعلى، وتصريحات الأصناف، والمتغيرات المُسنَد إليها تعبير دالة/سهمية/صنف كما هي (خيار renameGlobals معطَّل والكود غير مغلَّف داخل IIFE)، فتبقى قابلة للقراءة في الناتج رغم إخفاء الأجسام كبايت كود. ولا يُبلَّغ عن الأسماء المُصدَّرة.
  • VMTopLevelInitializerNotVirtualized — بقيت مُهيّئات المتغيرات على المستوى الأعلى بصيغة JavaScript عادية تحت تشويش VM لأن vmWrapTopLevelInitializers معطَّل أو تعذّر عليه محاكاتها افتراضيًا.
  • DynamicCodeRenameRisk — يبني الكود دالة من نص أثناء التشغيل (عبر eval المباشر، أو باني Function، أو fn.toString() المحقون في <script>/Worker)، وقد يشير ذلك إلى معرِّفات أعاد المشوِّش تسميتها.
  • VMDynamicCodeSkipped — تُخطّي دالة من ترميز بايت كود VM لأنها تحتوي على eval مباشر / new Function ديناميكي / Function (انظر vmForceCompileDynamicCode).
  • VMSyncFunctionSkippedInAsyncMode — مع تفعيل vmAsyncExecutor، تبيّن أن دالة علّمتها صراحةً في وضع comment متزامنة فتُخطّيت (لا يُحاكى افتراضيًا في ذلك الوضع سوى الدوال غير المتزامنة).
  • VMAsyncGeneratorSkippedInAsyncMode — مع تفعيل vmAsyncExecutor وجالِب مفتاح غير متزامن نشط، تعذّرت محاكاة مولِّد غير متزامن مُعلَّم افتراضيًا (يجب أن يُعيد مُكرِّره بشكل متزامن).
  • BrowserTargetWithNodeStyleCode — يبدو أن الكود يستهدف Node.js (مثل require('fs') أو __dirname أو process.argv) بينما خيار target مضبوط على بيئة شبيهة بالمتصفح.

vmObfuscation

Type: boolean Default: false

يفعّل تشويش البايت كود القائم على VM. عند التفعيل، تُترجَم دوال JavaScript إلى بايت كود مخصص يعمل على آلة افتراضية مضمَّنة. وهذا يوفّر أعلى مستوى من الحماية إذ يُحوَّل منطق الكود الأصلي بالكامل.

مثال: كودك القابل للقراءة مثل return qty * price يصبح قائمة من الأرقام مثل [0x15,0x03,0x17,...] لا يستطيع تنفيذها سوى مفسِّر VM المضمَّن. ولم يعد المنطق الأصلي ظاهرًا بصيغة JavaScript.

vmTargetFunctions

Type: string[] Default: []

حدّد بدقّة أيّ دوال على المستوى الجذري ينبغي أن تحصل على حماية VM بالاسم.

مثال:

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

النتيجة: هذه الدوال الثلاث فقط تحصل على حماية VM. وكل ما عداها يبقى JavaScript عاديًا (لكنه مشوَّش مع ذلك). مثالي لحماية فحوصات التراخيص الحساسة أو منطق المصادقة مع إبقاء بقية كودك رشيقًا.

vmExcludeFunctions

Type: string[] Default: []

حدّد الدوال على المستوى الجذري التي ينبغي ألّا تحصل أبدًا على حماية VM. له الأسبقية على الإعدادات الأخرى.

مثال:

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

متى تستخدمه: يمكن استثناء الدوال الحرجة للأداء على المستوى الجذري (حلقات الرسوم المتحركة، ومعالجة البيانات الفورية) لتجنّب حِمل VM مع الاستمرار في حماية كل شيء آخر.

vmTargetFunctionsMode

Type: string Default: root

يتحكم في كيفية اختيار الدوال/التوابع لتشويش VM.

الوضعالوصف
rootالسلوك الافتراضي. تُؤخَذ الدوال على المستوى الجذري فقط بعين الاعتبار لتشويش VM. يستخدم قائمة السماح vmTargetFunctions وقائمة المنع vmExcludeFunctions للتصفية.
commentلا يُشوَّش بـ VM سوى الدوال/التوابع المُزيَّنة بتعليق /* javascript-obfuscator:vm */. يعمل مع الدوال/التوابع عند أي مستوى تداخل.

مثال - وضع 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'
}

متى تستخدمه: عندما تحتاج إلى تحكم دقيق في الدوال التي تحصل تحديدًا على حماية VM، خصوصًا الدوال المتداخلة التي تحتوي على منطق حساس. فخلافًا لـ vmTargetFunctions الذي لا يعمل إلا مع الدوال المُسمّاة على المستوى الجذري، يتيح لك وضع comment حماية أي دالة في أي مكان من كودك.

vmForceCompileDynamicCode

Type: boolean Default: false

يتحكم فيما يفعله تشويش VM مع دالة تحتوي على استدعاء eval مباشر، أو new Function(...)، أو Function(...).

افتراضيًا، تُخطّى مثل هذه الدالة (وكل دالة معرَّفة داخلها) من ترميز بايت كود VM ويُبلَّغ عن تحذير VMDynamicCodeSkipped في result.getWarnings(). وذلك لأن المصدر المبني أثناء التشغيل قد يشير إلى معرِّفات من سلسلة النطاقات المحيطة — معرِّفات أعاد المشوِّش تسميتها.

عند ضبطه على true، تُرمَّز الدالة إلى بايت كود على أي حال ولا يُصدَر تحذير VMDynamicCodeSkipped بعد ذلك.

ويستمر إطلاق تحذير DynamicCodeRenameRisk المنفصل بصرف النظر عن هذا الخيار، لأن خطر إعادة التسمية الذي يصفه مستقل عن تخطّي VM — فتفعيل هذا الخيار لا يجعل النمط الأساسي أكثر أمانًا.

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

مع إيقاف الخيار (الافتراضي)، تُترَك loadConfig بصيغة JavaScript عادية. ومع تفعيله، تُترجَم loadConfig إلى بايت كود VM مثل أي دالة أخرى. استخدم هذا عندما تكون قد راجعت موضع الاستدعاء وتعرف أن الكود المبني أثناء التشغيل لا يعتمد على معرِّفات مُعاد تسميتها في الإغلاق.

vmWrapTopLevelInitializers

Type: boolean Default: false

يغلّف بعض مُهيّئات المتغيرات على المستوى الأعلى داخل IIFE (تعبيرات دوال مُستدعاة فورًا) حتى يمكن تشويشها بـ VM.

ما يفعله: دون هذا الخيار، تبقى الثوابت والمتغيرات على المستوى الأعلى ظاهرة في الناتج:

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

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

مع تفعيل هذا الخيار، يُغلَّف المُهيّئ داخل IIFE يُشوَّش بـ VM:

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

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

ملاحظة: لا يعمل هذا الخيار إلا عندما يكون vmTargetFunctionsMode بقيمة 'root' (الافتراضي).

vmDynamicOpcodes

Type: boolean Default: false

يجعل مفسِّر VM أصغر وفريدًا لكل عملية بناء.

ما يفعله:

  1. يصفّي التعليمات غير المستخدمة - إذا كان كودك لا يستخدم الأصناف، تُزال التعليمات المتعلقة بالأصناف كليًا
  2. يعشوِئ البنية - يُخلَط ترتيب معالِجات التعليمات في كل عملية بناء

والنتيجة - ناتج أصغر وكل عملية بناء تبدو مختلفة.

vmBytecodeEncoding

Type: boolean Default: false

يرمّز كل تعليمة بايت كود. تُفكّ ترميز التعليمات واحدة تلو الأخرى أثناء التنفيذ.

vmBytecodeArrayEncoding

Type: boolean Default: false

يرمّز مصفوفة البايت كود بأكملها ككتلة واحدة. تُفكّ ترميز المصفوفة مرة واحدة عند بدء التشغيل قبل بدء التنفيذ. استخدمه مع vmBytecodeEncoding للحصول على طبقتي حماية.

vmBytecodeArrayEncodingKey

Type: string Default: ''

مفتاح تشفير مخصص لترميز مصفوفة البايت كود. عند ضبطه، يُستخدَم هذا المفتاح بدلًا من المفتاح الافتراضي المشتق من البيئة. يجب توفير المفتاح أثناء التشغيل عبر vmBytecodeArrayEncodingKeyGetter.

يُخرج هذا الخيار مفتاح التشفير خارجيًا - فهو غير مضمَّن في الكود المشوَّش نفسه. ومع أن المفتاح لا يزال متاحًا أثناء التشغيل (وبالتالي ليس سرّيًا حقًا)، فإن هذا الفصل يمنع أدوات التحليل الساكن من العثور على المفتاح بفحص الكود وحده.

مهم: يجب أن يكون المفتاح متاحًا بشكل متزامن عند تحميل الكود المشوَّش. استخدم تخزينًا متزامنًا مثل الكوكيز، أو localStorage، أو sessionStorage، أو المتغيرات العامة، أو عناصر DOM (مثل وسوم meta المحقونة من الخادم). ولا يمكن استخدام الطرق غير المتزامنة مثل fetch() مباشرةً في تعبير جالِب المفتاح.

vmBytecodeArrayEncodingKeyGetter

Type: string Default: ''

تعبير JavaScript متزامن يُعيد مفتاح التشفير أثناء التشغيل. يُقيَّم هذا التعبير عند تحميل الكود المشوَّش، ويجب أن يُعيد المفتاح نفسه الذي قُدِّم في vmBytecodeArrayEncodingKey. ولحل المفتاح بشكل غير متزامن (عبر Promise)، فعّل vmAsyncExecutor.

ملاحظة: الجالِب الذي يُعيد Promise يتطلب vmAsyncExecutor. ولا يمكن التحقق من ذلك وقت البناء، لذا فإن جالِبًا يُعيد Promise مع vmAsyncExecutor معطَّل يفشل أثناء التشغيل — إذ يتلقى فاكّ الترميز الـ Promise بدلًا من المفتاح.

لن يعمل الكود المشوَّش إلا عندما يُعيد جالِب المفتاح المفتاح نفسه تمامًا الذي استُخدِم أثناء التشويش. فإذا لم يتطابق المفتاحان، سيفشل فك التشفير وسيُنتج الكود بيانات فاسدة أو أخطاء. وإذا أعاد جالِب المفتاح undefined أو null أو نصًا فارغًا، فسيطلق الكود خطأً: "VM decryption key not available".

مهم: أبقِ المفتاح خارج الملف/السكربت نفسه الذي يحوي الكود المشوَّش — فتضمينه هناك يتيح استعادته حتى بفحص ساكن محض للحزمة. خزّنه في مصدر منفصل بدلًا من ذلك: كوكيز يضبطها الخادم، أو localStorage يملؤه سكربت آخر، أو وسم meta في HTML محقون من الخادم، أو متغير عام يضبطه سكربت مختلف، أو (مع vmAsyncExecutor) يُجلَب من خادمك الخلفي أثناء التشغيل.

عندما يُجلَب المفتاح من خادمك الخلفي (عبر vmAsyncExecutor)، أضف فحوصات قائمة على الجلسة أو الأصل على نقطة النهاية تلك: أعِد المفتاح الصحيح للمستخدمين الحقيقيين (جلسة صالحة، Origin/Referer متوقعان) ومفتاحًا فاسدًا للطلبات المشبوهة (مثل أصل localhost/غير متوقع، أو غياب الجلسة). فيعمل المستخدمون الحقيقيون بشكل طبيعي؛ أما نسخة تعمل خارج بيئتك فتحصل على مفتاح يفكّ إلى لا شيء. والمنطق الدقيق يعتمد على موقعك.

أمثلة:

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

مثال استخدام:

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

يفعّل منفِّذ VM غير المتزامن، الذي يتيح لـ vmBytecodeArrayEncodingKeyGetter أن يُعيد Promise (جالِب مفتاح غير متزامن) — بحيث يمكن جلب مفتاح فك التشفير أثناء التشغيل (طلب شبكة، IndexedDB، إلخ.) بدلًا من وجوب توفّره بشكل متزامن عند تحميل الكود.

يُوصى به بشدة للأكواد غير المتزامنة بالكامل. في هذا الوضع لا يُحاكى افتراضيًا سوى الدوال async — فلا يمكن جعل دالة متزامنة غير متزامنة دون تحويل قيمة إعادتها إلى Promise وكسر مستدعيها — لذا فإن الكود غير المتزامن كليًا يحصل على أوسع تغطية. وهو يعمل أيضًا عندما يكون الجذر متزامنًا (مثل IIFE متزامن / مغلِّف UMD): إذ تُحمى الدوال async الأبعد داخلها، وتُترَك الأجزاء المتزامنة كما هي.

ما الذي يُحوَّل: كل دالة async الأبعد، أينما ظهرت (بما في ذلك المتداخلة داخل مغلِّفات متزامنة). الدالة غير المتزامنة الأبعد في كل سلسلة هي الوحدة المحمية — فكل ما بداخلها، متزامنًا وغير متزامن، يُترجَم ضمنها. أما الدوال المتزامنة والمولِّدات العادية فتُترَك دون تشويش.

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

التخطّيات والتحذيرات. تُترَك المولِّدات غير المتزامنة أيضًا دون تشويش عندما يكون جالِب مفتاح غير متزامن نشطًا (يجب أن يُعيد المولِّد غير المتزامن مُكرِّره بشكل متزامن ولا يمكنه انتظار المفتاح). في الوضع الافتراضي vmTargetFunctionsMode: 'root' تكون التخطّيات صامتة (الاختيار تلقائي)؛ وفي وضع comment يُصدَر تحذير عبر ObfuscationResult.getWarnings() كلما تعذّرت محاكاة دالة علّمتها صراحةً — إمّا لأنها تبيّنت متزامنة، أو لأنها مولِّد غير متزامن تحت جالِب مفتاح غير متزامن.

ويتطلب جالِب المفتاح غير المتزامن إضافةً vmBytecodeArrayEncoding مع vmBytecodeArrayEncodingKeyGetter.

مثال استخدام:

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

يرمّز أهداف القفزات في البايت كود. تُحسَب إزاحات القفز أثناء التشغيل، مما يخفي بنية تدفق التحكم (if/else، الحلقات، إلخ.) عن التحليل الساكن.

vmMacroOps

Type: boolean Default: false

يدمج تسلسلات التعليمات الشائعة في أكواد عمليات "ماكرو" مفردة. فمثلًا، قد يصبح LOAD + ADD + STORE تعليمة MACRO_ADD_TO_VAR واحدة. وهذا يكسر التعرّف على الأنماط وقد يحسّن الأداء.

vmDebugProtection

Type: boolean Default: false

يضيف دفاعات متعددة الطبقات مضادة للتنقيح والتحليل ونماذج LLM إلى بيئة تشغيل VM. يعمل على أفضل نحو مع الأهداف browser/browser-no-eval.

vmSelfDefending

Type: boolean Default: false

يضيف حماية متعددة الطبقات لكشف العبث، ومنع الاعتراض، ومقاومة الهندسة العكسية إلى بيئة تشغيل VM.

⚠️ يفعّل هذا الخيار قسرًا vmBytecodeArrayEncoding.

⚠️ كشف البيئات الحساسة. يربط هذا الخيار الكود المشوَّش ببيئة التشغيل الهدف ويستخدم بصمة متصفح متقدمة لكشف أدوات الأتمتة. والكود المحمي بهذا الخيار سيتعطّل عمدًا عند تشغيله في:

  • المتصفحات مقطوعة الرأس (Chrome/Chromium مقطوع الرأس، PhantomJS)
  • أدوات أتمتة المتصفح (Puppeteer، Playwright، Cypress، Selenium/ChromeDriver، Nightmare)
  • Node.js (عندما يكون target مضبوطًا على browser)
  • jsdom أو محاكاة DOM المشابهة على جانب الخادم
  • البيئات التي اعتُرِض فيها على أدوات المتصفح المدمجة الأصلية أو استُبدلت

والكود سيعمل بشكل صحيح في المتصفحات العادية (Chrome، Firefox، Safari، Edge)، بما في ذلك عند تحميله داخل iframe، وإضافات المتصفح (سكربتات المحتوى)، وWeb Workers. إذا احتجت إلى تشغيل اختبارات آلية على كود محمي، فعطّل vmSelfDefending لعمليات بناء الاختبار — فهذا الخيار مصمَّم لمنع التحليل الآلي ولا يمكن استخدامه بأمان مع أي إطار أتمتة.

يُوصى بشدة باستخدامه مع vmDebugProtection وvmBytecodeArrayEncodingKey وvmBytecodeArrayEncodingKeyGetter.

vmDefenseHook

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

يأخذ vmDefenseHook كائنًا بمفتاحين: name (مطلوب) و**aliases** (اختياري).

name هو دالة عامة تعرّفها صفحتك المُضيفة يستدعيها دفاع VM (vmDebugProtection / vmSelfDefending) بكائن إشارة عندما يكتشف إشارة عدائية — منقّح أو مفتِّش، أو متصفح مقطوع الرأس / أتمتة، أو عملية وكيل برمجة بالذكاء الاصطناعي، أو نطاق غير مسموح، وهكذا. استخدمها للإبلاغ عن الحدث إلى خادمك الخلفي (مثل navigator.sendBeacon). والإشارة (hook) هي مصرف قياس عن بُعد محض: تُتجاهَل قيمة إعادتها، وإشارة غائبة أو تطلق استثناءً هي عملية لا شيء صامتة لا يمكنها أبدًا تعطيل دفاع. ولتغيير ما يفعله الدفاع عند الكشف، استخدم vmDefenseReaction.

aliases يعيد تسمية حقول كائن الإشارة ذاك اختياريًا — مشروح تحت إعادة تسمية حقول الإشارة أدناه.

كائن الإشارة. تتلقى الإشارة signal واحدة:

  • source — الكاشف المحدد الذي أُطلِق (انظر الجدول).
  • category — المجموعة التي يُبلَّغ ضمنها: automation (متصفحات غير بشرية)، أو debugger (منقّح/مفتِّش نشط)، أو sandbox (مُضيف مُجهَّز/مزيَّف)، أو domain (خرق قفل النطاق)، أو tamper (تعديل الأدوات المدمجة أثناء التشغيل)، أو integrity (تغيّر كود VM نفسه).
  • score / threshold — مدى قوة إطلاق الكاشف والقيمة التي كان عليه بلوغها؛ لا تُطلَق الإشارة إلا عندما يكون score >= threshold. معظم الفحوصات كل شيء أو لا شيء (إشارة حاسمة واحدة)؛ أما headless فيجمع عدة إشارات لشكل المتصفح، لذا يكون score لديه أعلى من threshold عادةً.
sourceيكشفcategory
integrityأن كود VM المشوَّش نفسه قد عُدِّلintegrity
nodeكود موجَّه للمتصفح يعمل تحت Node.jsdebugger
debuggerجلسة منقّح أو مفتِّش مرفقة أو نشطة، أو بيئة تنقيحdebugger
headlessاستخدام متصفح مقطوع الرأس لتشغيل الكودautomation
agentوكيل برمجة بالذكاء الاصطناعي يشغّل الكودautomation
timingتوقفًا في التنفيذ يوحي بنقطة توقف أو منقّح يخطو خطوة خطوةdebugger
sandboxأن الكود يعمل في صندوق حماية أو بيئة مُضيف مزيَّفةsandbox
domainأن أصل الصفحة ليس في قائمة السماح vmDomainLockdomain
nativeHookأن دالة مدمجة أصلية قد استُبدلت أو اعتُرِض عليهاtamper

تسجيل الإشارة. عرّفها كمتغير عام عادي قبل تحميل الحزمة المشوَّشة — فبيئة تشغيل VM ودفاعاتها تعمل قبل برنامجك (المحمي)، لذا تُطلَق كثير من عمليات الكشف أثناء بدء التشغيل:

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

الإشارة المعرَّفة داخل المصدر المشوَّش تُسجَّل متأخرة جدًا بحيث لا تلتقط عمليات الكشف وقت بدء التشغيل، وإذا رُمِّزت بـ VM فلا يمكن الوصول إليها حتى يعمل برنامجك. وهي آمنة على أي حال (إشارة غائبة تنفّذ لا شيء، وحارس منع إعادة الدخول يمنع أي انفلات)، لكن للتغطية الكاملة سجّلها مقدَّمًا. ولحماية منطق إبلاغك رغم ذلك، أبقِ الإشارة المسجَّلة عازلًا من سطر واحد ((window.__vmDet = window.__vmDet || []).push(signal)) واقرأ/أرسِل ذلك العازل من كودك المشوَّش.

إعادة تسمية حقول الإشارة (aliases). القيم الافتراضية لـ source/category أسماء وصفية، فيستطيع أي شخص يُجهِّز رد النداء (أو يقرأ الناتج) أن يتعرّف على الحماية وعلى الكاشف الذي أُطلِق. aliases يعيد تسمية حقول الإشارة إلى رموز مبهمة من اختيارك، تُطبَّق داخل VM قبل إصدار الإشارة، بحيث لا تظهر تلك الأسماء أبدًا في الناتج ولا تصل إلى رد النداء. ويعرف تطبيقك التعيين الخاص به ويمرّر الرموز إلى خادمك الخلفي.

الأسماء البديلة لكل حقل، مع إبقاء إعادة تسمية المفاتيح والقيم منفصلة: يأخذ كل حقل key (اسم الخاصية الذي يتلقاه رد النداء)؛ كما يأخذ الحقلان النصيان source وcategory خريطة values، بينما score/threshold رقمان ويأخذان key فقط. الأسماء التي يمكنك تعيينها (وأي شيء آخر يُرفَض وقت البناء):

  • مفاتيح الحقولsource، category، score، threshold
  • قيم sourceheadless، agent، node، debugger، timing، sandbox، domain، nativeHook، integrity
  • قيم 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> }
}

هذا تجنّبٌ للبصمة، لا سرّية — إذ لا يزال بالإمكان استنتاج التعيين بالاختبار المتكرر — فمنفعته الوحيدة هي عدم كشف أسماء ثابتة تفسّر نفسها. والمدخلات غير المضبوطة تبقى بأسمائها الافتراضية.

يُقبَل نص مجرد (vmDefenseHook: '__vmDetection') كاختصار لـ { name: '__vmDetection' } لكنه مهجور — فضّل صيغة الكائن.

vmDefenseReaction

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

يضبط كيفية تفاعل كل فئة كشف. وهو لا يفعّل أي شيء — فالدفاعات نفسها تُشغَّل بواسطة vmSelfDefending وvmDebugProtection وvmDomainLock؛ ولا يختار هذا الخيار سوى كيفية تفاعل دفاع مفعَّل. الفئة هي وحدة التحكم — فكل كاشف في فئة يُنفِّذ تفاعل تلك الفئة.

تجمع كل فئة الكواشف التي تراقب نوعًا واحدًا من الحالات العدائية. ولا تتفاعل الفئة إلا عندما يكون الخيار الذي يُصدِر كواشفها مفعَّلًا:

الفئةيفعّلهاتتفاعل عند
automationvmSelfDefending أو vmDebugProtectionتشغيل الكود ببرمجية بدلًا من شخص: متصفح مقطوع الرأس أو مؤتمت، أو إطار كشط / اختبار، أو وكيل برمجة بالذكاء الاصطناعي يخطو في الصفحة.
debuggervmDebugProtection أو vmSelfDefendingفتح أحدهم منقّحًا أو مفتِّش أدوات المطور في المتصفح وخطوه في الكود العامل لفهمه.
sandboxvmDebugProtectionألّا يعمل الكود في متصفح حقيقي إطلاقًا — إذ نُقِل إلى بيئة JavaScript مُحاكاة أو مُبرمَجة لتنفيذه ودراسته دون اتصال.
domainvmDomainLockتشغيل الكود على موقع لم تصرّح به: مُضيف ليس في قائمة السماح vmDomainLock (مثلًا حزمتك منسوخة على نطاق شخص آخر).
tampervmSelfDefendingتعديل بيئة JavaScript المحيطة بـ VM لمراقبتها أو اختطافها، مثل استبدال أدوات المتصفح المدمجة الأصلية بنسخ مُجهَّزة.
integrityvmSelfDefendingتحرير أو ترقيع كود الحزمة المحمية نفسه منذ توليدك إياه.

تُطابَق كل فئة واحدًا أو أكثر من vmSelfDefending وvmDebugProtection وvmDomainLock؛ ولا توجد فئة خارج تلك الخيارات الثلاثة، وتفاعل مضبوط لفئة خيارها معطَّل ببساطة بلا أثر.

المفاتيح هي أسماء الفئات الست هذه، أو default (احتياطي للفئات غير المحددة). والقيم هي:

  • break — يتوقف فورًا
  • decoy — يستمر في العمل على حالة مسمومة، منتجًا نتائج خاطئة بصمت
  • none — لا يفعل شيئًا محليًا (قياس عن بُعد فقط)

الافتراضيات لكل فئة مبيَّنة أعلاه؛ والفئة التي لا تضبطها (أو تضبطها على قيمتها الافتراضية) تستخدم ذلك الافتراضي. default يصل إلى كل فئة، بما في ذلك الفئات الصحيحة بحكم البناء (integrity وtamper)، لذا فإن { default: 'none' } عملية بناء غير كاسرة حقًا، للقياس عن بُعد فقط:

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

يجعل معاني أكواد العمليات تعتمد على الموضع في البايت كود. لكل موضع تعيين مختلف من كود العملية إلى المعالِج مشتق من بذرة، بحيث يؤدي رقم كود العملية نفسه عمليات مختلفة في مواضع مختلفة.

vmCallContextOpcodes

Type: boolean Default: false

يجعل الدالة المحمية تعتمد على المكان الذي تُستدعى منه، بحيث لا يمكن انتزاعها من الكود وتشغيلها أو تحليلها بمفردها — فهي لا تتصرف بشكل صحيح إلا عند استدعائها عبر مواضع استدعائها الحقيقية في البرنامج. يؤثّر هذا الخيار في أداء التشغيل.

يُدعَم حاليًا فقط التركيبات التالية:

  • تصريحات الدوال (function f() {}
  • تعبيرات الدوال والدوال السهمية المُسنَدة إلى متغير (const f = () => {}
  • التوابع الخاصة للنسخ (this.#m()).

في كل حالة، يجب أن يُوصَل إلى الدالة دائمًا عبر استدعاء مباشر (f()، this.#m()). فإذا خُزِّنت في متغير آخر، أو مُرِّرت كوسيط، أو استُخدمت بأي طريقة أخرى كقيمة، فتُترَك دون حماية. الدوال غير المتزامنة مدعومة؛ أما المولِّدات فلا.

هذا الخيار تجريبي وقد يعطّل عمل كودك، فاختبر الناتج جيدًا قبل استخدامه.

vmStackEncoding

Type: boolean Default: false

يشفّر القيم على مكدس VM أثناء التنفيذ. تُرمَّز القيم عند دفعها وتُفكّ ترميزها عند سحبها، بحيث يُظهر فحص الذاكرة بيانات مشفَّرة بدلًا من القيم الفعلية.

يؤثّر هذا الخيار في الأداء تأثيرًا كبيرًا.

vmCompactDispatcher

Type: boolean Default: false

يستخدم منفِّذ VM واحدًا بدلًا من منفِّذين مزدوجين (متزامن + مولِّد). يقلّل حجم الكود المشوَّش لكنه يضيف حِملًا على الأداء بنحو 20% في الكود كثير التعاود.

  • false (افتراضي): منفِّذان مزدوجان — أداء مثالي، ناتج أكبر
  • true: منفِّذ واحد — ناتج أصغر، أبطأ قليلًا

vmStringArrayBytecodeOnly

Type: boolean Default: false

عند التفعيل، ستستخرج مصفوفة النصوص النصوص من بيانات البايت كود فقط — ولا تُحوَّل أي نصوص أخرى في الكود. وهذا يفعّل stringArray قسرًا حتى لو لم يُضبَط صراحةً.

لماذا تستخدمه: استخراج كل نصوص بيئة تشغيل VM إلى مصفوفة نصوص بطيء. يستهدف هذا الخيار محتوى البايت كود فقط لاستخراج مصفوفة النصوص، مما يحسّن الأداء مع الاستمرار في حماية ثوابت البايت كود.

  • عند vmBytecodeArrayEncoding: false — تُستخرَج النصوص داخل مجمّعات ثوابت البايت كود (مصفوفات c)
  • عند vmBytecodeArrayEncoding: true — تُستخرَج نصوص البايت كود المُرمَّزة بـ base64 على المستوى الأعلى
  • لا يزال stringArrayThreshold يتحكم في نسبة نصوص البايت كود تلك التي تُستخرَج

vmDomainLock

Type: string[] Default: []

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يقصر الكود المشوَّش على نطاقات و/أو نطاقات فرعية بعينها، وهو أصعب بكثير في تحديد موضعه وإزالته من domainLock.

إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بهذا الخيار، فسيُعاد توجيه المتصفح إلى عنوان URL المُمرَّر إلى vmDomainLockRedirectUrl، وستُعيد الاستدعاءات المحمية اللاحقة نتائج غير صحيحة حتى لو كُبِت إعادة التوجيه.

نطاقات ونطاقات فرعية متعددة

يمكن قفل كودك على أكثر من نطاق أو نطاق فرعي. فمثلًا، لقفله بحيث لا يعمل الكود إلا على www.example.com أضف www.example.com. ولجعله يعمل على النطاق الجذري بما في ذلك أي نطاقات فرعية (example.com وsub.example.com)، استخدم .example.com.

vmDomainLockRedirectUrl

Type: string Default: about:blank

⚠️ لا يعمل هذا الخيار مع target: 'node' أو target: 'service-worker' أو target: 'bytenode'

يتيح إعادة توجيه المتصفح إلى عنوان URL مُمرَّر إذا لم يُشغَّل الكود المصدري على النطاقات المحددة بواسطة vmDomainLock.

Preset Options

تشويش عالٍ، أداء منخفض

سيكون الأداء أبطأ بكثير مما هو عليه دون تشويش

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

تشويش متوسط، أداء مثالي

سيكون الأداء أبطأ مما هو عليه دون تشويش

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

تشويش منخفض، أداء عالٍ

سيكون الأداء عند مستوى طبيعي نسبيًا

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

الإعداد المسبق الافتراضي، أداء عالٍ

{
    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 فائق العلو (أقصى أمان)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع كل ميزات التصليب بما في ذلك الإرسال غير المباشر. يوفّر أقوى حماية لكن بحجم ناتج أكبر وتنفيذ أبطأ بكثير.

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

أو اضبط الخيارات بشكل فردي:

{
    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 المضاد لنماذج LLM (حماية من وكلاء الذكاء الاصطناعي)

صُمِّم هذا الإعداد المسبق خصيصًا لمنع وكلاء الذكاء الاصطناعي ونماذج LLM من إجراء هندسة عكسية على الكود المُرمَّز ببايت كود VM. يستند إلى vm-default مع تفعيل الدفاع الذاتي وحماية التنقيح. أخف من vm-high-obfuscation لكنه مصلَّب خصيصًا ضد التحليل الآلي.

{
    optionsPreset: 'vm-anti-llm'
}

يشمل:

  • تشويش بايت كود VM مع مصفوفة النصوص (من vm-default)
  • vmSelfDefending — كشف الاعتراض، وتجزئة السلامة، وبصمة المصدر، والتحقق عبر عالَم iframe نظيف، واشتقاق مفتاح شيفرة ARX
  • vmDebugProtection — فحوصات مضادة للتنقيح في حلقة إرسال VM
  • debugProtection: false — لا حماية تنقيح قديمة (حماية تنقيح VM أفضل)

تشويش VM العالي (أعلى أمان)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع معظم ميزات التصليب. يوفّر حماية قوية بأداء أفضل من الإعداد المسبق فائق العلو.

{
    optionsPreset: 'vm-high-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 المتوسط (أمان متوازن)

يفعّل هذا الإعداد المسبق تشويش البايت كود القائم على VM مع مجموعة متوازنة من ميزات التصليب. حل وسط جيد بين الأمان والأداء.

{
    optionsPreset: 'vm-medium-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 المنخفض (أمان أساسي، أداء أفضل)

يفعّل هذا الإعداد المسبق تشويش بايت كود VM الأساسي دون ميزات تصليب إضافية. توازن جيد بين الأمان وحجم الناتج.

{
    optionsPreset: 'vm-low-obfuscation'
}

أو اضبط الخيارات بشكل فردي:

{
    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 الافتراضي (VM + حماية مصفوفة النصوص)

يجمع هذا الإعداد المسبق بين تشويش البايت كود الأساسي القائم على VM وحماية مصفوفة النصوص. نقطة بداية جيدة لتشويش VM مع حماية النصوص.

{
    optionsPreset: 'vm-default'
}

أو اضبط الخيارات بشكل فردي:

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