Telemetría y reacciones de defensa de la VM
Informa a tu backend de las detecciones de las defensas de la VM con vmDefenseHook, y ajusta cómo reacciona cada categoría de detección con vmDefenseReaction - desde una compilación totalmente no disruptiva, de solo telemetría, hasta una que rompe de inmediato ante un bundle robado.
Ver
Obfuscator.io Defense Reactions: Break, Decoy, and the VM Defense Hook
El problema
Las defensas de la VM - vmSelfDefending, vmDebugProtection y vmDomainLock - actúan localmente: cuando se detecta un depurador, una herramienta de automatización, un entorno manipulado o un dominio no autorizado, el código protegido se rompe o envenena silenciosamente sus propios resultados. Eso detiene al atacante, pero de forma predeterminada tú nunca te enteras. No puedes saber con qué frecuencia se está sondeando tu bundle, qué detector se activó ni si una defensa está afectando a un usuario legítimo.
Dos opciones cierran esa brecha. Ninguna de ellas activa ninguna defensa - solo observan y dirigen las defensas que ya has activado:
vmDefenseHook- un callback global que recibe un objeto de señal cada vez que una defensa detecta algo. Úsalo para enviar telemetría a tu backend.vmDefenseReaction- un mapa por categoría que selecciona cómo reacciona una defensa activada: romper, decoy o no hacer nada localmente.
Ambas opciones se introdujeron en v7.1.0, pero todos los ejemplos de esta página usan la forma de objeto vmDefenseHook: { name }, que requiere
v7.4.0. Las versiones anteriores aceptaban una cadena simple (vmDefenseHook: '__vmDetection'); esa forma se rechaza a partir de v8.0.0, así que
usa la forma de objeto en todo momento.
Receta 1 - informa de las detecciones a tu backend
Paso 1 - registra una función de hook global, antes de que se cargue el bundle ofuscado
El runtime de la VM y sus defensas se ejecutan antes que tu programa protegido, por lo que muchas detecciones se producen durante el arranque. Define el hook como un global simple en la página anfitriona, antes de la etiqueta del script ofuscado:
Paso 2 - apunta vmDefenseHook hacia ella
La opción es un objeto cuyo name es la función global que se llamará (aliases es opcional - consulta más abajo):
En el panel, el campo VM Defense Hook aparece en la sección Protección avanzada una vez que al menos una defensa (vmSelfDefending, vmDebugProtection o vmDomainLock) está activada.
Paso 3 - recibe la señal en tu backend
Cada detección llama al hook con un único objeto signal:
source- el detector específico:headless,node,agent,agentBrowser,domain,debugger,sandbox,nativeHook,timingointegrity. A partir de v7.4.0, los antiguos detectoresenveinspectorinforman bajosource: 'debugger'.agentBrowserinforma bajocategory: 'automation'y se ejecuta en targets de navegador convmDebugProtection(v7.9.0+).category-automation,debugger,sandbox,domain,tamperointegrity. La fuentenodeinforma bajocategory: 'debugger'(v7.4.0+).score,threshold- la puntuación de la detección y el umbral que superó
Un endpoint de recepción mínimo (se muestra Express; funciona cualquier backend que acepte un POST). Normaliza el cuerpo a un array para que también gestione la forma por lotes que envía el patrón de búfer más abajo:
El hook es solo para informar - su valor de retorno se ignora, y un hook ausente o que lanza una excepción es una operación nula silenciosa. Nunca puede desactivar una defensa, así que un atacante que elimine o rompa tu hook no gana nada. Para cambiar lo que hace una defensa, usa vmDefenseReaction (Receta 2).
Define el hook en la página anfitriona, no dentro del código fuente ofuscado
Para la telemetría te interesa capturar cada detección, y muchas se producen en el arranque - un hook definido dentro del bundle ofuscado se registra demasiado tarde para captarlas, y si se compila en la VM no es accesible hasta que tu programa se ejecuta. Sigue siendo seguro en cualquier caso (un hook ausente no hace nada, y un hook que a su vez provoca una detección no se vuelve a llamar de forma recursiva), pero para una cobertura completa regístralo de antemano en la página anfitriona.
La única excepción es un hook que reacciona solo a una detección en tiempo de ejecución - como una limpieza cuando se abre un depurador durante el uso. Ese hook puede vivir dentro del bundle ofuscado; consulta la Receta 3.
Para proteger de todos modos tu lógica de reporte, mantén el hook registrado como un búfer de una línea y vacíalo desde tu código ofuscado:
Renombrar los campos de la señal (aliases)
Los valores predeterminados de source / category son nombres descriptivos, por lo que cualquiera que instrumente el callback (o lea la salida) puede reconocer la protección y qué detector se activó. aliases renombra los campos de la señal a tokens opacos que tú eliges, aplicados dentro de la VM antes de que se emita la señal, de modo que esos nombres nunca aparecen en la salida ni llegan al callback. Tu aplicación conoce su propio mapeo y reenvía los tokens a tu backend.
Los alias son por campo: cada uno toma una key (el nombre de la propiedad que recibe el callback); los campos de nombre de cadena source y category también toman un mapa values, mientras que score / threshold son números y toman solo una key. Las entradas sin definir conservan sus nombres predeterminados.
En el panel, la sección Alias de señales se encuentra debajo del campo VM Defense Hook.
Esto es evitación de huella identificable, no secreto - el mapeo aún puede inferirse mediante pruebas repetidas, por lo que su único beneficio es no exponer nombres estables y autoexplicativos.
Receta 2 - ajusta las reacciones predeterminadas
vmDefenseReaction configura cómo reacciona cada categoría de detección. No activa nada - las defensas en sí se activan mediante vmSelfDefending, vmDebugProtection y vmDomainLock; esta opción solo selecciona cómo reacciona una defensa activada. La categoría es la unidad de control: cada detector de una categoría ejecuta la reacción de esa categoría, y una reacción establecida para una categoría cuya opción está desactivada simplemente no tiene efecto.
| Categoría | Activada por | Reacciona cuando |
|---|---|---|
automation | vmSelfDefending o vmDebugProtection | El código está siendo controlado por software en lugar de por una persona: un navegador headless o automatizado, un framework de scraping / testing, o un agente de IA de programación recorriendo la página. |
debugger | vmDebugProtection o vmSelfDefending | Alguien tiene abierto un depurador o el inspector de herramientas de desarrollo del navegador y está recorriendo el código en ejecución para entenderlo. |
sandbox | vmDebugProtection | El código no se está ejecutando en un navegador real en absoluto - se ha trasladado a un entorno de JavaScript emulado o controlado por scripts para ejecutarlo y estudiarlo sin conexión. |
domain | vmDomainLock | El código se está ejecutando en un sitio que no autorizaste: un host que no está en tu lista de permitidos de vmDomainLock (por ejemplo, tu bundle copiado en el dominio de otra persona). |
tamper | vmSelfDefending | El entorno de JavaScript que rodea a la VM se ha modificado para vigilarla o secuestrarla, como funciones nativas integradas del navegador reemplazadas por versiones instrumentadas. |
integrity | vmSelfDefending | El propio código del bundle protegido se ha editado o parcheado desde que lo generaste. |
Las claves son estos seis nombres de categoría, o default (un valor de reserva para las categorías no especificadas). Los valores son:
break- romper de inmediatodecoy- seguir ejecutándose con un estado envenenado, produciendo silenciosamente resultados incorrectos.decoynecesitavmDebugProtectionovmDomainLocken un target de navegador; de lo contrario, actúa comobreak.none- no hacer nada localmente (solo telemetría)
Una categoría que no establezcas recurre a los valores predeterminados integrados:
default alcanza a todas las categorías, incluidas integrity y tamper, por lo que { default: 'none' } es una compilación genuinamente no disruptiva, de solo telemetría:
En el panel, los selectores de VM Defense Reactions aparecen en la sección Protección avanzada una vez que una defensa está activada; cada categoría solo es editable mientras esté activada una defensa que emita sus detectores.
Receta 3 - ejecuta tu propia lógica antes de que una defensa rompa
El hook no es solo para informar - también es el único lugar fiable para ejecutar tu propia respuesta antes de que una defensa reaccione. Cuando se abre un depurador en una página en ejecución, quizá quieras borrar lo que hay en pantalla, o reemplazar la vista por una página 404, antes de que el código se rompa.
Por qué el hook en lugar de código en otra parte de tu aplicación: break detiene todo el bytecode posterior, por lo que un desmontaje que se ejecute después de que se active una defensa - especialmente cuando está a su vez ofuscado en la VM - es exactamente lo que el break impide ejecutar. El hook se dispara en el sitio de la detección antes de que se aplique la reacción, de forma síncrona - por lo que una función síncrona que llame termina primero, y luego break detiene la VM.
Define la respuesta como tu vmDefenseHook. Como la detección debugger se dispara en tiempo de ejecución - después de que tu programa se haya cargado y haya definido el hook - el hook puede formar parte de tu código fuente ofuscado y se compila en bytecode junto con el resto del bundle. Bifurca según signal.category para que cada condición reciba la respuesta correcta, mantén el trabajo síncrono y luego deja que la reacción se ejecute:
Esto se aplica a las detecciones que se producen mientras tu aplicación se está ejecutando - consulta Cuándo funciona compilar el hook a bytecode más abajo.
Ten en cuenta estos puntos:
- Solo el trabajo síncrono tiene garantizado terminar primero. La reacción se ejecuta en la sentencia justo después de que el hook retorne. Las llamadas de disparar y olvidar que ceden el control de inmediato están bien (
navigator.sendBeacon, ediciones síncronas del DOM y del canvas); el trabajo que programes para más tarde - unsetTimeout, una continuación de promesa, unawait- no lo está, y cualquier cosa que necesite más bytecode de la VM no se ejecutará, porque eso es lo quebreakdetiene. - El hook se ejecuta antes de la reacción; no la reemplaza. Su valor de retorno se ignora, y no puede cancelar, retrasar ni cambiar lo que hace la reacción. Úsalo para actuar antes del break, no para vetarlo - para cambiar la reacción en sí, usa
vmDefenseReaction(Receta 2).
Cuándo funciona compilar el hook a bytecode
Colocar el hook dentro del bundle ofuscado de esta forma funciona solo porque la detección debugger se dispara en tiempo de ejecución. La VM dispara vmDefenseHook mientras sigue viva, después de que tu programa se haya cargado y haya definido el hook, por lo que el hook compilado en bytecode se decodifica y se ejecuta primero, y luego break. Esto es lo que protege el propio código fuente del hook.
No funciona para las detecciones que se producen en el arranque - automation, sandbox, domain, o un depurador ya abierto cuando se carga la página - porque en ese momento el hook compilado en bytecode aún no está definido, así que la defensa no encuentra ninguna función a la que llamar. Para esas, registra el hook como un global simple en la página anfitriona, como en la Receta 1. En caso de duda, un global simple en la página anfitriona cubre cada detección que llega al hook; la compilación en bytecode solo añade protección para el propio código fuente del hook, y solo para las detecciones en tiempo de ejecución.
De la telemetría a la imposición
La visibilidad y la imposición no tienen que lanzarse juntas. Despliega las defensas en dos etapas: primero una compilación que solo informa, y luego - una vez que la telemetría se vea limpia - una que reacciona.
Paso 1 - publica una compilación de solo observación
Activa todas las defensas que pienses usar, apunta vmDefenseHook a tu endpoint y desactiva todas las reacciones. Cada detector se sigue ejecutando e informa de cada acierto a tu backend, pero nada se rompe:
Paso 2 - revisa las señales recopiladas
Después de que la compilación haya visto tráfico real, busca detecciones que haya desencadenado el uso legítimo. Las dos más comunes:
- Aciertos de
automationprovenientes de tus propias pruebas de extremo a extremo o de la monitorización de disponibilidad - compila esos artefactos sin las defensas en lugar de tolerar la categoría en producción. - Aciertos de
domainprovenientes de un host de staging o de vista previa que olvidaste incluir en la lista de permitidos devmDomainLock- añade el host.
Prefiere corregir la causa antes que suavizar una reacción: cada categoría que se deja en none es un detector que un atacante puede ignorar sin problemas.
Paso 3 - activa las reacciones
Elimina la anulación default: 'none' para que se apliquen las reacciones integradas por categoría; esa única línea es todo el cambio. Si una categoría sigue produciendo falsos positivos que no puedes eliminar, deja solo esa categoría en none (p. ej., vmDefenseReaction: { automation: 'none' }) e impón el resto.
Mantén vmDefenseHook configurado después de que la imposición esté activa - el hook se dispara independientemente de la reacción, por lo que conservas visibilidad sobre quién está sondeando tu bundle mientras las defensas actúan.
