Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
recaptcha — Documentação e engenharia reversa do reCAPTCHA | Kitploit
Ferramentas/GitHubGitHub/elyelysiox/recaptcha
Análise EstáticaAnálise Dinâmica de Código (DAST)Engenharia ReversaSegurança WebAnti-BotBypass de CAPTCHA
GitHubelyelysiox/recaptcha

recaptcha

Documentação e engenharia reversa do reCAPTCHA

Ver Repositório
22738há 1 mêsRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Description

This repository contains a technical analysis of Google's antibot (reCAPTCHA) focusing on:

  • Payload Structure and Values
  • Fingerprinting Techniques
  • Obfuscation Techniques
  • Anti-debugging/Tampering Techniques
  • Virtual Machines

Contact

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

Obfuscation Techniques

reCAPTCHA is one of the anti-bot systems with the most sophisticated obfuscation techniques, employing a series of transformations that make the code less readable and more difficult to reverse engineer. Most obfuscations can be easily manipulated using the Abstract Syntax Tree (AST), but some are processed at runtime, rendering the AST useless in this case. Polymorphism is also applied to the code to change its structure in each version of the script. For example, the code doesn't perform the action directly. Instead, it uses objects or functions that change shape

  • Sequence Expressions The code is flattened by converting each block statement into a continuous comma-separated expression, it can appear in if statements, function arguments, and even within objects seq

  • Mixed Boolean Arithmetic Intertwines arithmetic operations (addition, subtraction, multiplication) with bitwise operations (AND, OR, XOR, NOT) to hide the original logic, for example -2 * ~(h & H) + -2 + (h ^ H)

  • Indirect Function Table Each function is built within a table, and is called using its index, like functions[index](https://github.com/elyelysiox/recaptcha/blob/HEAD/args)

  • Inline Constant Array A local array literal is assigned inline, mid-expression, the array groups constants (numbers, strings) that are reused throughout the function body via index access

    root@kitploit:~
    // 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
    }
    
  • Function Multiplexing Multiple logically distinct functions are merged into one, using a numeric parameter as a block selector. The active block is determined by evaluating the parameter against bitwise conditions. Callers pass a numeric literal as the selector

    root@kitploit:~
    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;
    }
    
  • Logical Operator Branching Replaces if statements and if/else blocks with logical operator short-circuit evaluation, converting control flow into expressions. combined with sequence expressions, multiple branches appear as a single continuous comma-separated expression

    root@kitploit:~
    // 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), ...)),
    
  • Bind Native Methods Constants Binds native browser methods to their original receivers, storing them as constants to prevent tampering

    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 Inaccessible or unused blocks of code are injected throughout the file, increasing its size to over 60,000 lines, this makes static analysis and LLM-based reverse engineering difficult

  • Control Flow Flattening Transforms each part of the code (declarations and loops) into a flat state machine. It hides the original execution logic by routing all code blocks through a central "dispatcher" block

    Dispatchers can change shape; some have 2-3 state variables, and the loop/condition type changes. They look like this

    cff1

    This is a CFF with 2 state variables, one handles the catch block and the other the try block.

  • Encrypted String Pool All string literals (DOM APIs, browser properties, CSS values, error messages, etc) are encrypted into a single massive string pool. A decryption function uses a seed and an LCG-based XOR cipher to extract each string at runtime

    There are 1990+ call sites spread across the code, the decryption function uses a running key that accumulates decoded codepoints, making each character dependent on all previous ones

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

  • Stateful Value Iterator reCAPTCHA uses stateful function that returns a sequence of runtime objects and values (like window, document.body, numeric constants) in a fixed order, each call advances an internal cursor, calling it out of sequence or too many times corrupts all subsequent reads. A timeout mechanism invalidates the state after a fixed interval, returning null for any late reads

    root@kitploit:~
    // 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  
    
    
  • Computed Function Table This is similar to Indirect Function Table, but here the index of the function to be obtained is calculated at runtime with a seed, using XOR and Modulus

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

    computed

  • Runtime Value Encryption Some values ​​(captcha configuration parameters, anchor parameters, etc) are never stored in plain text; they are encrypted immediately after collection and decrypted only at the time of use, have a prefix B at the beginning

    hiddenv

  • Async Control Flow Obfuscation Synchronous logic is converted into generator-based state machines wrapped in recursive Promise chains, tracing any value through the debugger forces stepping through multiple async handlers, losing the original execution context at each .then() boundary

Anchor Payload/Response

Payload Structure

Components to initialize reCAPTCHA``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

root@kitploit:~
### Resposta

A resposta contém:
- Design da janela do iframe do CAPTCHA
- Token de âncora usado para validação de payload (/reload)
- A configuração principal para inicialização, executada no método `recaptcha.anchor.Main.init` para recebê-la no recaptcha_en.js

### Estrutura:

Nota: o Recaptcha BotGuard foi removido em `04/01/2026`. Você pode ver alguns exemplos [aqui](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
]

Fingerprint

Os valores​​ são baseados nos valores descriptografados​​ do primeiro fingerprint de amostra, veja aqui

Cada subcampo dos valores​​ do fingerprint tem um formato base:

[value, key, elapsed]

Onde key é a chave de criptografia, e elapsed é o tempo que o coletor levou para obter e criptografar o valor. Isso permite que o reCAPTCHA detecte:

  • Execução excessivamente rápida
  • Hooks
  • Breakpoints e sandboxing

Ordem de Execução do Coletor

