التوثيق
/
وصفات عملية
/

قياسات دفاع VM وردود أفعاله

قياسات دفاع VM وردود أفعاله

Pro
v7.1.0+

أبلغ خادمك الخلفي باكتشافات دفاع VM باستخدام vmDefenseHook، واضبط كيفية استجابة كل فئة اكتشاف عبر vmDefenseReaction - من بناء لا يكسر شيئًا ويقتصر على القياسات، إلى بناء يتعطل بحزم عند حزمة مسروقة.

المشكلة

تعمل دفاعات VM - vmSelfDefending وvmDebugProtection وvmDomainLock - محليًا: فعند كشف مُنقِّح أو أداة أتمتة أو بيئة معبوث بها أو نطاق غير مصرَّح، يتعطل الكود المحمي أو يفسد نتائجه بصمت. وهذا يوقف المهاجم، لكنك افتراضيًا لا تسمع بذلك أبدًا. فلا يمكنك معرفة عدد مرات فحص حزمتك، ولا أي كاشف أُطلق، ولا ما إذا كان دفاعٌ ما يعطّل مستخدمًا شرعيًا.

منذ الإصدار 7.1.0، يسد خياران هذه الفجوة. ولا يفعّل أيٌّ منهما أي دفاع - إنما يراقبان الدفاعات التي فعّلتها سلفًا ويوجّهانها فحسب:

  • vmDefenseHook - دالة رد نداء عامة تستقبل كائن إشارة في كل مرة يكشف فيها دفاعٌ شيئًا. استخدمها لإرسال القياسات إلى خادمك الخلفي.
  • vmDefenseReaction - خريطة لكل فئة تحدد كيف يستجيب دفاع مفعَّل: يتعطل، أو يفسد نتائجه، أو لا يفعل شيئًا محليًا.

الوصفة 1 - أبلغ خادمك الخلفي بالاكتشافات

الخطوة 1 - سجّل دالة hook عامة قبل تحميل الحزمة المشوَّشة

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

<script>
    // In your page, BEFORE the obfuscated script:
    window.__vmDetection = function (signal) {
        navigator.sendBeacon('/api/vm-defense', JSON.stringify(signal));
    };
</script>
<script src="/app.obfuscated.js"></script>

الخطوة 2 - وجّه vmDefenseHook إليها

الخيار كائن يكون فيه name هو الدالة العامة المراد استدعاؤها (وaliases اختياري - انظر أدناه):

JavaScriptObfuscator.obfuscate(source, {
    vmObfuscation: true,
    // the hook alone enables nothing - a defense must be on for detectors to run:
    vmSelfDefending: true,
    vmDebugProtection: true,
    vmDefenseHook: { name: '__vmDetection' }
});

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

في لوحة التحكم، يظهر حقل VM Defense Hook في لوحة خيارات VM بمجرد تفعيل دفاع واحد على الأقل (vmSelfDefending أو vmDebugProtection أو vmDomainLock).

الخطوة 3 - استقبل الإشارة على خادمك الخلفي

يستدعي كل اكتشاف الـ hook بكائن signal واحد:

  • source - الكاشف المحدد: headless أو node أو agent أو domain أو debugger أو sandbox أو nativeHook أو timing أو integrity. واعتبارًا من الإصدار 7.4.0، يبلّغ الكاشفان السابقان env وinspector تحت source: 'debugger'.
  • category - automation أو debugger أو sandbox أو domain أو tamper أو integrity. ويبلّغ المصدر node تحت category: 'debugger' (الإصدار 7.4.0 فما فوق).
  • score وthreshold - درجة الاكتشاف والعتبة التي تجاوزها

نقطة نهاية استقبال أدنى (يظهر Express؛ ويصلح أي خادم خلفي يقبل POST). وهي تطبّع الجسم إلى مصفوفة لتتعامل أيضًا مع الصيغة المجمّعة التي يرسلها نمط المخزن المؤقت أدناه:

