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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
recaptcha — Documentación e ingeniería inversa de reCAPTCHA | Kitploit
Herramientas/GitHubGitHub/elyelysiox/recaptcha
Análisis EstáticoAnálisis Dinámico de Código (DAST)Ingeniería InversaSeguridad WebAnti-BotBypass de CAPTCHA
GitHubelyelysiox/recaptcha

recaptcha

Documentación e ingeniería inversa de reCAPTCHA

Ver Repositorio
2273858hace 3 mesesRevisado por Kitploit

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

Description

Este repositorio contiene un análisis técnico del antibot de Google (reCAPTCHA) centrado en:

  • Estructura y valores del payload
  • Técnicas de fingerprinting
  • Técnicas de ofuscación
  • Técnicas anti-depuración/manipulación
  • Máquinas virtuales

Contacto

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

Técnicas de ofuscación

reCAPTCHA es uno de los sistemas antibot con las técnicas de ofuscación más sofisticadas, ya que emplea una serie de transformaciones que hacen que el código sea menos legible y más difícil de aplicar ingeniería inversa. La mayoría de las ofuscaciones pueden manipularse fácilmente utilizando el Árbol de Sintaxis Abstracta (AST), pero algunas se procesan en tiempo de ejecución, lo que hace que el AST sea inútil en ese caso. También se aplica polimorfismo al código para cambiar su estructura en cada versión del script. Por ejemplo, el código no realiza la acción directamente. En su lugar, utiliza objetos o funciones que cambian de forma

  • Expresiones de secuencia El código se aplana convirtiendo cada sentencia de bloque en una expresión continua separada por comas; puede aparecer en sentencias if, argumentos de funciones e incluso dentro de objetos seq

  • Aritmética mixta booleana Entrelaza operaciones aritméticas (suma, resta, multiplicación) con operaciones bit a bit (AND, OR, XOR, NOT) para ocultar la lógica original, por ejemplo -2 * ~(h & H) + -2 + (h ^ H)

  • Tabla indirecta de funciones Cada función se construye dentro de una tabla y se llama mediante su índice, como functions[index](https://github.com/elyelysiox/recaptcha/blob/main/args)

  • Array constante en línea Se asigna un literal de array local en línea, en mitad de una expresión; el array agrupa constantes (números, cadenas) que se reutilizan en todo el cuerpo de la función mediante acceso por índice

    // b = [14, 1, "call"] assigned inline inside a sequence expression
    function(Y, Q, c, l, G, X, W, J, b, P) {
        (Y & 94) == Y && (b = [14, 1, "call"], ...)
        W[b[2]](J, G)   // W.call(J, G)
        Y >> b[1] & b[0]  // Y >> 1 & 14
    }
    
  • Multiplexación de funciones Múltiples funciones lógicamente distintas se fusionan en una sola, utilizando un parámetro numérico como selector de bloque. El bloque activo se determina evaluando el parámetro con condiciones bit a bit. Los llamadores pasan un literal numérico como selector

    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // block 1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // convert value to string logic
        }
    
        // block 2
        if ((N + 4 & 40) >= N && (N + 5 & C[0]) < N) {
            Y = bB();
            throw Error(Y === void 0 ? "unexpected value " + U + y : Y);
        }
    
        return u;
    }
    
  • Ramificación con operadores lógicos Reemplaza las sentencias if y los bloques if/else con la evaluación de cortocircuito de operadores lógicos, convirtiendo el flujo de control en expresiones. Combinado con expresiones de secuencia, múltiples ramas aparecen como una única expresión continua separada por comas

    // if (a) { block }
    a && (block)
    
    // if (!a) { block }
    a || (block)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // combined with CFF and sequence expressions:
    (Y | 1) & 14 || (c = Q.O, J = c.O.length + c.g.length),
    (Y ^ 59) >> 3 == 3 && (Q.classList
        ? Q.classList.add(c)
        : Z[31](31, Q, c) || (l = f[0](84, "string", "", Q), ...)),
    
  • Constantes de métodos nativos vinculados Vincula métodos nativos del navegador a sus receptores originales, almacenándolos como constantes para evitar su manipulación

    LO = (Tw = self) == null ? void 0 :
     (K9 = Tw.Math) == null ? void 0 :
     (v4 = K9.floor) == null ? void 0 :
     (mF = v4.bind) == null ? void 0 :
     mF.call(v4, Math)  // Math.floor.bind(Math)
    
    LO(x)           // Math.floor(x)
    U4()            // Math.random()
    Ge(obj, prop)   // Object.defineProperty(obj, prop)
    
  • Código muerto Se inyectan bloques de código inaccesibles o sin uso a lo largo del archivo, aumentando su tamaño a más de 60 000 líneas; esto dificulta el análisis estático y la ingeniería inversa basada en LLM

  • Aplanamiento del flujo de control Transforma cada parte del código (declaraciones y bucles) en una máquina de estados plana. Oculta la lógica de ejecución original enrutando todos los bloques de código a través de un bloque central «dispatcher»

    Los dispatchers pueden cambiar de forma; algunos tienen 2 o 3 variables de estado y el tipo de bucle/condición cambia. Tienen este aspecto

    cff1

    Este es un CFF con 2 variables de estado: una gestiona el bloque catch y la otra el bloque try.

  • Grupo de cadenas cifradas Todos los literales de cadena (APIs DOM, propiedades del navegador, valores CSS, mensajes de error, etc.) se cifran en un único grupo de cadenas masivo. Una función de descifrado utiliza una semilla y un cifrado XOR basado en LCG para extraer cada cadena en tiempo de ejecución

    Hay más de 1990 puntos de llamada repartidos por el código; la función de descifrado utiliza una clave continua que acumula los puntos de código descifrados, haciendo que cada carácter dependa de todos los anteriores

    X = function(J, b, P, F, U) {
        U = ["codePointAt", 127, "char encrypted pool"];
        for (F = (P = 0, b = "", l); P < Q; P++)
            J = (U[2][U[0]](c + P) ^ F) & U[1],  // XOR with running key
            b += String.fromCodePoint(J),
            F += J; // accumulate key
        return G = b;
    }
    
    // call sites pass a seed to locate and decrypt each string
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • Iterador de valores con estado reCAPTCHA utiliza una función con estado que devuelve una secuencia de objetos y valores de tiempo de ejecución (como window, document.body, constantes numéricas) en un orden fijo; cada llamada avanza un cursor interno, y llamarla fuera de secuencia o demasiadas veces corrompe todas las lecturas posteriores. Un mecanismo de tiempo de espera invalida el estado tras un intervalo fijo, devolviendo null para cualquier lectura tardía

    // sequential calls return different values:
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (timeout expired)
    
    l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12)
    // ↑ window                     ↑ window
    
    10 * l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12))
    
    c().querySelectorAll(a[X[2]](98, X[1], X[1]))
    // ↑ document.body  
    
    
  • Tabla de funciones calculadas Esto es similar a Indirect Function Table, pero aquí el índice de la función a obtener se calcula en tiempo de ejecución con una semilla, usando XOR y módulo

    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mN is the function table (50+ functions)
    
    q[29](5, 6977)   // seed=6977  → index resolves to function at mN[X]
    q[29](53, 6187)  // seed=6187  → different index, different function
    

    computed

Descargar herramienta