O sistema usa um escalonador interno:``` [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:~
Isto representa:

- Ordem de Execução
- Pipeline do Coletor
- Sequência de Geração de Sinais

### Códigos de Sinais de Impressão Digital e Derivação de Chaves
Transforma sinais de impressão digital em chaves de criptografia determinísticas por meio de um pipeline de derivação em vários estágios

Cada valor de impressão digital é:

- Normalizado
- Codificado em um código de sinal compacto
- Convertido em uma chave de criptografia numérica
- Criptografado usando a chave derivada

O processo é determinístico, o que significa que o mesmo valor de entrada sempre gera o mesmo código de sinal e chave de criptografia```
Raw Value
   ↓
Signal Code Derivation
   ↓
Compact Signal Code
   ↓
Numeric Key Derivation
   ↓
Encryption Key
   ↓
Value Encryption

Exemplo

Sinal de Entrada``` "BUTTON,195a81c9"

root@kitploit:~
***Passo 1 - Derivar o Código de Sinal***```javascript
deriveSignalCode("BUTTON,195a81c9")
// → "wg"

O código de sinal gerado é um identificador determinístico compacto para o valor original.

Etapa 2 - Derivar Chave Numérica```javascript deriveKey("wg") // → 3792

root@kitploit:~
O código de sinal é transformado em uma chave de criptografia numérica.

***Etapa 3 — Criptografar Valor***```javascript
encryptValueWithKey(3792, "wgia1z9pwq")
// → "bYVbh6BUsE_5pLA"

O próximo valor será criptografado com a chave derivada, seguindo a ordem do coletor.

Estrutura de Impressão Digital Agregada

Todos os códigos de sinal gerados são agregados em uma estrutura serializada compacta

Processo``` 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:~
**Final**```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"
]

Sinais

  • Idx 4 (string)

    • Valor: 3ccb

    • Com hash: true

    • Descrição: Gera uma chave HMAC a partir de window.localStorage.getItem("rc::a") + "6d" convertida em bytes, calcula HMAC-SHA256(siteKey) com essa chave e retorna os primeiros 4 caracteres hexadecimais do resultado.

      O valor de rc::a é um base64 gerado aleatoriamente.

  • Idx 5 (integer)

    • Valor: window.localStorage.length * 2
    • Com hash: false
    • Descrição: Comprimento de window.localStorage multiplicado por 2
  • Idx 16 (string)

    • Valor:


Certos sinais do reCAPTCHA podem estar indisponíveis ou falhar na coleta (devido a timeouts relacionados à depuração). Nesses casos, o sinal ausente é preenchido com um valor codificado em base64 gerado aleatoriamente. Por exemplo:``` ["CMXZyamk3ZHNjdGsyaQ==", 3249, 591]

root@kitploit:~
Uma vez concluída a construção da impressão digital, ela é serializada em uma string e criptografada usando a chave de criptografia carregada do campo de âncora (índice 18). O resultado criptografado é então armazenado no campo de índice `16` do payload `/reload`.

## Sinais da VM
A seguir estão os valores do navegador obtidos pela VM interna do reCAPTCHA, juntamente com a chave de sinal. Alguns valores não são exibidos na impressão digital de exemplo porque a VM extrai apenas determinados valores do bytecode de configuração. Portanto, outros valores serão exibidos. Para mais detalhes, consulte [aqui](https://github.com/elyelysiox/recaptcha-vm)

Formato do Sinal Base:```
[
  null,
  collectorElapsed,
  encryptElapsed,
  value
]

Onde collectorElapsed significa quanto tempo (ms) o coletor levou para obter o valor E encryptElapsed significa quanto tempo (ms) levou para criptografar o valor. Esses tempos são medidos durante a execução da VM.

Estrutura```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`)
  - Valor: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...`
  - Descrição: User-Agent completo do navegador

- **Key 727** (`array`)
  - Valor: `[]`
  - Descrição: Blocos de Preços de Produtos, contém preços de produtos comerciais no site, eles podem aparecer em sites de marketplace como Amazon, eBay, AliExpress, etc, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/findProductPricesBlock.js)

- **Key 150** (`array`)
  - Valor: `[\"Join And Get Free Trial!\",\"\",\"Captcha Solving Service\",\"Prod...`
  - Descrição: Links extraídos dos elementos `<a>` do site, a VM raramente extrai esses valores

- **Key 545** (`boolean`)
  - Valor: `false`
  - Descrição: `navigator.webdriver`

- **Key 370** (`integer`)
  - Valor: `0`
  - Descrição: Máximo de Pontos de Toque do Dispositivo `navigator.maxTouchPoints`

- **Key 779** (`array`)
  - Valor: `[null,null,null,null,"false"]`
  - Descrição: Extrai dados dos campos de envio/cobrança, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/formFieldScrape.js)
  
    `postal|postalcode|postalcode|postal_code|zip` → procura o campo de código postal
    
    `ship|deliver` → seção de envio
    
    `billing|payment|credit` → seção de cobrança
    
    `country` → seletor de país
    
    `addr.*(match|equal)|(match|equal).*address` → caixa de seleção "same address"
    
    Lê o nome, id, autocomplete, className de cada elemento
    Três fases: entradas de texto, elementos SELECT, caixas de seleção

