Documentação
/
Receitas
/

Telemetria e reações das defesas da VM

Telemetria e reações das defesas da VM

Pro
v7.1.0+

Reporte as detecções das defesas da VM ao seu backend com vmDefenseHook e ajuste como cada categoria de detecção reage com vmDefenseReaction - de um build totalmente não destrutivo, apenas de telemetria, a quebrar de forma severa em um bundle roubado.

O problema

As defesas da VM - vmSelfDefending, vmDebugProtection e vmDomainLock - agem localmente: quando um depurador, ferramenta de automação, ambiente adulterado ou domínio não autorizado é detectado, o código protegido quebra ou silenciosamente envenena seus próprios resultados. Isso detém o atacante, mas, por padrão, você nunca fica sabendo. Você não tem como saber com que frequência seu bundle está sendo sondado, qual detector disparou ou se uma defesa está quebrando para um usuário legítimo.

Desde a v7.1.0, duas opções fecham essa lacuna. Nenhuma delas ativa qualquer defesa - elas apenas observam e orientam as defesas que você já ativou:

  • vmDefenseHook - um callback global que recebe um objeto de sinal toda vez que uma defesa detecta algo. Use-o para enviar telemetria ao seu backend.
  • vmDefenseReaction - um mapa por categoria que seleciona como uma defesa ativada reage: quebrar, envenenar ou não fazer nada localmente.

Receita 1 - reportar detecções ao seu backend

Passo 1 - registre uma função de hook global, antes que o bundle ofuscado carregue

O runtime da VM e suas defesas rodam antes do seu programa protegido, então muitas detecções disparam durante a inicialização. Defina o hook como um global simples na página host, antes da tag de script ofuscada:

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

Passo 2 - aponte vmDefenseHook para ela

A opção é um objeto cujo name é a função global a ser chamada (aliases é opcional - veja abaixo):

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' }
});

A forma de string simples (vmDefenseHook: '__vmDetection') ainda é aceita como abreviação de { name: '__vmDetection' }, mas está obsoleta - prefira a forma de objeto.

No painel, o campo VM Defense Hook aparece no painel de opções da VM assim que pelo menos uma defesa (vmSelfDefending, vmDebugProtection ou vmDomainLock) está ativada.

Passo 3 - receba o sinal no seu backend

Toda detecção chama o hook com um único objeto signal:

  • source - o detector específico: headless, node, agent, domain, debugger, sandbox, nativeHook, timing ou integrity. A partir da v7.4.0, os antigos detectores env e inspector reportam sob source: 'debugger'.
  • category - automation, debugger, sandbox, domain, tamper ou integrity. A origem node reporta sob category: 'debugger' (v7.4.0+).
  • score, threshold - a pontuação da detecção e o limiar que ela cruzou

Um endpoint de recebimento mínimo (mostrado com Express; qualquer backend que aceite um POST funciona). Ele normaliza o corpo para um array, então também lida com a forma em lote enviada pelo padrão de buffer abaixo:

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

Renomeando os campos do sinal (aliases) v7.4.0+

Os valores padrão de source / category são nomes descritivos, então qualquer pessoa que instrumente o callback (ou leia a saída) pode reconhecer a proteção e qual detector disparou. aliases renomeia os campos do sinal para tokens opacos de sua escolha, aplicados dentro da VM antes de o sinal ser emitido, de modo que esses nomes nunca aparecem na saída nem chegam ao callback. Seu app conhece o próprio mapeamento e encaminha os tokens ao seu backend.

Os aliases são por campo: cada um recebe uma key (o nome da propriedade que o callback recebe); os campos de nome do tipo string source e category também recebem um mapa values, enquanto score / threshold são números e recebem apenas uma key. Entradas não definidas mantêm seus nomes padrão.

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

No painel, a seção Aliases de sinal fica abaixo do campo VM Defense Hook.

Receita 2 - ajustar as reações padrão

vmDefenseReaction configura como cada categoria de detecção reage. Ela não ativa nada - as próprias defesas são ligadas por vmSelfDefending, vmDebugProtection e vmDomainLock; esta opção apenas seleciona como uma defesa ativada reage. A categoria é a unidade de controle: todo detector de uma categoria aplica a reação daquela categoria, e uma reação definida para uma categoria cuja opção está desligada simplesmente não tem efeito.

CategoriaAtivada porReage quando
automationvmSelfDefending ou vmDebugProtectionO código está sendo controlado por software em vez de uma pessoa: um navegador headless ou automatizado, um framework de scraping / testes ou um agente de código de IA percorrendo a página.
debuggervmDebugProtection ou vmSelfDefendingAlguém tem um depurador ou o inspetor de ferramentas de desenvolvedor do navegador aberto e está percorrendo o código em execução para entendê-lo.
sandboxvmDebugProtectionO código não está rodando em um navegador real - ele foi transportado para um ambiente JavaScript emulado ou controlado por script para ser executado e estudado offline.
domainvmDomainLockO código está rodando em um site que você não autorizou: um host que não está na sua lista de permissões vmDomainLock (por exemplo, seu bundle copiado para o domínio de outra pessoa).
tampervmSelfDefendingO ambiente JavaScript ao redor da VM foi modificado para observá-la ou sequestrá-la, como funções nativas do navegador substituídas por versões instrumentadas.
integrityvmSelfDefendingO próprio código do bundle protegido foi editado ou modificado desde que você o gerou.

As chaves são esses seis nomes de categoria, ou default (um fallback para categorias não especificadas). Os valores são:

  • break - quebra imediatamente
  • decoy - continua rodando em estado envenenado, produzindo silenciosamente resultados errados
  • none - não faz nada localmente (apenas telemetria)

Uma categoria que você não define recai sobre os padrões internos:

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

default alcança todas as categorias, incluindo as corretas por construção (integrity, tamper), então { default: 'none' } é um build genuinamente não destrutivo, apenas de telemetria:

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

No painel, os seletores VM Defense Reactions aparecem no painel de opções da VM assim que uma defesa é ativada; cada categoria só é editável enquanto uma defesa que emite seus detectores estiver ligada.

Da telemetria à aplicação

Você não precisa escolher entre visibilidade e aplicação logo no primeiro dia. Implante as defesas em dois builds: um que apenas reporta e, depois - quando a telemetria estiver limpa -, um que reage.

Passo 1 - publique um build somente de observação

Ative todas as defesas que você pretende usar, aponte vmDefenseHook para o seu endpoint e desligue todas as reações. Cada detector ainda roda e reporta cada ocorrência ao seu backend - ele apenas nunca quebra nada:

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

Passo 2 - revise os sinais coletados

Depois que o build receber tráfego real, procure detecções que o uso legítimo disparou. As duas mais comuns:

  • ocorrências de automation vindas dos seus próprios testes end-to-end ou do monitoramento de disponibilidade - construa esses artefatos sem as defesas em vez de tolerar a categoria em produção.
  • ocorrências de domain vindas de um host de staging ou preview que você esqueceu de incluir na lista de permissões vmDomainLock - adicione o host.

Prefira corrigir a causa a suavizar uma reação: cada categoria deixada em none é um detector com o qual um atacante não precisa mais se preocupar.

Passo 3 - ative as reações

Remova a substituição default: 'none' para que as reações internas por categoria sejam aplicadas - toda a mudança é essa única linha. Se uma categoria continuar produzindo falsos positivos que você não consegue eliminar, mantenha apenas essa categoria em none (por exemplo, vmDefenseReaction: { automation: 'none' }) e aplique o restante.