Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
px-vm — Kit de ingeniería inversa para la máquina virtual de bytecode de PerimeterX, que incluye un desensamblador basado en CFG, un pipeline de descifrado de 5 capas, reconstrucción de tabla de códigos de operación y un limpiador de emulación de pila para la investigación de seguridad sobre la huella digital de detección de bots. | Kitploit
Herramientas/GitHubGitHub/b9ph0met/px-vm
Análisis Dinámico (Sandboxing)Evasión de IDS/IPSIngeniería InversaSeguridad WebAnálisis de MalwareCriptografíaAnálisis de BinariosPapers e InvestigaciónAprendizaje y EducaciónAnti-BotSuplantación de Huella Digital
551426hace 5 mesesRevisado por Kitploit
GitHub
b9ph0met/px-vm

px-vm

Ver Repositorio

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →

Acerca de

Kit de ingeniería inversa para la máquina virtual de bytecode de PerimeterX, que incluye un desensamblador basado en CFG, un pipeline de descifrado de 5 capas, reconstrucción de tabla de códigos de operación y un limpiador de emulación de pila para la investigación de seguridad sobre la huella digital de detección de bots.

Compartir

Análisis de la VM de Auditor de PerimeterX

Resumen

Este repositorio documenta la ingeniería inversa de auditor.js de PerimeterX, una máquina virtual de bytecode utilizada como capa secundaria de huellas digitales en el pipeline de detección de bots de PX. Este análisis cubre:

  • Extracción de bytecode y pipeline de descifrado de 5 capas
  • Reconstrucción de tabla de opcodes (107 base + 40 honey + 24 padding + 16 grupos de superinstrucciones)
  • Descifrado del pool de constantes (1230 entradas, 1095 cadenas cifradas)
  • Desensamblador basado en CFG con resolución de sub-despacho de superinstrucciones
  • Limpiador de emulación de pila que produce pseudocódigo legible
  • Técnicas anti-análisis: opcodes honey, instrucciones superpuestas, hash de integridad de código

Nota: Este repositorio cubre solo una versión (estática) de la VM y está destinado a fines de investigación y análisis de seguridad. No incluye solucionadores dinámicos ni implementaciones de solucionadores de producción.

Antecedentes

El jueves 2 de abril de 2026, PerimeterX implementó una nueva VM de bytecode como parte de su pipeline de detección de bots.

Qué hay dentro

auditor.js no parece un script de sensor PX normal. En lugar de las habituales búsquedas de propiedades ofuscadas y funciones de recolección:

  • 8 cadenas base64 masivas (_fg0 a _fg7), el programa VM cifrado dividido en variables
  • Una función de descifrado XOR (_dp) con una clave por sitio (_pk) que desempaqueta el JSON del programa
  • Un barajado Fisher-Yates que permuta la tabla de opcodes para que los valores de bytecode difieran por compilación
  • Un bucle de despacho con más de 107 manejadores de casos, el intérprete de la VM
  • Aritmética BigInt para el cifrado RSA de la salida de huellas digitales
  • Un hash de integridad de código (_0x8df7) que hashea la propia fuente de la VM para derivar una clave de descifrado, de modo que cualquier modificación rompe silenciosamente el descifrado del bytecode

Paso 1: Extracción de bytecode

El programa VM está dividido en 8 variables, concatenado y luego descifrado mediante _dp() usando un cifrado XOR por sitio con clave _pk:

var _pk = 893686289;
function _dp(_b) {
    var _r = atob(_b), _o = new Array(_r.length);
    for (var _i = 0; _i < _r.length; _i++) {
        _o[_i] = String.fromCharCode(
            _r.charCodeAt(_i) ^ (((_pk >>> (8 * (_i % 4))) ^ Math.imul(_i + 1, 0x6B8B4567)) & 0xFF)
        );
    }
    return _o.join("");
}

El resultado es un objeto JSON con nombres de clave de dos caracteres ofuscados (por ejemplo, "uo" para seed, "dk" para nonce). Una tabla de mapeo los convierte a nombres estándar.

node extractor.js
# -> program.json

Estructura del programa

CampoDescripción
sSemilla (12755), impulsa todas las operaciones criptográficas
nNonce (1603730985), aleatorización por programa
gIndicador de generador, habilita la capa de descifrado de hash de integridad
xIndicador cifrado, las constantes están cifradas con XOR
cPool de constantes, 1230 entradas
fFunciones, 112 entradas con bytecode cifrado
ePunto de entrada, índice de función 0