- **Key 659** (`array`)
  - Valor: `[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]`
  - Descrição: Contém dados dos elementos pressionados na página no formato `[[[count,timestamp]],[[hashedElem,tagType,type,autoComplete]],pressedCount,behaviorChecksum]`
 
    ### Tipo do Elemento
    
    | Tipo do Elemento | 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 |

    ### Algoritmo do Behavior CheckSum
    
    O behaviorChecksum é uma pontuação comportamental compacta derivada dos dados de interações do usuário coletados.
 
    Para cada interação:
    - O índice da interação é incrementado em um
    - O timestamp é combinado com o índice de interação ajustado
    - O hash do elemento é reduzido usando uma operação de módulo
    - O resultado é acumulado em uma pontuação contínua
   
    ---

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

    ### Exemplo

    ```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`)
  - Valor: `[[[0,0,979]],1,0]`
  - Descrição: Contém os movimentos de rolagem coletados durante a sessão da página
 
    ### Formato Base
    ```
    [ [ [ scrollX, scrollY, timestamp ] ], count, behaviorChecksum ]
    ```

- **Key 895** (`array`)
  - Valor: `[[[1,0]]]`
  - Descrição:` VisibilityStateEntry` rastreia o status de visibilidade da página, indicando se o usuário está atualmente visualizando a página ou navegou para fora dela, no formato `[[[isVisible, startTime]]]`

- **Key 1092** (`array`)
  - Valor: `[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]`
  - Descrição: Desempenho do reCAPTCHA, PerformanceNavigationTiming e PerformanceEventTiming, no formato `[vmStart,vmEnd,domContentLoadedEventEnd,loadEventEnd,firstUserInteractionTime]`

- **Key 41** (`array`)
  - Valor: `[[[1123,0,0]]]`
  - Descrição: ClearTimeout

- **Key 43** (`array`)
  - Valor: `[[[1123,0]]]`
  - Descrição: ClearTimeout

- **Key 549** (`array`)
  - Valor: `[0,null,null,null,null,null,null]`
  - Descrição: KeyboardEvent, teclas calculadas + timestamps

- **Key 352** (`array`)
  - Valor: `1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],...`
  - Descrição:
    A estrutura contém:

    - Temporização do movimento do mouse
    - Coordenadas do cursor
    - Durações do clique
    - Dimensões do elemento pressionado
    - Informações do tipo de ponteiro
    - Métricas de pressão
    - Distância percorrida pelo cursor
    - Estatísticas de temporização comportamental

    ### Formato Base:
    ```
    [
      eventsCount,
      mouseEvents,
      [
        coalescedEventsCount,
        averageInterEventDelay,
        timingVarianceScore
      ],
      [
        totalPoints,
        clickSequenceScore,
        totalCursorDistance,
        totalPoints
      ],
      0,
      0,
      behaviorChecksum
    ]
    ```
    
    ### Estrutura do Evento de Mouse:
    
    Cada entrada dentro de mouseEvents segue esta estrutura:
    
    ```
    [
      timestamp,
      clickDuration,
      clientX,
      clientY,
      [
        elementLeft,
        elementTop,
        elementWidth,
        elementHeight
      ],
      elementTagType,
      trackedElementIndex,
      pressure,
      pointerTravelDistance,
      pointerArea
    ]
    ```

    | Nome | Descrição |
    |---|---|
    | `timestamp` | Timestamp do evento relativo ao início do evento |
    | `clickDuration` | Duração entre `pointerdown` e `pointerup` |
    | `clientX` | ... |
    | `clientY` | ... |
    | `elementBounds` | Retângulo delimitador do elemento interagido |
    | `elementTagType` | Identificador codificado da tag DOM do elemento interagido |
    | `trackedElementIndex` | Identificador interno do elemento DOM interagido do mapa de interação em tempo de execução |
    | `pressure` | Valor normalizado da pressão do ponteiro multiplicado por `100` |
    | `pointerTravelDistance` | Distância percorrida entre `pointerdown` e `pointerup` |
    | `pointerArea` | Área de contato calculada como `width * height` |

    ### Tipo da Tag do Elemento

    Isso é inicializado durante a execução da VM do reCAPTCHA

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

    ### Exemplo
    ```
    [
      18342,
      91,
      742,
      381,
      [700, 320, 120, 38],
      3,
      1,
      50,
      1.4,
      16
    ]
    ```
    
    Representa:
    
    - evento em `18.342s`
    - duração do clique de `91ms`
    - clique em `(742, 381)`
    - interação com um `BUTTON`
    - pressão do ponteiro `0.5` (50)
    - leve movimento do cursor durante o clique
    - área de contato do ponteiro de `16`
   
    ### Algoritmo do Behavior CheckSum
 
    Para cada evento de mouse:

    - A duração do clique é amplificada
    - O resultado é combinado com o timestamp do evento
    - As coordenadas do cursor e as dimensões do elemento são misturadas
    - Uma proporção ponderada é calculada
    - A proporção é arredondada e acumulada
    
    Depois que todos os eventos são processados:
    
    - A pontuação acumulada é combinada com a distância total do cursor
    - O resultado é normalizado usando o número de pontos coletados
    - Uma transformação logarítmica é aplicada
    - Estatísticas adicionais de movimento são incorporadas
    - O valor final é reduzido usando uma operação de módulo
    - O resultado é arredondado em uma pequena pontuação inteira
    
    ---
    
    ```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);
    }
    ```

    ### Exemplo

    ```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`)
  - Valor: `""`
  - Descrição: Análise do Total de Preços do Site Coletado ($) com uma regex ``(?i)total[\S\s]{0,20}?(?:(?:(?:USD|\$)\s*)?[\d\.,]+\s*(?:USD|\$)|(?:USD|\$)\s*[\d\.,]+)``, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/websitePricesTotal.js)

