Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
recaptcha — Документация и обратная разработка reCAPTCHA | Kitploit
Инструменты/GitHubGitHub/elyelysiox/recaptcha
Статический анализДинамический анализ кода (DAST)Обратная инженерияВеб-безопасностьАнти-БотОбход CAPTCHA
GitHubelyelysiox/recaptcha

recaptcha

Документация и обратная разработка reCAPTCHA

Репозиторий
2273852 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Описание

Этот репозиторий содержит технический анализ антибота Google (reCAPTCHA), сфокусированный на:

  • Структуре и значениях полезной нагрузки (Payload)
  • Техниках снятия отпечатков (Fingerprinting)
  • Техниках обфускации (Obfuscation)
  • Техниках анти-отладки/анти-модификации (Anti-debugging/Tampering)
  • Виртуальных машинах (Virtual Machines)

Контакты

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

Техники обфускации

reCAPTCHA — одна из антибот-систем с наиболее изощрёнными техниками обфускации, применяющая ряд преобразований, которые делают код менее читаемым и усложняют обратную разработку. Большинство обфускаций легко обрабатываются с помощью абстрактного синтаксического дерева (AST), но некоторые выполняются во время выполнения, делая AST в этом случае бесполезным. К коду также применяется полиморфизм, изменяющий его структуру в каждой версии скрипта. Например, код не выполняет действие напрямую. Вместо этого используются объекты или функции, меняющие форму.

  • Последовательные выражения (Sequence Expressions) Код уплощается путём преобразования каждого блока инструкций в непрерывное выражение, разделённое запятыми; может встречаться в операторах if, аргументах функций и даже внутри объектов. seq

  • Смешанная булева арифметика (Mixed Boolean Arithmetic) Переплетает арифметические операции (сложение, вычитание, умножение) с побитовыми (AND, OR, XOR, NOT), чтобы скрыть исходную логику, например -2 * ~(h & H) + -2 + (h ^ H).

  • Косвенная таблица функций (Indirect Function Table) Каждая функция помещается в таблицу и вызывается по индексу, например functions[index](https://github.com/elyelysiox/recaptcha/blob/main/args).

  • Встроенный постоянный массив (Inline Constant Array) Литерал локального массива присваивается прямо внутри выражения; массив группирует константы (числа, строки), которые многократно используются в теле функции через доступ по индексу.

    root@kitploit:~
    // b = [14, 1, "call"] присвоено внутри последовательного выражения
    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
    }
    
  • Мультиплексирование функций (Function Multiplexing) Несколько логически различных функций объединяются в одну, используя числовой параметр как селектор блока. Активный блок определяется путём проверки параметра на побитовые условия. Вызывающие передают числовой литерал в качестве селектора.

    root@kitploit:~
    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // блок 1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // логика преобразования значения в строку
        }
    
        // блок 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;
    }
    
  • Ветвление через логические операторы (Logical Operator Branching) Заменяет блоки if и if/else на короткое замыкание логических операторов, превращая поток управления в выражения. В сочетании с последовательными выражениями множество ветвей выглядят как одно непрерывное выражение, разделённое запятыми.

    root@kitploit:~
    // if (a) { block }
    a && (block)
    
    // if (!a) { block }
    a || (block)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // в сочетании с CFF и последовательными выражениями:
    (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), ...)),
    
  • Привязка нативных методов как констант (Bind Native Methods Constants) Привязывает нативные методы браузера к их исходным получателям, сохраняя их как константы для предотвращения модификации.

    root@kitploit:~
    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)
    
  • Мёртвый код (Dead Code) Недоступные или неиспользуемые блоки кода вставляются по всему файлу, увеличивая его размер до более чем 60 000 строк; это затрудняет статический анализ и обратную разработку с помощью LLM.

  • Уплощение потока управления (Control Flow Flattening) Преобразует каждую часть кода (объявления и циклы) в плоский конечный автомат. Скрывает исходную логику выполнения, направляя все блоки кода через центральный блок-диспетчер.

    Диспетчеры могут менять форму; некоторые имеют 2-3 переменных состояния, а тип цикла/условия меняется. Выглядят они так:

    cff1

    Это CFF с двумя переменными состояния: одна управляет блоком catch, другая — блоком try.

  • Зашифрованный пул строк (Encrypted String Pool) Все строковые литералы (DOM API, свойства браузера, CSS-значения, сообщения об ошибках и т.д.) зашифрованы в одном огромном пуле строк. Функция дешифрования использует seed и XOR-шифр на основе LCG для извлечения каждой строки во время выполнения.

    По всему коду разбросано более 1990 мест вызова; функция дешифрования использует нарастающий ключ, накапливающий декодированные кодовые точки, что делает каждый символ зависимым от всех предыдущих.

    root@kitploit:~
    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 с нарастающим ключом
            b += String.fromCodePoint(J),
            F += J; // накопление ключа
        return G = b;
    }
    
    // места вызова передают seed для поиска и дешифровки каждой строки
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • Итератор значений с состоянием (Stateful Value Iterator) reCAPTCHA использует функцию с состоянием, которая возвращает последовательность объектов и значений среды выполнения (например, window, document.body, числовые константы) в фиксированном порядке; каждый вызов сдвигает внутренний курсор; вызов не по порядку или слишком много раз портит все последующие чтения. Механизм тайм-аута аннулирует состояние через заданный интервал, возвращая null для любых поздних чтений.

    root@kitploit:~
    // последовательные вызовы возвращают разные значения:
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (тайм-аут истёк)
    
    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  
    
  • Вычисляемая таблица функций (Computed Function Table) Похоже на Indirect Function Table, но здесь индекс получаемой функции вычисляется во время выполнения на основе seed с использованием XOR и Modulus.

    root@kitploit:~
    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mN — таблица функций (50+ функций)
    
    root@kitploit:~
    q[29](5, 6977)   // seed=6977  → индекс разрешается в функцию mN[X]
    q[29](53, 6187)  // seed=6187  → другой индекс, другая функция
    

    computed

  • Шифрование значений во время выполнения (Runtime Value Encryption) Некоторые значения (параметры конфигурации капчи, параметры якоря и т.д.) никогда не хранятся в открытом виде; они шифруются сразу после сбора и расшифровываются только в момент использования; имеют префикс B в начале.

    hiddenv

  • Обфускация асинхронного потока управления (Async Control Flow Obfuscation) Синхронная логика преобразуется в конечный автомат на основе генераторов, обёрнутый в рекурсивные цепочки Promise; отслеживание любого значения через отладчик вынуждает проходить через несколько асинхронных обработчиков, теряя исходный контекст выполнения на каждой границе .then().

  • Полезная нагрузка и ответ якоря (Anchor Payload/Response)

    Структура полезной нагрузки

    Компоненты для инициализации reCAPTCHA``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

    root@kitploit:~
    ### Response
    
    Ответ содержит:
    - Дизайн iframe-окна CAPTCHA
    - Якорный токен, используемый для проверки полезной нагрузки (/reload)
    - Основную конфигурацию для инициализации, выполняемую в методе `recaptcha.anchor.Main.init` для её получения в recaptcha_en.js
    
    ### Структура:
    
    Примечание: Recaptcha BotGuard был удалён `04/01/2026`. Вы можете увидеть некоторые примеры [здесь](https://github.com/elyelysiox/recaptcha-payload/tree/main/botguard_scripts)```javascript
    [
        "ainput",
        [
            "bgdata",
            "",
            "LyogQW50aS1zcGFtLiBXYW50IHRvIHNheSBoZWxsbz8gQ29ud...", // BotGuard Script Base64-Encoded
            "YWVtZ0h5MGNCWXJDQ2lidGh0RW13RmhWdlc3aU5yeVpzSmx6U...", // BotGuard VM Bytecode Double Base64-Encoded 
            "wrB8fsOVU8K0YAzDsyQpw7ZHw6jDnMK1AMO6SRcvw53CsGlQw6/DuMO0wqr" // VM Config Bytecode Base64-Encoded
        ],
        null,
        [
            "conf",
            null,
            "6LfTV4gkAAAAACDVrUvp9_DalxUPvFSU7M2HJDO-", // Website Key
            0,
            null,
            null,
            null,
            1,
            // Indexes for fingerprinting or something else
            [16, 21, 125, 63, 73, 95, 87, 41, 43, 42, 83, 102, 105, 109, 121],
            [-7614991, 137],
            0,
            null,
            null,
            null,
            null,
            0,
            null,
            0,
            null,
            700, // Time Start for Time Variances of Fingerprint Values
            1,
            null,
            0,
            // Encoded metadata for the VM's main bytecode constructs
            "CvsCEg8I8ajhFRgAOgZUOU5CNWISDwjmjuIVGAA6BlFCb29IYxIPCMfm1DgYADoGZHhkTmlkEg8Is4qgOBgBOgZMV0o1a2ISDwiB7OgVGAA6Bkh1dlBqZhIPCK6e6zcYADoGR2JpT1FkEg8I94jmNxgAOgZvaWxlRGQSDwjwzeMVGAE6BmZJVkloYhIPCOLKoDcYAToGZ0xOQ0hjEg8I3r+3NxgBOgZlYXp1NmQSDwjY0oEyGAA6BkFxNzd2ZhIOCLjllDIYAToFUUJPRDASDwio7784GAA6BkdGVU5jZhIPCLWzqzgYAToGb3JZVjZkEg8I0tuVNxgAOgZmZmFXQWUSDwiV2JQyGAE6BlBxNjBuZBIPCKuRyjgYADoGQVo0TmJiEg8IxfOINxgAOgZhWG9pYWMSDwiNyoYyGAE6Bk93TjR0ZhIOCIr9iDcYADoFTWZJSTQaJwgDEiMdJv3NgTUZp4oJGYQKGZzijAIZzPMRGa+VQBnqsCYZ5a8MGQ==",
            0,
            1,
            null,
            null,
            1,
            null,
            null,
            0,
            null,
            null,
            0,
            0,
            "cf5e3c3a6ab6c494c829a7932d9577c1e6de862dd4912e55dc7fe2e40a1f7604"
        ],
        "https://who.clickbait.team:443", // Website URL:Port
        null,
        [
            3,
            1,
            1
        ],
        null,
        null,
        null,
        1,
        3600,
        [
            "https://www.google.com/intl/es/policies/privacy/",
            "https://www.google.com/intl/es/policies/terms/"
        ],
        "vQWNjTpMwdevQPWmE8akDzp8jsOZfa1VqTzVHaPiQ/c=",
        1,
        0,
        null,
        1,
        1777669303203, // Fingerprint Data Encryption Key
        0,
        0,
        [203], // Config Bytecode Key
        null,
        [185], // Config Bytecode Key
        "RC--rg1OSRnOD0ayA",
        null,
        null,
        null,
        null,
        null,
        // Bft Token, Used in reCAPTCHA V2
        "0dAFcWeA4RepD9zDjeMQE73pAT27pXZ7Nz_419U2K36QNqzHaKtLIDkwZQLi-Ud8OvSZHbDEcxQxusBQnsF5QQErMRpJMcUplaFg",
        1777752103288 // "oc" Data Encryption Key
    ]
    

    Отпечаток

    Значения основаны на расшифрованных значениях из первого образца отпечатка, смотрите здесь

    Каждое подполе значений отпечатка имеет базовый формат:

    [value, key, elapsed]

    Где key — ключ шифрования, а elapsed — время, которое потребовалось сборщику для получения и шифрования значения. Это позволяет reCAPTCHA обнаруживать:

    • Чрезмерно быстрое выполнение
    • Хуки
    • Точки останова и изоляцию (песочница)

    Порядок выполнения сборщика

    Система использует внутренний планировщик:``` [42, 45, 53, 30, 28, 54, 29, 31, 32, 33, 34, 35, 37, 36, 38, 39, 43, 40, 41, 46, 48, 57, 58, 60, 61, 62, 63, 64, 66, 68, 69, 71, 72, 79, 55]

    root@kitploit:~
    Это представляет:
    
    - Порядок выполнения
    - Конвейер сборщика
    - Последовательность генерации сигналов
    
    ### Коды сигналов отпечатков и вывод ключей
    Преобразует сигналы отпечатков в детерминированные ключи шифрования через многоступенчатый конвейер вывода
    
    Каждое значение отпечатка:
    
    - Нормализуется
    - Кодируется в компактный код сигнала
    - Преобразуется в числовой ключ шифрования
    - Шифруется с использованием полученного ключа
    
    Процесс является детерминированным, то есть одно и то же входное значение всегда генерирует одинаковый код сигнала и ключ шифрования```
    Raw Value
       ↓
    Signal Code Derivation
       ↓
    Compact Signal Code
       ↓
    Numeric Key Derivation
       ↓
    Encryption Key
       ↓
    Value Encryption
    

    Пример

    Входной сигнал``` "BUTTON,195a81c9"

    root@kitploit:~
    ***Шаг 1 - Получение кода сигнала***```javascript
    deriveSignalCode("BUTTON,195a81c9")
    // → "wg"
    

    Сгенерированный сигнальный код представляет собой компактный детерминированный идентификатор исходного значения.

    Шаг 2 - Получение числового ключа```javascript deriveKey("wg") // → 3792

    root@kitploit:~
    Сигнальный код преобразуется в числовой ключ шифрования.
    
    ***Шаг 3 — Зашифровать значение***```javascript
    encryptValueWithKey(3792, "wgia1z9pwq")
    // → "bYVbh6BUsE_5pLA"
    

    Следующее значение будет зашифровано с помощью производного ключа, следуя порядку сбора.

    Структура агрегированного отпечатка

    Все сгенерированные коды сигналов агрегируются в компактную сериализованную структуру

    Процесс``` value -> "BUTTON,195a81c9" seed code -> wg key -> 3792 value -> "wgia1z9pwq" seed code -> 21 key -> 1599 value -> 1 seed code -> p1 key -> 3521 value -> "8cc68d83" seed code -> ld key -> 3448 value -> "https://nextcaptcha.com/demo..." seed code -> 9p key -> 1879 value -> 4 seed code -> op key -> 3553 value -> false seed code -> 1r key -> 1633 value -> 7 seed code -> qf key -> 3605 value -> "jYAQSHAEAI" seed code -> 1z key -> 1641 value -> "" seed code -> 80 key -> 1784 value -> 2 seed code -> jk key -> 3393 value -> "AAAAAAAAAA" seed code -> 1z key -> 1641 value -> "h3" seed code -> 9p key -> 1879 value -> "0,BUTTON,195a81c9" seed code -> ia key -> 3352 value -> -1 seed code -> 1u key -> 1636 value -> 0 seed code -> wq key -> 3802 value -> "74,fbfbc5b3" seed code -> 6z key -> 1796 value -> 0 seed code -> wq key -> 3802 value -> 0 seed code -> wq key -> 3802 value -> 2 seed code -> jk key -> 3393 value -> 0 seed code -> wq key -> 3802 value -> "-1,-1" seed code -> 1m key -> 1628 value -> "static.cloudflareinsights.co,..." seed code -> 1g key -> 1622 value -> "" seed code -> 80 key -> 1784 value -> "https://nextcaptcha.com,https...." seed code -> pd key -> 3572 value -> "[4,"CABIBQAggA","BAgAAgAAgA"]" seed code -> 1n key -> 1629 value -> "Demostración empresarial de reCAPTCHA v3..." seed code -> 1k key -> 1626 value -> "[2,76852,77850,77351]" seed code -> 9b key -> 1865 value -> "sha384-TNm" seed code -> 23 key -> 1601 value -> "[1680,1050,876,1166,844,876]" seed code -> 13 key -> 1570 value -> "[300,null,1778502450481]" seed code -> ex key -> 3251 value -> "[null,null,"",""]" seed code -> rx key -> 3654 value -> "[2147483648,70806416,65303240]" seed code -> 2r key -> 1664 value -> "GA1.1.354395113.1778502448" seed code -> 1g key -> 1622 value -> false seed code -> 1r key -> 1633 value -> "[[[1,"wg"],..." seed code -> 85 key -> 1789

    root@kitploit:~
    **Финал**```json
    [
      [
        [1, "wg"], [1, "21"], [1, "p1"],
        [1, "ld"], [1, "9p"], [1, "op"],
        [1, "1r"], [1, "qf"], [1, "1z"],
        [1, "80"], [1, "jk"], [1, "1z"],
        [1, "9p"], [1, "ia"], [1, "1u"],
        [1, "wq"], [1, "6z"], [1, "wq"],
        [1, "wq"], [1, "jk"], [1, "wq"],
        [1, "1m"], [1, "1g"], [1, "80"],
        [1, "pd"], [1, "1n"], [1, "1k"],
        [1, "9b"], [1, "23"], [1, "13"],
        [1, "ex"], [1, "rx"], [1, "2r"],
        [1, "1g"], [1, "1r"]
      ],
      "54"
    ]
    

    Сигналы

    • Idx 4 (string)

      • Значение: 3ccb

      • Хэшировано: true

      • Описание: Генерирует HMAC-ключ из window.localStorage.getItem("rc::a") + "6d", преобразованного в байты, вычисляет HMAC-SHA256(siteKey) с этим ключом и возвращает первые 4 шестнадцатеричных символа результата.

        Значение rc::a — это случайно сгенерированная строка в base64.

    • Idx 5 (integer)

      • Значение: window.localStorage.length * 2
      • Хэшировано: false
      • Описание: Длина window.localStorage умноженная на 2
    • Idx 16 (string)

      • Значение: yM5Us/j/fn6EDgtmPlP4Pxj605nMJN9dRYHyy5Mn

      • Хэшировано: true

      • Описание: 40-символьный отпечаток Bloom-фильтра в base64 для всех узлов <HEAD>. Обходит каждый дочерний элемент, собирая имена тегов, атрибуты и текстовое содержимое, которые сериализуются и пропускаются через хэш djb2.

        Каждый дайджест подаётся в BitHash(240 бит, 7 раундов, макс. 25 узлов), который устанавливает биты в сетке 40×6, а затем кодирует каждый 6-битный сегмент как символ base64. Собственные скрипты reCAPTCHA исключаются с помощью динамического регулярного выражения по src.

    • Idx 17 (integer)

      • Значение: 2
      • Хэшировано: false
      • Описание: Проверка возможности чтения/записи сторонних куки, Пример)
    • Idx 18 (string)

      • Значение: a2hyNTFuNDI4NnA3
      • Хэшировано: false
      • Описание: Случайно сгенерированное значение, закодированное в Base64
    • Idx 27 (string)

      • Значение: location.origin
      • Хэшировано: false
      • Описание: URL веб-сайта.
    • Idx 28 (boolean)

      • Значение: false
      • Хэшировано: false
      • Описание: window.parent != window ? true : window.frameElement != null ? true : false
    • Idx 29 (string)

      • Значение: e2a3cd70
      • Хэшировано: true
      • Описание: Хэш тела функции grecaptcha.execute с помощью SHA-256, Пример
    • Idx 30 (integer)

      • Значение: 0
      • Хэшировано: false
      • Описание: Индекс скрипта, содержащего скрипт reCAPTCHA https://www.gstatic.com/recaptcha/releases/<version>/, Пример
    • Idx 31 (string)

      • Значение: AAgkAQI0SB
      • Хэшировано: true
      • Описание: Хэшированные ключи document.cookie, Пример
    • Idx 32 (string)

      • Значение: ""
      • Хэшировано: false
      • Описание: URL реферера document.referrer.
    • Idx 33 (integer)

      • Значение: 2

      • Хэшировано: false

      • Описание: Элемент блока reCAPTCHA, в котором происходит рендеринг.

        root@kitploit:~
        // например, grecaptcha.execute('.grecaptcha') -> этот div
        // По сути, возвращает число или глубину/уровень этого div в документе.
        
        // Пример: html > body > main > form > fieldset > div.recaptcha.form-field
        // 5 4 3 2 1 0
        // out = 5
        
        nM = document.getElementsByClassName('grecaptcha-badge')[0] // или document.getElementsByClassName('g-recaptcha')[0] v2
        let count = 0;
        for (; nM = nM.parentElement || null;) {
          count++;
        }
        
        const result = count;
        
    • Idx 34 (string)

      • Значение: AAAAAAAAAA
      • Хэшировано: true
      • Описание: Хэшированы все имена атрибутов <INPUT>, Пример
    • Idx 35 (string)

      • Значение: 0,DIV,f0c7414e
      • Хэшировано: true
      • Описание: document.activeElement - анализирует, является ли он элементом покупки, используя регулярное выражение /buy|pay|place|order|donate|purchase/i с textContent, classNames и id, Пример
    • Idx 36 (string)

      • Значение: h3, h2 or http/1.1
      • Хэшировано: false
      • Описание: nextHopProtocol из навигационной производительности performance.getEntriesByType("navigation")[0].nextHopProtocol
    • Idx 37 (integer)

      • Значение: -1
      • Хэшировано: false
      • Описание: performance.timing.unloadEventStart
    • Idx 38 (integer)

      • Значение: 96
      • Хэшировано: false
      • Описание: DNS-запрос performance.timing.domainLookupStart - performance.timing.domainLookupEnd
    • Idx 39 (integer)

      • Значение: 0
      • Хэшировано: false
      • Описание: Тип навигации performance.navigation.type
    • Idx 40 (integer)

      • Значение: 0
      • Хэшировано: false
      • Описание: Последняя позиция прокрутки по Y window.scrollY или document.defaultView.pageYOffset
    • Idx 41 (string)

      • Значение: DIV,a08cd360
      • Хэшировано: true
      • Описание: Элемент :hover, над которым находилась мышь в тот же момент; берётся последний элемент и хэшируются tagName, classNames и id, Пример
    • Idx 42 (string)

      • Значение: 9,e3b0c442
      • Хэшировано: true
      • Описание: Хэш случайного текстового скрипта с помощью SHA-256 плюс индекс, Пример
    • Idx 44 (string)

      • Значение: 2v591z63wq
      • Хэшировано: true
      • Описание: Элемент :hover, document.activeElement, все элементы <INPUT> хэшированы, location.url, window.scrollY. Пример:
      • root@kitploit:~
        const element = document.querySelectorAll(":hover");
        const current = element[element.length - 1];
        
        const result = [
            deriveSignalCode(hash(current)),
            deriveSignalCode(hash(document.activeElement)),
            deriveSignalCode(hash(document.querySelectorAll('input'))),
            deriveSignalCode(location.url),
            deriveSignalCode(String(window.scrollY))
        ].join('')
        
    • Idx 45 (integer)

      • Значение: 4
      • Хэшировано: false
      • Описание: Длина window.history.
    • Idx 46 (string)

      • Значение: https://static.kogstatic.com/0000/34c...
      • Хэшировано: false
      • Описание: В скрипте на странице произошла ошибка, указаны line:column, где это произошло.
    • Idx 47 (integer)

      • Значение: 0
      • Хэшировано: false
      • Описание: Возвращает длину текста, который в данный момент выделен на странице пользователем window.getSelection().toString().length || 0
    • Idx 49 (string)

      • Значение: h2-0
      • Хэшировано: false
      • Описание: Найти запись Performance Resource Timing для скрипта reCAPTCHA, получить её nextHopProtocol и определить, равна ли его duration нулю. Вернуть результат в формате protocol-isZero, Пример
    • Idx 50 (array)

      • Значение: [1,0,null,1,1,["805b1z63wq"],"MWc2MzZwMnR0ZHNkMw==",0,null,[[1]]]

      • Хэшировано: true

      • Описание: Содержит поведение пользователя, хэшированные элементы :hover и таймаут, увеличивающийся каждый раз, когда собирается ещё один элемент :hover. Анализирует активацию пользователя для накопления количества раз, когда пользователь взаимодействовал или всё ещё присутствует на странице, вычисляя (10 * IsActive + IsBeenActive)

        Базовый формат:

        root@kitploit:~
        [
           count,
           timeout,
           null,
           timeoutMultiplier,
           transitionCount,
           [ elementsHoverHashed ],
           sessionId,
           userActivationScore,
           null,
           [ [ flags ] ]
        ]
        
    • Idx 51 (array)

      • Значение: [0]
      • Хэшировано: false
      • Описание: Ищет в document.body.innerText совпадения со словами "try again", "incorrect", "invalid" или "declined" и возвращает общее количество найденных совпадений. В противном случае возвращает 0, Пример
    • Idx 52 (integer)

      • Значение: 11
      • Хэшировано: false
      • Описание: 10 * navigator.userActivation.isActive + navigator.userActivation.hasBeenActive
    • Idx 53 (integer)

      • Значение: 4

      • Хэшировано: false

      • Описание: Берёт текущий URL веб-сайта, преобразует его в массив символов, обрезает до 100 символов и затем преобразует обратно в строку, Пример

        Затем, если длина этой обрезанной строки чётная, возвращается 5, если нечётная — 4.

    • Idx 54 (boolean)

      • Значение: false
      • Хэшировано: false
      • Описание: Указывает, скрыт ли документ от пользователя, то есть не виден ли он на экране, window.document.hidden
    • Idx 55 (array)

      • Значение: [[[1,"2v"],[1,"9z"],[1,"z8"],[1,"us"],[1,..
      • Хэшировано: false
      • Описание: Упорядочивание сгенерированных кодов сигналов по значениям отпечатков.
    • Idx 56 (string)

      • Значение: -1,-1
      • Хэшировано: false
      • Описание: Проверка window.opener, возвращает "-1,-1", если null, Пример
    • Idx 57 (string)

      • Значение: www.gstatic.com,_,static.kogstatic.com,www.google.com,www.googletagmanager.,...

      • Хэшировано: false

      • Описание: Собирает хосты из src всех элементов <SCRIPT>, представленных в document.scripts, Пример

        Для каждого <SCRIPT>: Если элемент имеет атрибут src (hasAttribute("src")), берётся значение src и разбирается с помощью URI-подобного регулярного выражения (nd), извлекая только компонент хоста (группа захвата 3 регулярного выражения).

        Если <SCRIPT> не имеет атрибута src (является встроенным скриптом), используется плейсхолдер "_".

    • Idx 58 (string)

      • Значение: mapslitepromosdismissed1
      • Хэшировано: false
      • Описание: Выбранный ключ window.localStorage (образец).
    • Idx 59 (string)

      • Значение: ""
      • Хэшировано: false
      • Описание: Имя навигационного контекста окна или вкладки window.name
    • Idx 60 (string)

      • Значение: https://www.kogama.com,https://www.google.com,https://js.stripe.com
      • Хэшировано: false
      • Описание: URL для событий открытых сообщений, Пример
    • Idx 61 (array)

      • Значение: [0,"AAAAAAAAAA","AAAAAAAAAA"]
      • Хэшировано: true
      • Описание: Хэши имён атрибутов и типов целевых элементов, зарегистрированных с помощью MutationObserver, Пример
    • Idx 62 (string)

      • Значение: document.title
      • Хэшировано: false
      • Описание: Полный заголовок веб-сайта.
    • Idx 63 (array)

      • Значение: []

      • Хэшировано: false

      • Описание: Извлекает временные метки (12-13-значные числа, начинающиеся с 1[2-9], характерные для эпох миллисекунд ~2008-2099) из значений куки, Пример

        Суммирует следующие значения по всем найденным ID: количество, минимум, максимум и среднее. Конечным результатом является массив [count, min, max, avg]

    • Idx 64 (integer)

      • Значение: 55557
      • Хэшировано: false
      • Описание: Время выполнения (от привязки до перезагрузки).
    • Idx 65 (string)

      • Значение: sha384-3qc
      • Хэшировано: true
      • Описание: Целостность скрипта reCAPTCHA, настроенного в https://www.google.com/recaptcha/api.js?render= (обрезано до 10 символов)
    • Idx 67 (array)

      • Значение: [screen.width, screen.height, screen.availHeight, window.innerWidth, window.innerHeight, window.outerHeight]
      • Хэшировано: false
      • Описание: Разрешение экрана, ширина и высота окна просмотра браузера и высота окна браузера.
    • Idx 68 (array)

      • Значение: [300,null,1777685870223]
      • Хэшировано: false
      • Описание: Смещение часового пояса и текущая временная метка Unix [new Date().getTimezoneOffset(), null, Date.now()]
    • Idx 69 (string)

      • Значение: 09AKhCRwjrDFiHsrRA--o23-HB-eWqOtk_XQ-rLE1...
      • Хэшировано: false
      • Описание: Токен сессии, используемый для идентификации человека, хранится в куки браузера; увеличивает показатель (score), если действителен.
    • Idx 70 (array)

      • Значение: [null,null,"","",null,"1l0fl"]

      • Хэшировано: false

      • Описание: Извлекает общие денежные суммы (например, Total: $50.00 или Total 150.00 EUR), Пример

        из document.innerText путём поиска символа или кода валюты вместе с числовым значением с помощью регулярного выражения:

        root@kitploit:~
        total[\S\s]{0,20}?(((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR))`
        

        total → Ищет точное слово "total"

        [\S\s]{0,20}? → Ищет от (0) до (20) промежуточных символов (таких как пробелы, двоеточия или переносы строк) перед числом

        (((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR)) → Основной блок, который захватывает деньги и разделён на две отдельные опции

    • Idx 71 (array)

      • Значение: [jsHeapSizeLimit,usedJSHeapSize,totalJSHeapSize]
      • Хэшировано: false
      • Описание: Память HEAP JavaScript производительности.
    • Idx 72 (array)

      • Значение: [[["Google Chrome","147"],["Not.A/Brand",...

      • Хэшировано: false

      • Описание: Массив данных userAgent navigator.userAgentData, флаг, указывающий, является ли устройство мобильным, и платформа, Пример:

        root@kitploit:~
        [
          navigator.userAgentData.brands.map(b => [b.brand, b.version]),
          navigator.userAgentData.mobile ? 1 : 0,
          navigator.userAgentData.platform
        ]
        
    • Idx 73 (array)

      • Значение: [[null,2,0,"Mozilla/5.0 (Windows NT 10.0;...
      • Хэшировано: false
      • Описание: Зашифрованные сигналы виртуальной машины (VM).
    • Idx 77 (integer)

      • Значение: null
      • Хэшировано: false
      • Описание: Временная метка Unix, иногда появляется.
    • Idx 78 (string)

      • Значение: ""
      • Хэшировано: false
      • Описание: Кука Google GA, может появиться, если веб-сайт использует Google Tag Manager.

    Некоторые сигналы reCAPTCHA могут быть недоступны или не собраны (из-за тайм-аутов, связанных с отладкой). В таких случаях отсутствующий сигнал заполняется случайно сгенерированным значением, закодированным в base64. Например:``` ["CMXZyamk3ZHNjdGsyaQ==", 3249, 591]

    root@kitploit:~
    После завершения построения отпечатка (fingerprint) он сериализуется в строку и шифруется с помощью ключа шифрования, загруженного из поля «anchor» (индекс 18). Затем зашифрованный результат сохраняется в поле с индексом `16` полезной нагрузки `/reload`.
    
    ## Сигналы VM
    
    Ниже приведены значения браузера, полученные внутренней VM reCAPTCHA, вместе с ключом сигнала. Некоторые значения не отображаются в примере отпечатка, так как VM извлекает только определённые значения из конфигурационного байт-кода. Поэтому будут показаны другие значения. Подробнее см. [здесь](https://github.com/elyelysiox/recaptcha-vm)
    
    Формат базового сигнала:```
    [
      null,
      collectorElapsed,
      encryptElapsed,
      value
    ]
    

    Где collectorElapsed означает, сколько времени (мс) потребовалось сборщику для получения значения А encryptElapsed означает, сколько времени (мс) потребовалось для шифрования значения. Эти времена измеряются во время выполнения VM.

    Structure```json

    [ null, 7, 0, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36" ], null, null, [ null, 0, 0, "[]" ], null, null, [ null, 4, 0, "["Join And Get Free Trial!","","Captcha Solving Service","Products","Docs"]" ], [ null, 0, 0, "false" ], null, [ null, 0, 0, "0" ], [ null, 1, 0, "[null,null,null,null,"false"]" ], [ null, 3, 4, "[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]" ], [ null, 1, 4, "[[[0,0,979]],1,0]" ], [ null, 1, 1, "[[[1,0]]]" ], [ null, 4, 1, "[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]" ], [ null, 1, 1, "[[[1123,0,0]]]" ], [ null, 1, 2, "[[[1123,0]]]" ], [ null, 1, 3, "[0,null,null,null,null,null,null]" ], [ null, 5, 9, "[1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],[28,777,858,28],0,0,25]" ], [ null, 0, 0, "" ], [ null, 0, 0, "229.6" ], [ null, 0, 0, "false" ], [ null, 1, 0, "[1,0,0,Infinity]" ], [ null, 1, 1, "["0",-1,-1,999]" ], [ null, 1, 0, "["undefined",3]" ], [ null, 1, 6, "[2,4,53324367238]" ], [ null, 12, 0, "["Google Inc. (Intel Inc.)","ANGLE (Intel Inc., Intel(R) UHD Graphics 630, OpenGL 4.1)",30]" ], [ null, 28, 2, "[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,-1914850612,571474391,-1588406278,3443508,1967713171,-1249474914,-1588406278,0,918504841,-807058197]" ]

    root@kitploit:~
    - **Key 417** (`string`)
      - Значение: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...`
      - Описание: Полный User-Agent браузера
    
    - **Key 727** (`array`)
      - Значение: `[]`
      - Описание: Блоки цен на товары, содержит цены на коммерческие продукты на веб-сайте; они могут появляться на торговых площадках, таких как Amazon, eBay, AliExpress и т.д. [Пример](https://github.com/elyelysiox/recaptcha/blob/main/findProductPricesBlock.js)
    
    - **Key 150** (`array`)
      - Значение: `[\"Join And Get Free Trial!\",\"\",\"Captcha Solving Service\",\"Prod...`
      - Описание: Ссылки, извлечённые из элементов `<a>` на веб-сайте; VM редко извлекает эти значения
    
    - **Key 545** (`boolean`)
      - Значение: `false`
      - Описание: `navigator.webdriver`
    
    - **Key 370** (`integer`)
      - Значение: `0`
      - Описание: Максимальное количество точек касания устройства `navigator.maxTouchPoints`
    
    - **Key 779** (`array`)
      - Значение: `[null,null,null,null,"false"]`
      - Описание: Извлекает данные из полей доставки/оплаты; [Пример](https://github.com/elyelysiox/recaptcha/blob/main/formFieldScrape.js)
      
        `postal|postalcode|postalcode|postal_code|zip` → поиск поля почтового индекса
        
        `ship|deliver` → раздел доставки
        
        `billing|payment|credit` → раздел оплаты
        
        `country` → выбор страны
        
        `addr.*(match|equal)|(match|equal).*address` → флажок «совпадает с адресом»
        
        Считывает name, id, autocomplete, className каждого элемента
        Три фазы: текстовые поля, SELECT-выражения, флажки
    
    - **Key 659** (`array`)
      - Значение: `[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]`
      - Описание: Содержит данные о нажатых элементах на странице в формате `[[[count,timestamp]],[[hashedElem,tagType,type,autoComplete]],pressedCount,behaviorChecksum]`
     
        ### Тип элемента
        
        | Тип элемента | ID |
        |-------------|----|
        | `""` | 1 |
        | `text` | 2 |
        | `button` | 3 |
        | `submit` | 4 |
        | `checkbox` | 5 |
        | `email` | 6 |
        | `password` | 7 |
        | `select-one` | 8 |
        | `select-multiple` | 9 |
        | `radio` | 10 |
        | `textarea` | 11 |
        | `file` | 12 |
        | `tel` | 13 |
        | `number` | 14 |
        | `date` | 15 |
        | `reset` | 16 |
        | `range` | 17 |
    
        ### Алгоритм контрольной суммы поведения (Behavior CheckSum)
        
        `behaviorChecksum` — компактная оценка поведения, полученная на основе собранных данных о взаимодействиях пользователя.
     
        Для каждого взаимодействия:
        - Индекс взаимодействия увеличивается на единицу
        - Временная метка комбинируется со скорректированным индексом взаимодействия
        - Хеш элемента сокращается с помощью операции взятия остатка от деления
        - Результат накапливается в текущее значение
       
        ---
    
        ```javascript
        function computePressedElementsChecksum(pressedElementsArray) {
          let accumulator = 0;
        
          for (const [countTimestampPair, elementInfo] of zip(
            pressedElementsArray[0],
            pressedElementsArray[1],
          )) {
            const shiftedTimestamp = countTimestampPair[0] + 1;
            const baseValue = countTimestampPair[1] + shiftedTimestamp;
            const remainder = elementInfo[0] % baseValue;
            accumulator = remainder + accumulator;
          }
        
          const logTerm = Math.log(accumulator + 1) * 4;
          const modTerm = accumulator % 10;
          const behaviorChecksum = Math.floor(logTerm + modTerm);
        
          return JSON.stringify(pressedElementsArray);
        }
    
        function zip(a, b) {
          const length = Math.min(a.length, b.length);
          const result = [];
          for (let i = 0; i < length; i++) {
            result.push([a[i], b[i]]);
          }
          return result;
        }
        ```
    
        ### Пример
    
        ```javascript
        const checksum = computePressedElementsChecksum([[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]);
        console.log(checksum); // → 39
        ```
    
    - **Key 959** (`array`)
      - Значение: `[[[0,0,979]],1,0]`
      - Описание: Содержит данные о перемещениях прокрутки, собранные во время сессии на странице
     
        ### Базовый формат
        ```
        [ [ [ scrollX, scrollY, timestamp ] ], count, behaviorChecksum ]
        ```
    
    - **Key 895** (`array`)
      - Значение: `[[[1,0]]]`
      - Описание:`VisibilityStateEntry` отслеживает состояние видимости страницы, указывая, просматривает ли пользователь страницу в данный момент или ушёл с неё, в формате `[[[isVisible, startTime]]]`
    
    - **Key 1092** (`array`)
      - Значение: `[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]`
      - Описание: Производительность reCAPTCHA, PerformanceNavigationTiming и PerformanceEventTiming, в формате `[vmStart,vmEnd,domContentLoadedEventEnd,loadEventEnd,firstUserInteractionTime]`
    
    - **Key 41** (`array`)
      - Значение: `[[[1123,0,0]]]`
      - Описание: ClearTimeout
    
    - **Key 43** (`array`)
      - Значение: `[[[1123,0]]]`
      - Описание: ClearTimeout
    
    - **Key 549** (`array`)
      - Значение: `[0,null,null,null,null,null,null]`
      - Описание: KeyboardEvent, вычисленные клавиши + временные метки
    
    - **Key 352** (`array`)
      - Значение: `1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],...`
      - Описание:
        Структура содержит:
    
        - Хронометраж движения мыши
        - Координаты курсора
        - Продолжительность нажатий
        - Размеры нажатого элемента
        - Информацию о типе указателя
        - Показатели давления
        - Расстояние перемещения курсора
        - Статистику временных характеристик поведения
    
        ### Базовый формат:
        ```
        [
          eventsCount,
          mouseEvents,
          [
            coalescedEventsCount,
            averageInterEventDelay,
            timingVarianceScore
          ],
          [
            totalPoints,
            clickSequenceScore,
            totalCursorDistance,
            totalPoints
          ],
          0,
          0,
          behaviorChecksum
        ]
        ```
        
        ### Структура события мыши:
        
        Каждая запись внутри mouseEvents имеет следующую структуру:
        
        ```
        [
          timestamp,
          clickDuration,
          clientX,
          clientY,
          [
            elementLeft,
            elementTop,
            elementWidth,
            elementHeight
          ],
          elementTagType,
          trackedElementIndex,
          pressure,
          pointerTravelDistance,
          pointerArea
        ]
        ```
    
        | Имя | Описание |
        |---|---|
        | `timestamp` | Временная метка события относительно начала события |
        | `clickDuration` | Продолжительность между `pointerdown` и `pointerup` |
        | `clientX` | ... |
        | `clientY` | ... |
        | `elementBounds` | Ограничивающий прямоугольник взаимодействующего элемента |
        | `elementTagType` | Закодированный идентификатор тега DOM взаимодействующего элемента |
        | `trackedElementIndex` | Внутренний идентификатор взаимодействующего элемента DOM из карты взаимодействий во время выполнения |
        | `pressure` | Нормализованное значение давления указателя, умноженное на `100` |
        | `pointerTravelDistance` | Расстояние между `pointerdown` и `pointerup` |
        | `pointerArea` | Площадь контакта, вычисленная как `width * height` |
    
        ### Тип тега элемента
    
        Инициализируется во время выполнения VM reCAPTCHA
    
        | Тип      | ID |
        |-----------|----|
        | `BODY`    | 1  |
        | `INPUT`   | 2  |
        | `BUTTON`  | 3  |
        | `SELECT`  | 4  |
        | `TEXTAREA`| 5  |
        | `FORM`    | 6  |
        | `A`       | 7  |
        | `AREA`    | 8  |
        | `AUDIO`   | 9  |
        | `VIDEO`   | 10 |
        | `IFRAME`  | 11 |
        | `DIV`     | 12 |
        | `SPAN`    | 13 |
        | `LABEL`   | 14 |
    
        ### Пример
        ```
        [
          18342,
          91,
          742,
          381,
          [700, 320, 120, 38],
          3,
          1,
          50,
          1.4,
          16
        ]
        ```
        
        Представляет:
        
        - событие через `18,342 с`
        - длительность нажатия `91 мс`
        - нажатие в точке `(742, 381)`
        - взаимодействие с кнопкой (`BUTTON`)
        - давление указателя `0,5` (50)
        - небольшое движение курсора во время нажатия
        - площадь контакта указателя `16`
       
        ### Алгоритм контрольной суммы поведения (Behavior CheckSum)
     
        Для каждого события мыши:
    
        - Продолжительность нажатия усиливается
        - Результат комбинируется с временной меткой события
        - Координаты курсора и размеры элемента смешиваются
        - Вычисляется взвешенное отношение
        - Отношение округляется и накапливается
        
        После обработки всех событий:
        
        - Накопленная оценка комбинируется с общим расстоянием курсора
        - Результат нормализуется по количеству собранных точек
        - Применяется логарифмическое преобразование
        - Добавляются дополнительные статистические показатели движения
        - Итоговое значение сокращается с помощью операции взятия остатка от деления
        - Результат округляется до небольшого целочисленного значения
        
        ---
        
        ```javascript
        function computeMouseBehaviorChecksum(mouseDataArray) {
          let totalSum = 0;
        
          for (let i = 0; i < mouseDataArray[1].length; i++) {
            const event = mouseDataArray[1][i];
        
            const scaledClickDuration = event[1] * 4;
            const xPlusScaledDuration = event[0] + scaledClickDuration;
            const combinedElementDims = event[2] + event[4][2] + event[4][1]; // clientY + elementWidth + elementTop
            const product = xPlusScaledDuration * combinedElementDims;
            const divisor = event[3] + event[4][3] + event[4][0] + 1; // elementTagType + elementHeight + elementLeft + 1
            const roundedValue = Math.round(product / divisor);
        
            console.log(roundedValue);
            totalSum += roundedValue;
          }
        
          const summaryArray = mouseDataArray[3]; // [totalPoints, clickSequenceScore, totalCursorDistance, totalPoints]
          const sumPlusCursorDistance = totalSum + summaryArray[2];
          const totalPointsPlusOne = summaryArray[0] + 1;
          const ratio = sumPlusCursorDistance / totalPointsPlusOne;
          const ratioPlusOne = ratio + 1;
          const logRatio = Math.log(ratioPlusOne);
          const scaledLog = logRatio * 4;
          const ratioPlusTotalPoints = ratio + summaryArray[0];
          const ratioPlusTotalPointsPlusScore = ratioPlusTotalPoints + summaryArray[1];
          const modResult = ratioPlusTotalPointsPlusScore % 11;
          const behaviorChecksum = Math.round(scaledLog + modResult);
          return JSON.stringify(mouseDataArray);
        }
        ```
    
        ### Пример
    
        ```javascript
        const checksum = computeMouseChecksum([1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],[28,777,858,28],0,0,25]);
        console.log(checksum); // → 25
        ```
    
    - **Key 360** (`string`)
      - Значение: `""`
      - Описание: Собранные общие цены на веб-сайте, извлечённые с помощью регулярного выражения `(?i)total[\S\s]{0,20}?(?:(?:(?:USD|\$)\s*)?[\d\.,]+\s*(?:USD|\$)|(?:USD|\$)\s*[\d\.,]+)`, [Пример](https://github.com/elyelysiox/recaptcha/blob/main/websitePricesTotal.js)
    
    - **Key 1278** (`integer`)
      - Значение: `229.6`
      - Описание: Деление на 10 текущего времени выполнения `Math.trunc(performance.now()) / 10`
        
    - **Key 1422** (`boolean`)
      - Значение: `false`
      - Описание: Определяет, есть ли на веб-сайте поля для OTP/2FA, [Пример](https://github.com/elyelysiox/recaptcha/blob/main/parseOTPFields.js)
    
    - **Key 614** (`array`)
      - Значение: `[1,0,0,Infinity]`
      - Описание: Информация о батарее устройства, в формате `[level,isCharging,chargingTime,dischargingTime]`
    
    - **Key 2033** (`array`)
      - Значение: `["0",-1,-1,999]`
      - Описание: Некоторые константные значения VM и время выполнения VM
    
    - **Key 1313** (`array`)
      - Значение: `["undefined",3]`
      - Описание: Проверки Android, Chrome, `[typeof window.android, Object.keys(window.chrome).length]`
    
    - **Key 1994** (`array`)
      - Значение: `[2,4,53324367238]`
      - Описание: `[navigator.hardwareConcurrency, navigator.deviceMemory, navigator.storage.estimate().qouta]`
    
    - **Key 1310** (`array`)
      - Значение: `["Google Inc. (Intel Inc.)","ANGLE (Intel Inc.,...`
      - Описание: Рендерер WebGL, производитель и общее количество расширений, [Пример](https://github.com/elyelysiox/recaptcha/blob/main/webglSignals.js)
    
    
    - **Key 291** (`array`)
      - Значение: `[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,...`
      - Описание: Хешированные ключи определённых прототипов объектов браузера, таких как `SpeechSynthesisEvent`, `NetworkInformation`, `HTMLElement` и т.д., [Пример](https://github.com/elyelysiox/recaptcha/blob/main/hashBrowserProtos.js)
    
    ## Полезная нагрузка запроса на повторную загрузку (Reload Request Payload)
    
    Эти данные сериализуются с помощью protobuf (Protocol Buffers) — эффективного, нейтрального метода сериализации структурированных данных, разработанного Google.```javascript
    [
      "rreq",
      "U5VsmTDhJM1iOJUyw4DEUTYv",
      "03AFcWeA5Els3SIQviW2OYCHYD4uDhKlFPG6A48z2nk74BC2vrXSRvtpP9uVkWW96kUKm7sHIr...",
      null,
      null,
      "-383788762",
      "q",
      "05APQrAobTCFGtbKVY3NwExv-K_G7oqmzGyUcTXi532CBKvSJUiT49tkRSgGD__OdfVRZtrI3i...",
      "submit",
      null,
      null,
      null,
      null,
      null,
      "6LcAbwIqAAAAAJvVAhSSJ8qzYsujc7kn1knmSgQX",
      null,
      "0XA4cHhALxgMF9_Kt6uze2ZTR08XAe2x8o3BrU1hbTouNf3o1cnRmYRxZW01IA0BCNC_qJykb...",
      null,
      null,
      null,
      "tbMywxNTQsODQ0XSxbMSwyOTksMTA4Nl1dLFtbMiw2MSwxMzIuNzM5OTk5OTk5ODQ2MzNdLF...",
      "0aAPQrAobqMEazjp9PGLYWTgxWGGcq9k5MJNI6LFBWfTh0UkDaVobdH-InwAYsTXtxs3rH_fI",
      "BDAAYAIAGEcAAUoYI4lDCKAsCJlcgB6AAJtgggoIEEOALSoQRZxSZyAJBHANCkAJQYhFJES...",
      null,
      null,
      "W1tbNTAwNiw0M10sWzY0NjA3LDFdLFs0NTQ2NCwxXSxbMzU4MzcsMV1dXQ==",
      null,
      null,
    ]
    

    Компоненты

    ИндексЗначениеОписание
    0rreqИдентификатор типа запроса
    1U5VsmTDhJM1iO...Версия reCAPTCHA
    203AFcWeA5Els3...Токен проверки, полученный из конечной точки /anchor
    5-383788762Хэш всего сериализованного полезного отпечатка, Пример
    6qУказывает на выполняемый вызов или режим запроса
    705APQrAobTCFG...Шаблоны использования, содержащие историю использования и ранее решённые шаблоны вызовов. Могут значительно повысить оценку, если действительны
    8submitКонкретное действие сайта, которое пользователь выполняет на странице во время проверки (например signin, register)
    146LcAbwIqAAAA...Ключ веб-сайта
    160XA4cHhALxgM...Зашифрованный весь сериализованный полезный отпечаток с помощью ключа шифрования из anchor (индекс 18) 1777669303203
    20tbMywxNTQsOD...Структура телеметрии в кодировке Base64, содержащая дельты времени виртуальной машины, временные данные ресурсов, собранную статистику объектов браузера и URL-адреса скриптов веб-сайта
    210aAPQrAobqME...Токен, связанный с ранее решённой CAPTCHA. Используется для непрерывности сеанса и корреляции доверия
    22BDAAYAIAGEcA...Хэш всех ключей объектов браузера
    25

    Режимы вызовов

    ЗначениеОписание
    qВызов reCAPTCHA V3
    fiВызов reCAPTCHA V2/Invisible
    aАудио-вызов
    qrБыстрый ответ (новый)

    Полезная нагрузка телеметрии (Idx 20)

    Для декодирования:```javascript atob("W1tbMywwLDgyOV0sWzEs...") // → [[[3,0,829],[1,42,863]],[[2,727,1341.300000011921]...

    root@kitploit:~
    Полезная нагрузка содержит:
    
    - Информацию о времени загрузки ресурсов
    - Метрики производительности долгих задач
    - Дельта выполнения VM reCAPTCHA
    - URL-адреса скриптов веб-сайта
    - Статистику коллекций объектов браузера
    
    ### Базовая структура```js
    [
      [recaptchaResources],
      [tasksTiming],
      [
          null,
          null,
          null,
          idleTimeoutDelta,
          deltaTiming,
          0,
          0,
          0,
      ],
      websiteScriptsUrls,
      [collectionElapsed, browserObjectsLength]
    ]
    

    Формат тайминга длительных задач```js

    [ PerformanceLongTaskTiming.name == "self" ? 2 : 4, PerformanceLongTaskTiming.duration, PerformanceLongTaskTiming.startTime ]

    root@kitploit:~
    ### Формат тайминга ресурсов reCAPTCHA```js
    [
       resourceType,
       duration,
       startTime
    ]
    
    РесурсТип
    recaptcha/api.js3
    recaptcha/releases/<version>1
    https://www.google.com/recaptcha/api2/anchor2
    https://www.google.com/recaptcha/api2/bframe4

    Счетчики событий (Idx 25)

    Это поле содержит счетчики взаимодействий с браузером, закодированные в Base64, собранные во время выполнения.

    Пример декодированного значения:```js [ [ [5006, 43], [64607, 1], [45464, 1], [35837, 1] ] ]

    root@kitploit:~
    ### Структура счетчика событий```js
    [
      [
        [eventType, count]
      ]
    ]
    

    Известные хеши событий

    ХешТип события
    5006pointermove
    64607pointerdown
    45464pointerup
    31617keydown
    37178keyup
    35837focusin

    Структура ответа```js

    [ "rresp", "", null, 120, [ "pmeta", [ "/m/013xlm", null, 3, 3, 3, null, "Tractor" ], null, [1] ], "", null, null, "", "", null, null, "", null, "", "", 0 ]

    root@kitploit:~
    ## Описание полей
    
    | Индекс | Имя | Описание |
    |---|---|---|
    | `0` | `rresp` | Идентификатор типа ответа, возвращаемый конечной точкой reload |
    | `1` | `responseToken` | Токен ответа reCAPTCHA |
    | `3` | `tokenExpiration` | Время жизни токена в секундах до истечения срока |
    | `4` | `pmeta` | Блок метаданных задачи, содержащий информацию о типе CAPTCHA, категории и расположении сетки |
    | `5` | `challengeType` | Тип задачи CAPTCHA |
    | `8` | `usagePatternToken` | Шаблоны использования, хранящиеся в `window.sessionStorage` и повторно используемые в будущих запросах `/reload` |
    | `9` | `challengeImageToken` | Токен, используемый для получения полезной нагрузки изображения CAPTCHA из конечной точки `/payload` |
    | `12` | `humanVerificationToken` | Токен идентификации человека, связанный с состоянием Google reCAPTCHA и файлами cookie браузера |
    | `14` | `captchaSessionToken` | Внутренний сессионный токен |
    | `15` | `bftToken` | ... |
    
    ---
    
    ### Структура `pmeta`
    
    Пример:```js
    [
        "pmeta",
        [
            "/m/013xlm",
            null,
            3,
            3,
            3,
            null,
            "Tractor"
        ],
        null,
        [1]
    ]
    

    pmeta[1] Значения

    ПозицияЗначениеОписание
    0/m/013xlmВнутренний идентификатор категории для целевого класса объекта
    23Количество столбцов сетки
    33Количество строк сетки
    5nullЗарезервированное или опциональное поле метаданных
    6"Tractor"Текстовая метка

    Типы заданий

    ТипОписание
    imageselectСтандартная CAPTCHA с выбором изображения
    tileselectДинамическое задание на основе плиток
    dynamicДинамическое задание, где плитки перезагружаются после выбора
    multicaptchaМногошаговое задание CAPTCHA
    audioАудио-задание для доступности
    nocaptchaПроверка только с помощью флажка
    doscaptchaОтказ от CAPTCHA при злоупотреблениях

    Получение изображения задания

    Значение в Idx 9 (challengeImageToken) используется для получения изображения CAPTCHA:```txt https://www.google.com/recaptcha//payload ?p= &k=

    root@kitploit:~
    ### Идентификаторы категорий
    
    | ID | Категория |
    |---|---|
    | `/m/0pg52` | Такси |
    | `/m/01bjv` | Автобус |
    | `/m/02yvhj` | Школьный автобус |
    | `/m/04_sv` | Мотоцикл |
    | `/m/013xlm` | Трактор |
    | `/m/01jk_4` | Дымоход |
    | `/m/014xcs` | Пешеходный переход |
    | `/m/015qff` | Светофор |
    | `/m/0199g` | Велосипед |
    | `/m/015qbp` | Паркомат |
    | `/m/0k4j` | Автомобиль |
    | `/m/015kr` | Мост |
    | `/m/019jd` | Лодка |
    | `/m/0cdl1` | Пальма |
    | `/m/09d_r` | Гора / холм |
    | `/m/01pns0` | Пожарный гидрант |
    | `/m/01lynh` | Лестница |
    
    ## Полезная нагрузка запроса UserVerify
    Полезная нагрузка `/userverify` отправляется после того, как пользователь пройдет задачу с изображениями reCAPTCHA v2
    
    # Структура полезной нагрузки```
    v: hsFBb1u5wWWWkWP4in1ua2cQ
    c: 03AFcWeA5RIHz5mI2COQqTcLjdrC7FiPpdfkX-hB-B2iFenI...
    response: eyJyZXNwb25zZSI6WzMsMSw0LDksMCwxMSwxMCwxMywxNF0....
    t: 24521
    ct: 24521
    ch: -4007845
    oc: 0ZpqzzPgYKEEaN0xpfo3v_voeVUySZK3Ktf_fLVRdhnu3yeTy4BhO...
    pm: 51bGwsbnVsbCxbbnVsbCxudWxsLG51bGwsWzEwLDQuMjcwMDAwMD....
    

    Компоненты

    ПолеИмяОписание
    vrecaptchaVersionВерсия reCAPTCHA
    cchallengeTokenТокен состояния вызова, полученный от /replaceimage или предыдущего запроса /userverify
    responseЗакодированная полезная нагрузка, содержащая индексы выбранных плиток и дополнительные метаданные взаимодействия
    tchallengeElapsedПрошедшее время с момента начальной загрузки вызова
    ctcompletionTimeОбщее время, затраченное пользователем на решение и отправку CAPTCHA
    chocHashХеш всей сериализованной полезной нагрузки oc, Пример
    ocencryptedVmSignalsЗашифрованные сигналы, собранные из виртуальной машины reCAPTCHA, см. здесь.
    pmtelemetryPayloadЗакодированная в Base64 структура телеметрии, содержащая разницу времени выполнения ВМ, временные метки ресурсов, собранную статистику объектов браузера и метаданные скриптов веб-сайта

    Полезная нагрузка response

    Представляет индексы/позиции квадратов, выбранных пользователем в сетке

    Полезная нагрузка позже кодируется как JWT перед отправкой


    Пример сетки 3×3

    grid33```txt 0 1 2 3 4 5 6 7 8

    root@kitploit:~
    Пример полезной нагрузки:```json
    {
      "response": [2, 3, 6]
    }
    

    Пример сетки 4×4 MultiCaptcha

    grid44```txt 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

    root@kitploit:~
    Пример полезной нагрузки:```json
    {
      "response": [2, 3, 6, 14]
    }
    

    Поле e

    Полезная нагрузка response может также включать поле e:```json { "response": [2, 3, 6, 14], "e": "bxCoiXVt49I7CTS_tNlVbGg" }

    root@kitploit:~
    Это поле содержит зашифрованные метаданные взаимодействия, связанные с действиями кнопок CAPTCHA, такими как:
    
    - `Verify`
    - `Next`
    - `Skip`
    
    ### Внутренняя структура `e`
    
    После расшифровки структура выглядит следующим образом:
    
    ``````txt
    [[["9ffd9672"]]]
    

    Каждое значение представляет собой хешированный идентификатор для класса/действия кнопки rc-button-default

    Хеш:

    • Основан на SHA-256
    • Усечен до 8 символов

    Более длинные последовательности взаимодействия могут выглядеть так:```txt [ [ ["9ffd9672"], ["9ffd9672"], ["9ffd9672"], ["9ffd9672"] ] ]

    root@kitploit:~
    ### `oc` — Зашифрованные сигналы VM
    
    Использует тот же алгоритм шифрования, что и поле `idx 16` в полезной нагрузке запроса `/reload`, с ключом шифрования, загруженным в якорь (индекс 31) `1777752103288`
    
    ### `pm` — Полезная нагрузка телеметрии
    
    Поле `pm` содержит структуру телеметрии, закодированную в Base64, аналогичную полезной нагрузке телеметрии, используемой в `/reload`.
    
    ## Антиотладка/Защита от взлома
    - ***Метка целостности на основе Symbol***
        reCAPTCHA устанавливает ключ Symbol `Symbol(jas)` для каждого массива и объекта с числовым значением, используемым в качестве проверки целостности. Поскольку Symbols не перечисляемы и невидимы для стандартных операций клонирования (таких как JSON.stringify), любая попытка заменить или клонировать эти структуры приводит к потере метки, что reCAPTCHA обнаруживает как подделку
    
        ![tamp](https://raw.githubusercontent.com/elyelysiox/recaptcha/main/photos/849230834092888898.png)
    
    - ***Захват переменных замыкания***
        Некоторые значения намеренно ограничены областью внешней функции и используются только внутри вложенных обратных вызовов или замыканий; переменная никогда не существует в той же области, где используется
    
    - ***Проверки времени выполнения***
        reCAPTCHA включает механизмы обнаружения отладки во время выполнения. Если обнаруживается, что код анализируется отладчиком, он перезапускает сеанс отладки, что приводит к потере состояния выполнения и контекста
    
    - ***Вкладка сбоя источника***
    
        https://github.com/user-attachments/assets/4ae3bf68-5ae7-4adc-a0b9-36cc11b64998
      
        Эта ошибка возникает в браузерах, использующих Chromium. Существует несколько ошибок, которые приводят к неожиданному закрытию браузера или инструментов разработчика, например, показанная здесь:
        
        https://blog.castle.io/detect-and-crash-chromium-bots-with-one-weird-trick-bots-hate-it/ 
        https://issues.chromium.org/issues/340836884?ref=blog.castle.io
        
        Поэтому одна из этих ошибок, вероятно, срабатывает при наступлении тайм-аута, так как это, скорее всего, не произошло бы в ходе реального пользовательского сеанса
    
    ## reCAPTCHA Botguard
    
    Хотя BotGuard был удалён Google, я кратко объясню, как он работает внутри, для тех, кто интересуется его устройством и тем, чем он отличается от других типов ботгарда.
    
    Сначала процесс генерации токена: VM генерирует токены для постоянных ошибок во время выполнения. Эти ошибки могут быть вызваны отклонениями смещения байт-кода, отсутствующими регистрами VM, неверным состоянием VM и нарушением целостности потока управления. Эти ошибки перехватываются диспетчером, который вызывает функцию, записывающую байты для токена.
    
    VM использует ARX Cipher — алгоритм, созданный АНБ в 2013 году, похожий на Speck для шифрования данных. Он также используется во всех версиях Google BotGuard. Алгоритм меняется с каждой версией, как и константа (3990), порядок операций и раунды. Выглядит это так:```javascript
    /*
    D -> cipher state array
    P -> seed
    E -> byte index
    */
    Vl = function(D, P, E, F, v) {
        F = D[3] | 0;
        D = D[2] | 0;
        for (v = 0; v < 14; v++) {
            E = E >>> 8 | E << 24;
            E += P | 0;
            E ^= D + 3990;
            P = P << 3 | P >>> 29;
            P ^= E;
            F = F >>> 8 | F << 24;
            F += D | 0;
            F ^= v + 3990;
            D = D << 3 | D >>> 29;
            D ^= F;
        }
        return [P >>> 24 & 255, P >>> 16 & 255, P >>> 8 & 255, P >>> 0 & 255, E >>> 24 & 255, E >>> 16 & 255, E >>> 8 & 255, E >>> 0 & 255];
    }
    

    Byte Writer & Encryption

    Основная функция шифрования имеет два режима: с шифрованием и без шифрования. Режим с шифрованием использует ARX Cipher, Bitwise + XOR для шифрования данных и помещения их в буфер. Существует 4 типа буферов:

    • Основной буфер 180
    • Буфер энтропийного пада 353
    • Буфер ошибок 304
    • Буфер PoE (Proof of Execution) 243 (не используется в этом типе botguard).

    Режим без шифрования просто помещает уже зашифрованные байты в буфер```javascript // (The sequence flatten messed up the statements a bit) /* Q -> cipher state array FQ(v, c) -> derive a seed c = (z << 3) - 4 -> index FQ(v, (c | 0) + 4) -> position */ t = function(D, P, E, F, v, Q) { if (E.O == E) { P = function(h, A, c, x, z) { A = v.length; // buffer length z = (A | 0) - 4 >> 3; if (v.Jw != z) { // vm.block_index != index v.Jw = z; // set new block index c = (z << 3) - 4; x = [0, 0, Q[1], Q[2]]; try { v.zB = Vl(x, FQ(v, c), FQ(v, (c | 0) + 4)); // call ARX Cipher to generate keyStream } catch (V) { throw V; } } v.push(v.zB[A & 7] ^ h); // sets A to bits 0-7, and obtains a byte from the keystream and applies xor with a byte of the data to be encrypted }; v = Z(P, E); // get buffer if (P == 180 || P == 243 || P == 353) { Q = Z(189, E); } else { // set encripted bytes to buffer P = function(h) { v.push(h); }; } F && P(F & 255); E = D.length; for (F = 0; F < E; F++) { P(D[F]); } } }

    root@kitploit:~
    А это функция, которая обрабатывает ошибки и вызывает byte writer.```javascript
    // (The sequence flatten messed up the statements a bit)
    
    p = function(D, P, E, F, v, Q, h, A) {
        D = E[1];
        A = E[2];
        Q = Z(465, P) >> 3; 
        h.push(D, Q >> 8 & 255, Q & 255); // error code/header bytes
        E.message && (D += E.message);
        A = void 0;
        E && E[0] === U && (E = void 0);
        h = Z(244, P);
        h.length == 0 && (A != void 0 && h.push(A & 255));
        D = "";
        E && (E.stack && (D += ":" + E.stack));
        E = Z(0, P); // buffer size limit (2048)
        if (!P.TB && E[0] > 3) {
            D = D.slice(0, (E[0] | 0) - 3); 
            E[0] -= (D.length | 0) + 3;  // reduce size limit
            D = Pv(D);
            E = P.O;
            P.O = P;
            try {
                v = (v = Z(304, P)) && v[v.length - 1] || 95;
                if (P.n3) {
                    // this path is never executed
                    (F = Z(123, P)) && F[F.length - 1] == v || t([v & 255], 123, P);
                } else {
                    t([95], 304, P); // set byte to error buffer
                }
                t(O(2, D.length).concat(D), 180, P, 9); // set bytes to main buffer
            } finally {
                P.O = E;
            }
        }
    }
    

    В конце выполнения VM вызывает главную функцию, которая подготавливает полезную нагрузку с этими буферами и генерирует токен, являющийся подписью. В отличие от других BotGuard VM, эта VM не имеет системы снятия отпечатков, Google Botguard, а также не выполняет эти операции выдачи ошибок и записи байт, и она намного проще и легче поддается обратному проектированию.

    Disclaimer

    Этот репозиторий предназначен исключительно для образовательных и исследовательских целей. Код, техники и концепции, представленные здесь, предназначены для академического изучения и понимания рассматриваемых тем.

    Скачать инструмент
    W1tbNTAwNiw...
    Счётчики в кодировке Base64 для событий взаимодействия пользователя, таких как движение мыши, клики, клавиатура и изменения фокуса