Документация
/
Рецепты
/

Телеметрия и реакции защиты VM

Телеметрия и реакции защиты VM

Pro
v7.1.0+

Сообщайте на свой бэкенд о срабатываниях защиты VM через vmDefenseHook и настраивайте реакцию на каждую категорию срабатываний через vmDefenseReaction — от полностью неразрушающей сборки, отправляющей только телеметрию, до жёсткого слома на украденном бандле.

Проблема

Средства защиты VM — vmSelfDefending, vmDebugProtection и vmDomainLock — действуют локально: при обнаружении отладчика, инструмента автоматизации, изменённой среды или неавторизованного домена защищённый код ломается или незаметно отравляет собственные результаты. Это останавливает злоумышленника, но по умолчанию вы об этом никогда не узнаёте. Вы не можете сказать, как часто ваш бандл прощупывают, какой детектор сработал и не ломает ли защита легитимного пользователя.

С версии v7.1.0 этот пробел закрывают две опции. Ни одна из них не включает никакую защиту — они лишь наблюдают за уже включёнными вами средствами защиты и управляют ими:

  • vmDefenseHook — глобальный коллбэк, получающий объект-сигнал каждый раз, когда защита что-то обнаруживает. Используйте его для отправки телеметрии на бэкенд.
  • vmDefenseReaction — карта по категориям, задающая, как реагирует включённая защита: сломаться, отравить или ничего не делать локально.

Рецепт 1 — сообщать о срабатываниях на бэкенд

Шаг 1 — зарегистрируйте глобальную функцию-хук до загрузки обфусцированного бандла

Среда выполнения VM и её защиты работают до вашей защищённой программы, поэтому многие срабатывания происходят во время старта. Определите хук как обычную глобальную функцию на странице-хосте, перед тегом обфусцированного скрипта:

<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 — примите сигнал на бэкенде

Каждое срабатывание вызывает хук с единственным объектом signal:

  • source — конкретный детектор: headless, node, agent, domain, debugger, sandbox, nativeHook, timing или integrity. Начиная с v7.4.0 прежние детекторы env и inspector сообщают под source: 'debugger'.
  • categoryautomation, debugger, sandbox, domain, tamper или integrity. Источник node сообщает под category: 'debugger' (v7.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);
});

Переименование полей сигнала (aliases) v7.4.0+

Значения source / category по умолчанию — описательные имена, поэтому любой, кто инструментирует коллбэк (или читает результат), может распознать защиту и то, какой детектор сработал. aliases переименовывает поля сигнала в непрозрачные токены на ваш выбор, применяемые внутри VM до того, как сигнал будет выпущен, так что эти имена никогда не появляются в результате и не попадают в коллбэк. Ваше приложение знает собственное сопоставление и пересылает токены на бэкенд.

Псевдонимы задаются на каждое поле: каждое принимает 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Кодом управляет программа, а не человек: headless- или автоматизированный браузер, фреймворк для скрейпинга / тестирования или ИИ-агент, шагающий по странице.
debuggervmDebugProtection или vmSelfDefendingУ кого-то открыт отладчик или инспектор инструментов разработчика браузера, и он пошагово изучает выполняющийся код.
sandboxvmDebugProtectionКод вообще не выполняется в настоящем браузере — его перенесли в эмулируемую или скриптовую среду JavaScript, чтобы выполнить и изучить офлайн.
domainvmDomainLockКод выполняется на сайте, который вы не авторизовали: хост не из вашего белого списка vmDomainLock (например, ваш бандл скопирован на чужой домен).
tampervmSelfDefendingСреда JavaScript вокруг VM изменена, чтобы наблюдать за ней или перехватывать её, например встроенные объекты браузера подменены на инструментированные версии.
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 от ваших же end-to-end тестов или мониторинга доступности — собирайте эти артефакты без защит вместо того, чтобы терпеть эту категорию в продакшене.
  • срабатывания domain от staging- или preview-хоста, который вы забыли включить в белый список vmDomainLock, — добавьте хост.

Предпочитайте устранение причины смягчению реакции: каждая категория, оставленная на none, — это детектор, о котором злоумышленнику больше не нужно беспокоиться.

Шаг 3 — включите реакции

Уберите переопределение default: 'none', чтобы применились встроенные реакции по категориям, — весь переключатель в этой одной строке. Если какая-то категория продолжает давать ложные срабатывания, которые вы не можете устранить, оставьте только эту категорию на none (например, vmDefenseReaction: { automation: 'none' }) и принуждайте остальные.