- **Key 1278** (`integer`)
  - Valor: `229.6`
  - Descrição: Divisão por 10 da temporização atual do runtime `Math.trunc(performance.now()) / 10`
    
- **Key 1422** (`boolean`)
  - Valor: `false`
  - Descrição: Analisa se há campos OTP/2FA no site, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/parseOTPFields.js)

- **Key 614** (`array`)
  - Valor: `[1,0,0,Infinity]`
  - Descrição: Informações da bateria do dispositivo, no formato `[level,isCharging,chargingTime,dischargingTime]`

- **Key 2033** (`array`)
  - Valor: `["0",-1,-1,999]`
  - Descrição: Alguns valores constantes da VM e a temporização do runtime da VM

- **Key 1313** (`array`)
  - Valor: `["undefined",3]`
  - Descrição: Verificações de Android e Chrome, `[typeof window.android, Object.keys(window.chrome).length]`

- **Key 1994** (`array`)
  - Valor: `[2,4,53324367238]`
  - Descrição: `[navigator.hardwareConcurrency, navigator.deviceMemory, navigator.storage.estimate().qouta]`

- **Key 1310** (`array`)
  - Valor: `["Google Inc. (Intel Inc.)","ANGLE (Intel Inc.,...`
  - Descrição: WebGL Renderer, Vendor e Total de Extensões, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/webglSignals.js)


- **Key 291** (`array`)
  - Valor: `[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,...`
  - Descrição: Chave com hash de Protótipos específicos de objetos do navegador, como `SpeechSynthesisEvent`, `NetworkInformation`, `HTMLElement`, etc, [Exemplo](https://github.com/elyelysiox/recaptcha/blob/main/hashBrowserProtos.js)

## Payload da Requisição Reload

Esses dados são serializados usando protobuf (Protocol Buffers), um método eficiente e neutro para serializar dados estruturados, desenvolvido pelo 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,
]

Componentes

Modos de Desafio

ValorDescrição
qDesafio reCAPTCHA V3
fiDesafio reCAPTCHA V2/Invisible
aDesafio de áudio

Payload de Telemetria (Idx 20)

Para decodificar:```javascript atob("W1tbMywwLDgyOV0sWzEs...") // → [[[3,0,829],[1,42,863]],[[2,727,1341.300000011921]...

root@kitploit:~
O payload contém:

- Informações de Resource Timing
- Cronometragem de desempenho de tarefas longas
- Deltas de execução da VM do reCAPTCHA
- URLs de scripts do site
- Estatísticas de coleta de objetos do navegador

### Estrutura Base```js
[
  [recaptchaResources],
  [tasksTiming],
  [
      null,
      null,
      null,
      idleTimeoutDelta,
      deltaTiming,
      0,
      0,
      0,
  ],
  websiteScriptsUrls,
  [collectionElapsed, browserObjectsLength]
]

Formato de Temporização de Tarefa Longa```js

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

root@kitploit:~
### Formato de Resource Timing do reCAPTCHA```js
[
   resourceType,
   duration,
   startTime
]
Recurso

Contadores de Eventos (Idx 25)

Este campo contém contadores codificados em Base64 para eventos de interação do navegador coletados durante a execução

Exemplo decodificado:```js [ [ [5006, 43], [64607, 1], [45464, 1], [35837, 1] ] ]

root@kitploit:~
### Estrutura do Contador de Eventos```js
[
  [
    [eventType, count]
  ]
]

Hashes de Eventos Conhecidos

Estrutura da Resposta```js

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

root@kitploit:~
## Descrições dos Campos

| Índice | Nome | Descrição |
|---|---|---|
| `0` | `rresp` | Identificador do tipo de resposta retornado pelo endpoint de reload |
| `1` | `responseToken` | Token de resposta do reCAPTCHA |
| `3` | `tokenExpiration` | Tempo de vida do token em segundos antes da expiração |
| `4` | `pmeta` | Bloco de metadados do desafio contendo informações sobre o tipo de CAPTCHA, categoria e layout da grade |
| `5` | `challengeType` | Tipo de desafio CAPTCHA |
| `8` | `usagePatternToken` | Padrões de uso, armazenados em `window.sessionStorage` e reutilizados em futuras requisições `/reload` |
| `9` | `challengeImageToken` | Token usado para recuperar o payload de imagem do CAPTCHA do endpoint `/payload` |
| `12` | `humanVerificationToken` | Token de identificação humana associado ao estado do Google reCAPTCHA e aos cookies do navegador |
| `14` | `captchaSessionToken` | Token de sessão interno |
| `15` | `bftToken` | ... |

---

### Estrutura do `pmeta`

Exemplo:```js
[
    "pmeta",
    [
        "/m/013xlm",
        null,
        3,
        3,
        3,
        null,
        "Tractor"
    ],
    null,
    [1]
]

pmeta[1] Values


Challenge Types


Challenge Image Retrieval