Paso 2: Descifrado de constantes

Todas las 1095 constantes de cadena están cifradas con dos capas:

Capa 1: XOR murmur estático con clave 4008000571, dependiente de la posición.

Capa 2: XOR de flujo PRNG usando un LCG glibc, sembrado combinando la semilla del programa con el índice de cada constante mediante el hash multiplicativo de Knuth.

Antes del descifrado, la semilla se XOR con una huella digital del entorno (_0xaf48), una máscara de bits de 8 bits calculada probando APIs del navegador:

BitPruebaChrome
0typeof window.matchMedia === "function"1
1document.elementFromPoint existe1
2typeof window.requestAnimationFrame === "function"1
3typeof window.getComputedStyle === "function"1
4CSS.supports existe1
5navigator.sendBeacon existe1
6document.execCommand existe1
7process.versions.node existe (Node.js)0

Para Chrome: _0xaf48 = 0b01111111 = 127, lo que da una semilla efectiva = 12755 ^ 127 = 12716.

Esto significa que el mismo programa produce diferentes resultados de descifrado en diferentes entornos. Ejecutarlo en Node.js vs Chrome vs Firefox produce diferentes semillas.

node decrypt_constants.js
# -> program_decrypted.json, constants_table.txt

Lo que revelan las constantes

Las cadenas descifradas nos dicen exactamente qué huellas digitales recoge la VM:

Huellas digitales del navegador: screenWidth, screenHeight, innerWidth, innerHeight, devicePixelRatio, colorDepth, platform, userAgent, language, timezone, timezoneOffset, forcedColors, highContrast

Temporización de rendimiento: navigationStart, domComplete, domLoading, fetchStart, requestStart, responseEnd, secureConnectionStart, serverTiming

Criptografía RSA: BigInt, modPow, AQAB (65537 en base64), modulusLength, shiftLeft, shiftRight, getRandomValues

Sondeo DOM/SVG: http://www.w3.org/2000/svg, createElementNS, getBoundingClientRect, getTotalLength, getBBox

Nombres de campos PX: mtr, tst, mst, enc, sbx, fstec, pdc, prb, wvi, wva, pti, dis, los, cv, sc, jd, ads, enve, init

Referencias de endpoints: https://fst-ec.perimeterx.net/?id=

Anti-depurador: _CMP_RCX_07;_JNZ_0x0A_EB_CC, CC|CD-04|BREAKPOINT-005

Paso 3: Tabla de opcodes

107 opcodes base que cubren todo el lenguaje JavaScript, más ruido generado dinámicamente:

40 opcodes honey son implementaciones alternativas de operaciones aritméticas/de comparación usando expresiones matemáticamente equivalentes pero sintácticamente diferentes. ADD puede aparecer como (a^b) + 2*(a&b) o -((-a)-b) o a-(-b). Cada opcode base puede tener hasta 3 variantes, generadas deterministicamente a partir de la semilla. Una simple instrucción ADD puede aparecer como 4 valores diferentes de bytecode dentro del mismo programa, rompiendo enfoques de coincidencia de patrones.

24 opcodes de relleno se asignan en la permutación pero no tienen manejadores y nunca se emiten. Existen para expandir el espacio de opcodes y hacer que el barajado sea más difícil de invertir.

16 grupos de superinstrucciones son la característica anti-análisis más importante. Cuando el bucle de despacho resuelve un opcode a un líder de superinstrucción, el manejador lee un byte adicional del flujo de bytecode y despacha a un sub-manejador. El sub-manejador puede ser una operación completamente diferente:

El líder se resuelve comoSub-byteRealmente ejecuta
FOR_IN_NEXT74FOR_IN_NEXT
FOR_IN_NEXT100MAKE_CLOSURE
ASSIGN_OP_VAR165ASSIGN_OP_VAR
ASSIGN_OP_VAR37JMP
GET_VAR_PROP_C143SET_VAR_POP
GET_VAR_PROP_C23JMP_NULLISH

La tabla de opcodes se baraja mediante Fisher-Yates con semilla efectiva, por lo que los valores de bytecode difieren por compilación.

node build_opcodes.js
# -> opcode_table.json, opcode_table.txt

Paso 4: Constructor de CFG

El núcleo del kit de herramientas. cfg.js construye un grafo de flujo de control siguiendo todas las rutas de ejecución desde PC=0, decodificando cada instrucción con el contexto de cifrado correcto.

Por qué no un desensamblador lineal

Descargar herramienta