app.post('/api/vm-defense', express.text({ type: '*/*' }), (req, res) => {
    // a signal: { source: 'headless', category: 'automation', score: 7, threshold: 4 }
    const signals = [].concat(JSON.parse(req.body));
    for (const signal of signals) {
        console.warn('vm-defense', { ...signal, ip: req.ip, ua: req.get('user-agent') });
    }
    res.sendStatus(204);
});

إعادة تسمية حقول الإشارة (الأسماء البديلة) v7.4.0+

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

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

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

في لوحة التحكم، يقع قسم Signal aliases أسفل حقل VM Defense Hook.

الوصفة 2 - عدّل ردود الأفعال الافتراضية

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

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

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

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

أما الفئة التي لا تضبطها فترجع إلى القيم الافتراضية المدمجة:

// built-in defaults
vmDefenseReaction: {
    automation: 'break',
    debugger: 'decoy',
    sandbox: 'decoy',
    domain: 'break',
    tamper: 'break',
    integrity: 'break'
}

يصل default إلى كل فئة، بما فيها الفئتان الصحيحتان بحكم التصميم (integrity وtamper)، ولذلك فإن { default: 'none' } هو حقًا بناء لا يكسر شيئًا ويقتصر على القياسات:

vmDefenseReaction: { default: 'none' } // never break - pair with vmDefenseHook
vmDefenseReaction: { automation: 'none' } // tolerate automation FPs; the rest keep their defaults (a bad domain still breaks)

في لوحة التحكم، تظهر قوائم VM Defense Reactions في لوحة خيارات VM بمجرد تفعيل دفاع؛ وتكون كل فئة قابلة للتحرير فقط ما دام دفاعٌ يصدر كواشفها مفعَّلًا.

من القياسات إلى الإنفاذ

لست مضطرًا للاختيار بين الرؤية والإنفاذ من اليوم الأول. أطلق الدفاعات على بناءين: بناء يبلّغ فقط، ثم - حين تبدو القياسات نظيفة - بناء يستجيب.

الخطوة 1 - أطلق بناء مراقبة فقط

فعّل كل دفاع تنوي استخدامه، ووجّه vmDefenseHook إلى نقطة نهايتك، وأطفئ كل ردود الأفعال. عندئذ يظل كل كاشف يعمل ويبلّغ خادمك الخلفي بكل ضربة - لكنه لا يكسر شيئًا أبدًا:

JavaScriptObfuscator.obfuscate(source, {
    vmObfuscation: true,
    vmSelfDefending: true,
    vmDebugProtection: true,
    vmDomainLock: ['example.com'],
    vmDefenseHook: '__vmDetection',
    vmDefenseReaction: { default: 'none' } // observe only
});

الخطوة 2 - راجع الإشارات المجموعة

بعد أن يشهد البناء حركة مرور حقيقية، ابحث عن الاكتشافات التي أطلقها استخدام شرعي. وأكثرها شيوعًا اثنان:

  • ضربات automation من اختباراتك الشاملة أو مراقبة الجاهزية لديك - ابنِ تلك المخرجات دون الدفاعات بدلًا من التسامح مع الفئة في الإنتاج.
  • ضربات domain من مضيف تجهيز أو معاينة نسيت تضمينه في قائمة السماح في vmDomainLock - أضِف المضيف.

فضّل معالجة السبب على تليين رد الفعل: فكل فئة تُترَك عند none هي كاشف لم يعد على المهاجم القلق منه.

الخطوة 3 - شغّل ردود الأفعال

أزِل تجاوز default: 'none' لتُطبَّق ردود الأفعال المدمجة لكل فئة - والتبديل كله هو ذلك السطر الواحد. وإذا ظلت فئة تنتج نتائج إيجابية كاذبة لا يمكنك التخلص منها، فأبقِ تلك الفئة وحدها عند none (مثل vmDefenseReaction: { automation: 'none' }) وأنفِذ البقية.