O valor em Idx 9 (challengeImageToken) é usado para recuperar a imagem do CAPTCHA:```txt https://www.google.com/recaptcha//payload ?p= &k=

root@kitploit:~
### Identificadores de Categoria

| ID | Categoria |
|---|---|
| `/m/0pg52` | Táxi |
| `/m/01bjv` | Ônibus |
| `/m/02yvhj` | Ônibus escolar |
| `/m/04_sv` | Motocicleta |
| `/m/013xlm` | Trator |
| `/m/01jk_4` | Chaminé |
| `/m/014xcs` | Faixa de pedestres |
| `/m/015qff` | Semáforo |
| `/m/0199g` | Bicicleta |
| `/m/015qbp` | Parquímetro |
| `/m/0k4j` | Carro |
| `/m/015kr` | Ponte |
| `/m/019jd` | Barco |
| `/m/0cdl1` | Palmeira |
| `/m/09d_r` | Montanha / colina |
| `/m/01pns0` | Hidrante |
| `/m/01lynh` | Escadas |

## Payload de Solicitação UserVerify
O payload `/userverify` é enviado após o usuário concluir um desafio de imagem do reCAPTCHA v2

# Estrutura do Payload```
v: hsFBb1u5wWWWkWP4in1ua2cQ
c: 03AFcWeA5RIHz5mI2COQqTcLjdrC7FiPpdfkX-hB-B2iFenI...
response: eyJyZXNwb25zZSI6WzMsMSw0LDksMCwxMSwxMCwxMywxNF0....
t: 24521
ct: 24521
ch: -4007845
oc: 0ZpqzzPgYKEEaN0xpfo3v_voeVUySZK3Ktf_fLVRdhnu3yeTy4BhO...
pm: 51bGwsbnVsbCxbbnVsbCxudWxsLG51bGwsWzEwLDQuMjcwMDAwMD....

Componentes

Payload de response

Representa os índices/posições dos quadrados selecionados pelo usuário na grade

O payload é posteriormente codificado como JWT antes do envio


Exemplo de Grade 3×3

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

root@kitploit:~
Exemplo de payload:```json
{
  "response": [2, 3, 6]
}

Exemplo de grade 4×4 de MultiCaptcha

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

root@kitploit:~
Exemplo de payload:```json
{
  "response": [2, 3, 6, 14]
}

Campo e

O payload response também pode incluir um campo e:```json { "response": [2, 3, 6, 14], "e": "bxCoiXVt49I7CTS_tNlVbGg" }

root@kitploit:~
Este campo contém metadados de interação criptografados relacionados a ações de botão de CAPTCHA, tais como:

- `Verify`
- `Next`
- `Skip`

### Estrutura Interna de `e`

Após a descriptografia, a estrutura se assemelha a:```txt
[[["9ffd9672"]]]

Cada valor representa um identificador com hash para a classe/ação do botão rc-button-default

O hash é:

  • Baseado em SHA-256
  • Truncado para 8 caracteres

Sequências de interação mais longas podem ter a seguinte aparência:```txt [ [ ["9ffd9672"], ["9ffd9672"], ["9ffd9672"], ["9ffd9672"] ] ]

root@kitploit:~
### `oc` — Sinais de VM Criptografados

Usa o mesmo algoritmo de criptografia do campo `idx 16` do payload da requisição `/reload`, com a chave de criptografia carregada no anchor (índice 31) `1777752103288`

### `pm` — Payload de Telemetria

O campo `pm` contém uma estrutura de telemetria codificada em Base64 semelhante ao payload de telemetria usado em `/reload`.

 
## Anti-debugging/Adulteração
- ***Tag de Integridade Baseada em Symbol***
    o reCAPTCHA define uma chave Symbol `Symbol(jas)` em todo array e objeto com um valor numérico usado como verificação de integridade. Como Symbols não são enumeráveis e invisíveis para operações de clonagem padrão (como JSON.stringify), qualquer tentativa de substituir ou clonar essas estruturas perde a tag, o que o reCAPTCHA detecta como adulteração

    ![tamp](https://raw.githubusercontent.com/elyelysiox/recaptcha/main/photos/849230834092888898.png)

- ***Captura de Variáveis por Closure***
    Alguns valores são intencionalmente escopados em uma função externa e consumidos apenas dentro de callbacks ou closures aninhados; a variável nunca existe no mesmo escopo onde é usada

- ***Verificações de Temporização***
    o reCAPTCHA incorpora mecanismos de detecção de depuração em tempo de execução. Se ele detectar que o código está sendo analisado por um depurador, ele reinicia a sessão de depuração, fazendo com que o estado e o contexto de execução sejam perdidos

- ***Aba de Origem do Crash***

    https://github.com/user-attachments/assets/4ae3bf68-5ae7-4adc-a0b9-36cc11b64998
  
    Esse bug ocorre em navegadores que usam Chromium. Existem vários bugs que fazem o navegador ou as ferramentas de desenvolvedor fecharem inesperadamente, como o mostrado aqui:
    
    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
    
    Portanto, um desses bugs é provavelmente acionado quando o timeout ocorre, já que não seria algo que aconteceria no fluxo de um usuário real

## reCAPTCHA Botguard

Embora o BotGuard tenha sido removido pelo Google, explicarei um pouco sobre como ele funciona internamente para quem tem interesse em saber como é, e como ele é diferente de outros tipos de botguard

Primeiro, o processo de geração de tokens: a VM gera tokens para erros persistentes durante a execução. Esses erros podem ser devidos a desvios de offset do bytecode, registradores de VM ausentes, estado incorreto da VM e integridade de fluxo de controle ruim. Esses erros são capturados pelo dispatcher, que chama uma função que grava bytes para o token.

A VM usa ARX Cipher, um algoritmo criado pela NSA em 2013, semelhante ao Speck para criptografar dados. Ele também é usado em todo o Google BotGuard. O algoritmo muda a cada versão, assim como a constante (3990), a ordem das operações e as rodadas. Fica assim:```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];
}

Escritor de Bytes e Criptografia

A função principal de criptografia tem dois modos: criptografia e sem criptografia. O modo de criptografia usa ARX Cipher, Bitwise + XOR para criptografar os dados e defini-los em um buffer. Existem 4 tipos de buffers:

  • buffer principal 180
  • buffer Entropy Pad 353
  • buffer de erro 304
  • buffer PoE (Proof of Execution) 243 (não usado neste tipo de botguard).

O modo sem criptografia apenas define bytes já criptografados no buffer```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:~
E esta é a função que lida com erros e chama o escritor de bytes```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;
        }
    }
}

No final da execução, a VM chama a função principal que prepara o payload com esses buffers e gera o token, que é uma assinatura. Ao contrário de outras VMs BotGuard, esta VM não possui um sistema de fingerprinting, Google Botguard, nem executa essas emissões de erro + escrita de bytes, e é muito mais simples e fácil de realizar engenharia reversa.

Disclaimer

Este repositório é exclusivamente para fins educacionais e de pesquisa. O código, as técnicas e os conceitos aqui apresentados destinam-se ao estudo acadêmico e à compreensão dos tópicos abordados.

Baixar ferramenta
yM5Us/j/fn6EDgtmPlP4Pxj605nMJN9dRYHyy5Mn
  • Com hash: true

  • Descrição: Impressão digital (fingerprint) de filtro Bloom em base64 de 40 caracteres de todos os nós <HEAD>. Percorre cada elemento filho coletando nomes de tags, atributos e conteúdo de texto, serializados e processados por um hash djb2.

    Cada digest é alimentado em um BitHash(240 bits, 7 rounds, max 25 nodes) que define bits em uma grade 40×6 e depois codifica cada segmento de 6 bits como um caractere base64. As próprias tags de script do reCAPTCHA são excluídas por meio de uma regex dinâmica no atributo src.

  • Idx 17 (integer)

    • Valor: 2
    • Com hash: false
    • Descrição: Verifica se há acesso para armazenar/ler cookies de terceiros, Exemplo
  • Idx 18 (string)

    • Valor: a2hyNTFuNDI4NnA3
    • Com hash: false
    • Descrição: Valor gerado aleatoriamente codificado em Base64
  • Idx 27 (string)

    • Valor: location.origin
    • Com hash: false
    • Descrição: URL do site.
  • Idx 28 (boolean)

    • Valor: false
    • Com hash: false
    • Descrição: window.parent != window ? true : window.frameElement != null ? true : false
  • Idx 29 (string)

    • Valor: e2a3cd70
    • Com hash: true
    • Descrição: Corpo da função grecaptcha.execute com hash SHA-256, Exemplo
  • Idx 30 (integer)

    • Valor: 0
    • Com hash: false
    • Descrição: O índice do script que contém o Script do reCAPTCHA https://www.gstatic.com/recaptcha/releases/<version>/, Exemplo
  • Idx 31 (string)

    • Valor: AAgkAQI0SB
    • Com hash: true
    • Descrição: Chaves de document.cookie com hash, Exemplo
  • Idx 32 (string)

    • Valor: ""
    • Com hash: false
    • Descrição: URL de referência (referrer) document.referrer.
  • Idx 33 (integer)

    • Valor: 2

    • Com hash: false

    • Descrição: Elemento da caixa do reCAPTCHA onde a renderização é feita.

      root@kitploit:~
      // like grecaptcha.execute('.grecaptcha') -> this div
      // Basically, it returns a number or the depth or level of that div in the document.
      
      // Example: html > body > main > form > fieldset > div.recaptcha.form-field
      // 5 4 3 2 1 0
      // out = 5
      
      nM = document.getElementsByClassName('grecaptcha-badge')[0] // or document.getElementsByClassName('g-recaptcha')[0] v2
      let count = 0;
      for (; nM = nM.parentElement || null;) {
        count++;
      }
      
      const result = count;
      
  • Idx 34 (string)

    • Valor: AAAAAAAAAA
    • Com hash: true
    • Descrição: Fez hash de todos os nomes de atributos <INPUT>, Exemplo
  • Idx 35 (string)

    • Valor: 0,DIV,f0c7414e
    • Com hash: true
    • Descrição: document.activeElement Analisa se é um elemento de compra usando uma regex /buy|pay|place|order|donate|purchase/i com textContent, classNames e id, Exemplo
  • Idx 36 (string)

    • Valor: h3, h2 ou http/1.1
    • Com hash: false
    • Descrição: nextHopProtocol do desempenho de navegação performance.getEntriesByType("navigation")[0].nextHopProtocol
  • Idx 37 (integer)

    • Valor: -1
    • Com hash: false
    • Descrição: performance.timing.unloadEventStart
  • Idx 38 (integer)

    • Valor: 96
    • Com hash: false
    • Descrição: Consulta DNS performance.timing.domainLookupStart - performance.timing.domainLookupEnd
  • Idx 39 (integer)

    • Valor: 0
    • Com hash: false
    • Descrição: Tipo de navegação performance.navigation.type
  • Idx 40 (integer)

    • Valor: 0
    • Com hash: false
    • Descrição: Última posição de rolagem Y window.scrollY ou document.defaultView.pageYOffset
  • Idx 41 (string)

    • Valor: DIV,a08cd360
    • Com hash: true
    • Descrição: O elemento :hover onde o mouse estava posicionado naquele mesmo momento, obtém o último elemento e aplica hash em tagName, classNames e id, Exemplo
  • Idx 42 (string)

    • Valor: 9,e3b0c442
    • Com hash: true
    • Descrição: Aplicou hash a um script de texto aleatório com SHA-256 mais o índice, Exemplo
  • Idx 44 (string)

    • Valor: 2v591z63wq
    • Com hash: true
    • Descrição: Elemento :hover, document.activeElement, todos os elementos <INPUT> com hash, location.url, window.scrollY, Exemplo:
    • 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)

    • Valor: 4
    • Com hash: false
    • Descrição: Comprimento de window.history.
  • Idx 46 (string)

    • Valor: https://static.kogstatic.com/0000/34c...
    • Com hash: false
    • Descrição: Ocorreu um erro em um script na página e o line:column onde aconteceu.
  • Idx 47 (integer)

    • Valor: 0
    • Com hash: false
    • Descrição: Retorna o comprimento do texto atualmente selecionado na página pelo usuário window.getSelection().toString().length || 0
  • Idx 49 (string)

    • Valor: h2-0
    • Com hash: false
    • Descrição: Encontra a entrada de Performance Resource Timing para o script do reCAPTCHA, obtém seu nextHopProtocol e determina se sua duration é zero. Retorna o resultado no formato protocol-isZero, Exemplo
  • Idx 50 (array)

    • Valor: [1,0,null,1,1,["805b1z63wq"],"MWc2MzZwMnR0ZHNkMw==",0,null,[[1]]]

    • Com hash: true

    • Descrição: Contém comportamentos do usuário, elementos :hover com hash e um timeout que é incrementado cada vez que outro elemento :hover é coletado. Analisa ativações do usuário para acumular o número de vezes que o usuário interagiu ou ainda está presente na página, calculando (10 * IsActive + IsBeenActive)

      Formato Base:

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

    • Valor: [0]
    • Com hash: false
    • Descrição: Pesquisa em document.body.innerText por correspondências com as palavras "try again", "incorrect", "invalid" ou "declined" e retorna o número total de correspondências encontradas. Caso contrário, retorna 0, Exemplo
  • Idx 52 (integer)

    • Valor: 11
    • Com hash: false
    • Descrição: 10 * navigator.userActivation.isActive + navigator.userActivation.hasBeenActive
  • Idx 53 (integer)

    • Valor: 4

    • Com hash: false

    • Descrição: Pega a URL atual do site, converte-a em uma matriz de caracteres, trunca-a em 100 caracteres e a converte novamente em uma string, Exemplo

      Então é 5 se o comprimento dessa string truncada for par, ou 4 se for ímpar.

  • Idx 54 (boolean)

    • Valor: false
    • Com hash: false
    • Descrição: Indica se o documento está oculto do usuário, ou seja, se não está visível na tela, window.document.hidden
  • Idx 55 (array)

    • Valor: [[[1,"2v"],[1,"9z"],[1,"z8"],[1,"us"],[1,..
    • Com hash: false
    • Descrição: Ordenação dos códigos de sinais gerados pelos valores de fingerprint.
  • Idx 56 (string)

    • Valor: -1,-1
    • Com hash: false
    • Descrição: Verificações de window.opener, retorna "-1,-1" se for null, Exemplo
  • Idx 57 (string)

    • Valor: www.gstatic.com,_,static.kogstatic.com,www.google.com,www.googletagmanager.,...

    • Com hash: false

    • Descrição: Coleta os hosts do src de todos os elementos <SCRIPT> presentes em document.scripts, Exemplo

      Para cada <SCRIPT> Se o elemento tiver o atributo src (hasAttribute("src")), o valor de src é obtido e analisado com uma regex do tipo URI (nd), extraindo apenas o componente do host (grupo de captura 3 da regex).

      Se o <SCRIPT> não tiver um atributo src (é um script inline), o espaço reservado "_" é usado.

  • Idx 58 (string)

    • Valor: mapslitepromosdismissed1
    • Com hash: false
    • Descrição: Chave amostrada de window.localStorage.
  • Idx 59 (string)

    • Valor: ""
    • Com hash: false
    • Descrição: Nome do contexto de navegação de uma janela ou aba window.name
  • Idx 60 (string)

    • Valor: https://www.kogama.com,https://www.google.com,https://js.stripe.com
    • Com hash: false
    • Descrição: URLs para eventos de mensagem abertos, Exemplo
  • Idx 61 (array)

    • Valor: [0,"AAAAAAAAAA","AAAAAAAAAA"]
    • Com hash: true
    • Descrição: Hashes de nomes de atributos e tipos de elemento de destino registrados por MutationObserver, Exemplo
  • Idx 62 (string)

    • Valor: document.title
    • Com hash: false
    • Descrição: Título completo do site.
  • Idx 63 (array)

    • Valor: []

    • Com hash: false

    • Descrição: Extrai timestamps (números de 12 a 13 dígitos começando com 1[2-9], típicos de epoch millis ~2008-2099) dos valores de cookie, Exemplo

      Acumule os seguintes valores sobre todos os IDs encontrados: contagem, mínimo, máximo e média. O valor final é um array [count, min, max, avg]

  • Idx 64 (integer)

    • Valor: 55557
    • Com hash: false
    • Descrição: Tempo de execução (da âncora até o recarregamento).
  • Idx 65 (string)

    • Valor: sha384-3qc
    • Com hash: true
    • Descrição: Integridade do script do reCAPTHCA configurado em https://www.google.com/recaptcha/api.js?render= (truncado para 10 caracteres)
  • Idx 67 (array)

    • Valor: [screen.width, screen.height, screen.availHeight, window.innerWidth, window.innerHeight, window.outerHeight]
    • Com hash: false
    • Descrição: Resolução da tela, largura e altura da viewport do navegador e altura da janela do navegador.
  • Idx 68 (array)

    • Valor: [300,null,1777685870223]
    • Com hash: false
    • Descrição: Deslocamento de fuso horário e timestamp Unix atual [new Date().getTimezoneOffset(), null, Date.now()]
  • Idx 69 (string)

    • Valor: 09AKhCRwjrDFiHsrRA--o23-HB-eWqOtk_XQ-rLE1...
    • Com hash: false
    • Descrição: Um token de sessão usado para identificação humana, armazenado nos cookies do navegador e incrementa a pontuação se for válido.
  • Idx 70 (array)

    • Valor: [null,null,"","",null,"1l0fl"]

    • Com hash: false

    • Descrição: Extrai valores monetários totais (como Total: $50.00 ou Total 150.00 EUR), Exemplo

      de document.innerText pesquisando o símbolo ou código da moeda junto com o valor numérico usando a expressão regular:

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

      total → Pesquisa a palavra exata "total"

      [\S\s]{0,20}? → Pesquisa entre (0) e (20) caracteres intervenientes (como espaços, dois-pontos ou quebras de linha) antes de encontrar o número

      (((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR)) → Este é o bloco principal que captura o dinheiro e está dividido em duas opções separadas

  • Idx 71 (array)

    • Valor: [jsHeapSizeLimit,usedJSHeapSize,totalJSHeapSize]
    • Com hash: false
    • Descrição: Memória HEAP de desempenho do JavaScript.
  • Idx 72 (array)

    • Valor: [[["Google Chrome","147"],["Not.A/Brand",...

    • Com hash: false

    • Descrição: Array de dados do userAgent navigator.userAgentData, uma flag indicando se é mobile e a plataforma, Exemplo:

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

    • Valor: [[null,2,0,"Mozilla/5.0 (Windows NT 10.0;...
    • Com hash: false
    • Descrição: Sinais Criptografados da VM.
  • Idx 77 (integer)

    • Valor: null
    • Com hash: false
    • Descrição: Timestamp Unix, às vezes aparece.
  • Idx 78 (string)

    • Valor: ""
    • Com hash: false
    • Descrição: Cookie Google GA, pode aparecer se o site usa o Google Tag Manager.
  • ÍndiceValorDescrição
    0rreqIdentificador do tipo de requisição
    1U5VsmTDhJM1iO...Versão do reCAPTCHA
    203AFcWeA5Els3...Token de validação obtido do endpoint /anchor
    5-383788762Hash de todo o payload de fingerprint serializado, Amostra
    6qIndica o modo de desafio ou requisição que está sendo executado
    705APQrAobTCFG...Padrões de Uso, contendo histórico de uso e padrões de desafio resolvidos anteriormente. Pode aumentar significativamente a pontuação se for válido
    8submitAção específica do site que o usuário está executando na página no momento da verificação (por exemplo, signin, register)
    146LcAbwIqAAAA...Chave do site
    160XA4cHhALxgM...Payload de fingerprint serializado criptografado com a chave de criptografia do anchor (índice 18) 1777669303203
    20tbMywxNTQsOD...Estrutura de telemetria codificada em Base64 contendo deltas de tempo da VM, tempos de recursos, estatísticas de objetos do navegador coletadas e URLs de scripts do site
    210aAPQrAobqME...Token associado a um CAPTCHA resolvido anteriormente. Usado para continuidade de sessão e correlação de confiança
    22BDAAYAIAGEcA...Hash de todas as chaves de objetos do navegador
    25W1tbNTAwNiw...Contadores codificados em Base64 para eventos de interação do usuário, como movimento do mouse, cliques, teclado e mudanças de foco
    qrResposta rápida (novo)
    Tipo
    recaptcha/api.js3
    recaptcha/releases/<version>1
    https://www.google.com/recaptcha/api2/anchor2
    https://www.google.com/recaptcha/api2/bframe4
    HashTipo de Evento
    5006pointermove
    64607pointerdown
    45464pointerup
    31617keydown
    37178keyup
    35837focusin
    PositionValueDescription
    0/m/013xlmIdentificador interno de categoria para a classe do objeto alvo
    23Número de colunas da grade
    33Número de linhas da grade
    5nullCampo de metadados reservado ou opcional
    6"Tractor"Rótulo de texto
    TypeDescription
    imageselectCAPTCHA padrão de seleção de imagem
    tileselectDesafio de imagem dinâmica baseado em blocos
    dynamicDesafio dinâmico onde os blocos são recarregados após a seleção
    multicaptchaDesafio CAPTCHA de múltiplas etapas
    audioDesafio de acessibilidade baseado em áudio
    nocaptchaFluxo de verificação apenas com caixa de seleção
    doscaptchaNegar CAPTCHA se houver abuso
    CampoNomeDescrição
    vrecaptchaVersionVersão do reCAPTCHA
    cchallengeTokenToken de estado do desafio retornado de /replaceimage ou de uma solicitação /userverify anterior
    responsePayload codificado contendo os índices dos quadrados selecionados e metadados adicionais de interação
    tchallengeElapsedTempo decorrido desde que o desafio foi inicialmente carregado
    ctcompletionTimeTempo total gasto pelo usuário para resolver e enviar o CAPTCHA
    chocHashHash de todo o payload serializado oc, Exemplo
    ocencryptedVmSignalsSinais criptografados coletados da VM do reCAPTCHA, veja aqui.
    pmtelemetryPayloadEstrutura de telemetria codificada em Base64 contendo deltas de tempo da VM, tempos de recursos, estatísticas de objetos do navegador coletadas e metadados de scripts do site