Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
recaptcha — Documentazione e reverse engineering di reCAPTCHA | Kitploit
Strumenti/GitHubGitHub/elyelysiox/recaptcha
Analisi StaticaAnalisi Dinamica del Codice (DAST)Reverse EngineeringSicurezza WebAnti-BotBypass CAPTCHA
GitHubelyelysiox/recaptcha

recaptcha

Documentazione e reverse engineering di reCAPTCHA

Vedi Repository
227381 mese faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Descrizione

Questo repository contiene un'analisi tecnica dell'antibot di Google (reCAPTCHA) concentrandosi su:

  • Struttura e valori del payload
  • Tecniche di fingerprinting
  • Tecniche di offuscamento
  • Tecniche anti-debug/anti-manomissione
  • Macchine virtuali

Contatti

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

Tecniche di offuscamento

reCAPTCHA è uno dei sistemi anti-bot con le tecniche di offuscamento più sofisticate, impiegando una serie di trasformazioni che rendono il codice meno leggibile e più difficile da reverse engineering. La maggior parte degli offuscamenti può essere facilmente manipolata utilizzando l'Abstract Syntax Tree (AST), ma alcuni vengono elaborati a runtime, rendendo l'AST inutile in questo caso. Il polimorfismo viene anche applicato al codice per cambiarne la struttura in ogni versione dello script. Ad esempio, il codice non esegue l'azione direttamente. Invece, utilizza oggetti o funzioni che cambiano forma.

  • Sequence Expressions Il codice viene appiattito convertendo ogni blocco di istruzioni in un'espressione continua separata da virgole; può apparire in istruzioni if, argomenti di funzioni e persino all'interno di oggetti. seq

  • Aritmetica booleana mista Intreccia operazioni aritmetiche (addizione, sottrazione, moltiplicazione) con operazioni bitwise (AND, OR, XOR, NOT) per nascondere la logica originale, ad esempio -2 * ~(h & H) + -2 + (h ^ H)

  • Tabella di funzioni indiretta Ogni funzione è costruita all'interno di una tabella e viene chiamata usando il suo indice, come functions[index](https://github.com/elyelysiox/recaptcha/blob/HEAD/args)

  • Array di costanti inline Un array letterale locale viene assegnato inline, a metà espressione; l'array raggruppa costanti (numeri, stringhe) che vengono riutilizzate in tutto il corpo della funzione tramite accesso per indice.

    root@kitploit:~
    // b = [14, 1, "call"] assegnato inline all'interno di un'espressione sequenziale
    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
    }
    
  • Multiplexing di funzioni Più funzioni logicamente distinte vengono unite in una sola, utilizzando un parametro numerico come selettore di blocco. Il blocco attivo viene determinato valutando il parametro rispetto a condizioni bitwise. I chiamanti passano un letterale numerico come selettore.

    root@kitploit:~
    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // blocco 1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // logica di conversione del valore in stringa
        }
    
        // blocco 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;
    }
    
  • Ramificazione con operatori logici Sostituisce i blocchi if e if/else con la valutazione short-circuit degli operatori logici, convertendo il flusso di controllo in espressioni. Combinato con le sequence expressions, più rami appaiono come un'unica espressione continua separata da virgole.

    root@kitploit:~
    // if (a) { blocco }
    a && (blocco)
    
    // if (!a) { blocco }
    a || (blocco)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // combinato con CFF e 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), ...)),
    
  • Costanti di metodi nativi bind Lega i metodi nativi del browser ai loro ricevitori originali, memorizzandoli come costanti per prevenire manomissioni.

    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)
    
  • Codice morto Blocchi di codice inaccessibili o inutilizzati vengono iniettati in tutto il file, aumentandone le dimensioni a oltre 60.000 righe; questo rende difficile l'analisi statica e il reverse engineering basato su LLM.

  • Appiattimento del flusso di controllo (CFF) Trasforma ogni parte del codice (dichiarazioni e cicli) in una macchina a stati piatta. Nasconde la logica di esecuzione originale instradando tutti i blocchi di codice attraverso un blocco "dispatcher" centrale.

    I dispatcher possono cambiare forma; alcuni hanno 2-3 variabili di stato e il tipo di ciclo/condizione cambia. Appaiono così:

    cff1

    Questo è un CFF con 2 variabili di stato: una gestisce il blocco catch e l'altra il blocco try.

  • Pool di stringhe crittate Tutti i letterali stringa (API DOM, proprietà del browser, valori CSS, messaggi di errore, ecc.) sono crittati in un unico enorme pool di stringhe. Una funzione di decifratura utilizza un seed e un cifrario XOR basato su LCG per estrarre ogni stringa a runtime.

    Ci sono oltre 1990 siti di chiamata sparsi nel codice; la funzione di decifratura utilizza una chiave corrente che accumula i codepoint decodificati, rendendo ogni carattere dipendente da tutti i precedenti.

    root@kitploit:~
    X = function(J, b, P, F, U) {
        U = ["codePointAt", 127, "pool crittato di caratteri"];
        for (F = (P = 0, b = "", l); P < Q; P++)
            J = (U[2][U[0]](c + P) ^ F) & U[1],  // XOR con chiave corrente
            b += String.fromCodePoint(J),
            F += J; // accumula chiave
        return G = b;
    }
    
    // i siti di chiamata passano un seed per individuare e decifrare ogni stringa
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • Iteratore di valori stateful reCAPTCHA utilizza una funzione stateful che restituisce una sequenza di oggetti runtime e valori (come window, document.body, costanti numeriche) in un ordine fisso; ogni chiamata fa avanzare un cursore interno. Chiamarlo fuori sequenza o troppe volte corrompe tutte le letture successive. Un meccanismo di timeout invalida lo stato dopo un intervallo fisso, restituendo null per qualsiasi lettura tardiva.

    root@kitploit:~
    // chiamate sequenziali restituiscono valori diversi:
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (timeout scaduto)
    
    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  
    
    
  • Tabella di funzioni calcolate Simile a Tabella di funzioni indiretta, ma qui l'indice della funzione da ottenere viene calcolato a runtime con un seed, usando XOR e Modulo.

    root@kitploit:~
    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mN è la tabella delle funzioni (50+ funzioni)
    
    root@kitploit:~
    q[29](5, 6977)   // seed=6977  → l'indice risolve nella funzione in mN[X]
    q[29](53, 6187)  // seed=6187  → indice diverso, funzione diversa
    

    computed

  • Crittografia runtime dei valori Alcuni valori (parametri di configurazione del captcha, parametri dell'ancora, ecc.) non vengono mai memorizzati in testo chiaro; vengono crittati immediatamente dopo la raccolta e decifrati solo al momento dell'uso. Hanno un prefisso B all'inizio.

    hiddenv

  • Offuscamento del flusso di controllo asincrono La logica sincrona viene convertita in macchine a stati basate su generatori racchiuse in catene ricorsive di Promise. Tracciare qualsiasi valore tramite il debugger costringe a passare attraverso più gestori asincroni, perdendo il contesto di esecuzione originale ad ogni confine .then().

Payload/Risposta dell'Ancora

Struttura del Payload

Componenti per inizializzare reCAPTCHA``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

root@kitploit:~
### Response

La risposta contiene:
- Design della finestra iframe del CAPTCHA
- Token anchor utilizzato per la convalida del payload (/reload)
- La configurazione principale per l'inizializzazione, eseguita nel metodo `recaptcha.anchor.Main.init` per riceverla in recaptcha_en.js

### Struttura:

Nota: Recaptcha BotGuard è stato rimosso il `04/01/2026`, puoi vedere alcuni esempi [qui](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
]

Impronta digitale

I valori ​​si basano sui valori decifrati provenienti dalla prima impronta digitale di esempio, guarda qui

Ogni sottocampo dei valori dell'impronta digitale ha un formato base:

[value, key, elapsed]

Dove key è la chiave di crittografia, e elapsed è il tempo impiegato dal collector per ottenere e crittografare il valore. Questo permette a reCAPTCHA di rilevare:

  • Esecuzione eccessivamente veloce
  • Hook
  • Breakpoint e sandboxing

Ordine di esecuzione del Collector

Il sistema utilizza uno scheduler 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:~
Questo rappresenta:

- Ordine di esecuzione
- Pipeline del collettore
- Sequenza di generazione del segnale

### Codici dei segnali delle impronte digitali e derivazione delle chiavi
Trasforma i segnali delle impronte digitali in chiavi di crittografia deterministiche attraverso una pipeline di derivazione a più stadi

Ogni valore dell'impronta digitale è:

- Normalizzato
- Codificato in un codice segnale compatto
- Convertito in una chiave di crittografia numerica
- Crittografato utilizzando la chiave derivata

Il processo è deterministico, il che significa che lo stesso valore di input genera sempre lo stesso codice segnale e la stessa chiave di crittografia```
Raw Value
   ↓
Signal Code Derivation
   ↓
Compact Signal Code
   ↓
Numeric Key Derivation
   ↓
Encryption Key
   ↓
Value Encryption

Esempio

Segnale di ingresso``` "BUTTON,195a81c9"

root@kitploit:~
***Step 1 - Derivare il Codice del Segnale***```javascript
deriveSignalCode("BUTTON,195a81c9")
// → "wg"

Il codice del segnale generato è un identificatore deterministico compatto per il valore originale.

Passaggio 2 - Derivare la Chiave Numerica```javascript deriveKey("wg") // → 3792

root@kitploit:~
Il codice del segnale viene trasformato in una chiave di crittografia numerica.

***Passaggio 3 — Crittografa il valore***```javascript
encryptValueWithKey(3792, "wgia1z9pwq")
// → "bYVbh6BUsE_5pLA"

Il valore successivo verrà crittografato con la chiave derivata, seguendo l'ordine del collettore.

Struttura aggregata delle impronte digitali

Tutti i codici di segnale generati vengono aggregati in una struttura serializzata compatta.

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

Segnali

  • Idx 4 (string)

    • Valore: 3ccb

    • Hashato: true

    • Descrizione: Genera una chiave HMAC da window.localStorage.getItem("rc::a") + "6d" convertito in byte, calcola HMAC-SHA256(siteKey) con quella chiave e restituisce i primi 4 caratteri esadecimali del risultato.

      Il valore di rc::a è un base64 generato casualmente.

  • Idx 5 (integer)

    • Valore: window.localStorage.length * 2
    • Hashato: false
    • Descrizione:window.localStorage lunghezza moltiplicata per 2
  • Idx 16 (string)

    • Valore:


Alcuni segnali reCAPTCHA potrebbero non essere disponibili o non essere raccolti (a causa di timeout legati al debugging). In tali casi, il segnale mancante viene sostituito con un valore codificato in base64 generato casualmente. Ad esempio:``` ["CMXZyamk3ZHNjdGsyaQ==", 3249, 591]

root@kitploit:~
Una volta completata la costruzione dell'impronta, viene serializzata in una stringa e crittografata utilizzando la chiave di crittografia caricata dal campo anchor (indice 18). Il risultato crittografato viene poi memorizzato nel campo dell'indice `16` del payload `/reload`.

## Segnali VM
I seguenti sono i valori del browser ​​ottenuti dalla VM interna di reCAPTCHA, insieme alla chiave del segnale. Alcuni valori ​​non sono mostrati nell'esempio di impronta perché la VM estrae solo determinati valori dal bytecode di configurazione. Pertanto, verranno visualizzati altri valori. Per maggiori dettagli, vedere [qui](https://github.com/elyelysiox/recaptcha-vm)

Formato base del segnale:```
[
  null,
  collectorElapsed,
  encryptElapsed,
  value
]

Dove collectorElapsed indica quanto tempo (ms) ha impiegato il collector per ottenere il valore E encryptElapsed indica quanto tempo (ms) ha impiegato per crittografare il valore. Questi tempi sono misurati durante l'esecuzione della 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`)
  - Value: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...`
  - Descrizione: User-Agent completo del browser

- **Key 727** (`array`)
  - Value: `[]`
  - Descrizione: Blocchi di prezzi dei prodotti, contiene prezzi per prodotti commerciali sul sito web, questi possono apparire su marketplace come Amazon, eBay, AliExpress, ecc., [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/findProductPricesBlock.js)

- **Key 150** (`array`)
  - Value: `[\"Join And Get Free Trial!\",\"\",\"Captcha Solving Service\",\"Prod...`
  - Descrizione: Link estratti dagli elementi `<a>` del sito web, la VM raramente estrae questi valori

- **Key 545** (`boolean`)
  - Value: `false`
  - Descrizione: `navigator.webdriver`

- **Key 370** (`integer`)
  - Value: `0`
  - Descrizione: Punti di contatto massimi del dispositivo `navigator.maxTouchPoints`

- **Key 779** (`array`)
  - Value: `[null,null,null,null,"false"]`
  - Descrizione: Estrae dati dai campi di spedizione/fatturazione, [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/formFieldScrape.js)
  
    `postal|postalcode|postalcode|postal_code|zip` → cerca il campo del codice postale
    
    `ship|deliver` → sezione spedizione
    
    `billing|payment|credit` → sezione fatturazione
    
    `country` → selettore paese
    
    `addr.*(match|equal)|(match|equal).*address` → checkbox "stesso indirizzo"
    
    Legge name, id, autocomplete, className di ogni elemento
    Tre fasi: input di testo, istruzioni SELECT, checkbox

- **Key 659** (`array`)
  - Value: `[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]`
  - Descrizione: Contiene i dati degli elementi premuti sulla pagina nel formato `[[[count,timestamp]],[[hashedElem,tagType,type,autoComplete]],pressedCount,behaviorChecksum]`
 
    ### Tipo di elemento
    
    | Tipo di 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 Behavior CheckSum
    
    Il behaviorChecksum è un punteggio comportamentale compatto derivato dai dati di interazione dell'utente raccolti.
 
    Per ogni interazione:
    - L'indice di interazione viene incrementato di uno
    - Il timestamp viene combinato con l'indice di interazione aggiustato
    - L'hash dell'elemento viene ridotto usando un'operazione modulo
    - Il risultato viene accumulato in un punteggio progressivo
   
    ---

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

    ### Esempio

    ```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`)
  - Value: `[[[0,0,979]],1,0]`
  - Descrizione: Contiene i movimenti di scorrimento raccolti durante la sessione della pagina
 
    ### Formato base
    ```
    [ [ [ scrollX, scrollY, timestamp ] ], count, behaviorChecksum ]
    ```

- **Key 895** (`array`)
  - Value: `[[[1,0]]]`
  - Descrizione: `VisibilityStateEntry` tiene traccia dello stato di visibilità della pagina, indicando se l'utente sta visualizzando la pagina o se è uscito, nel formato `[[[isVisible, startTime]]]`

- **Key 1092** (`array`)
  - Value: `[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]`
  - Descrizione: reCAPTCHA Performance, PerformanceNavigationTiming e PerformanceEventTiming, nel formato `[vmStart,vmEnd,domContentLoadedEventEnd,loadEventEnd,firstUserInteractionTime]`

- **Key 41** (`array`)
  - Value: `[[[1123,0,0]]]`
  - Descrizione: ClearTimeout

- **Key 43** (`array`)
  - Value: `[[[1123,0]]]`
  - Descrizione: ClearTimeout

- **Key 549** (`array`)
  - Value: `[0,null,null,null,null,null,null]`
  - Descrizione: KeyboardEvent, tasti calcolati + timestamp

- **Key 352** (`array`)
  - Value: `1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],...`
  - Descrizione:
    La struttura contiene:

    - Tempi di movimento del mouse
    - Coordinate del cursore
    - Durate dei clic
    - Dimensioni dell'elemento premuto
    - Informazioni sul tipo di puntatore
    - Metriche di pressione
    - Distanza percorsa dal cursore
    - Statistiche temporali comportamentali

    ### Formato base:
    ```
    [
      eventsCount,
      mouseEvents,
      [
        coalescedEventsCount,
        averageInterEventDelay,
        timingVarianceScore
      ],
      [
        totalPoints,
        clickSequenceScore,
        totalCursorDistance,
        totalPoints
      ],
      0,
      0,
      behaviorChecksum
    ]
    ```
    
    ### Struttura dell'evento del mouse:
    
    Ogni voce all'interno di mouseEvents segue questa struttura:
    
    ```
    [
      timestamp,
      clickDuration,
      clientX,
      clientY,
      [
        elementLeft,
        elementTop,
        elementWidth,
        elementHeight
      ],
      elementTagType,
      trackedElementIndex,
      pressure,
      pointerTravelDistance,
      pointerArea
    ]
    ```

    | Nome | Descrizione |
    |---|---|
    | `timestamp` | Timestamp dell'evento relativo all'inizio dell'evento |
    | `clickDuration` | Durata tra `pointerdown` e `pointerup` |
    | `clientX` | ... |
    | `clientY` | ... |
    | `elementBounds` | Rettangolo di delimitazione dell'elemento interagito |
    | `elementTagType` | Identificatore codificato del tag DOM dell'elemento interagito |
    | `trackedElementIndex` | Identificatore interno dell'elemento DOM interagito dalla mappa di interazione runtime |
    | `pressure` | Valore di pressione del puntatore normalizzato moltiplicato per `100` |
    | `pointerTravelDistance` | Distanza percorsa tra `pointerdown` e `pointerup` |
    | `pointerArea` | Area di contatto calcolata come `width * height` |

    ### Tipo di elemento tag

    Viene inizializzato durante l'esecuzione della VM di 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 |

    ### Esempio
    ```
    [
      18342,
      91,
      742,
      381,
      [700, 320, 120, 38],
      3,
      1,
      50,
      1.4,
      16
    ]
    ```
    
    Rappresenta:
    
    - evento a `18.342s`
    - durata clic di `91ms`
    - clic a `(742, 381)`
    - interazione con un `BUTTON`
    - pressione del puntatore `0.5` (50)
    - leggero movimento del cursore durante il clic
    - area di contatto del puntatore di `16`
   
    ### Algoritmo Behavior CheckSum
 
    Per ogni evento del mouse:

    - La durata del clic viene amplificata
    - Il risultato viene combinato con il timestamp dell'evento
    - Le coordinate del cursore e le dimensioni dell'elemento vengono mescolate
    - Viene calcolato un rapporto ponderato
    - Il rapporto viene arrotondato e accumulato
    
    Dopo che tutti gli eventi sono stati elaborati:
    
    - Il punteggio accumulato viene combinato con la distanza totale del cursore
    - Il risultato viene normalizzato usando il numero di punti raccolti
    - Viene applicata una trasformazione logaritmica
    - Vengono incorporate statistiche di movimento aggiuntive
    - Il valore finale viene ridotto usando un'operazione modulo
    - Il risultato viene arrotondato a un piccolo punteggio intero
    
    ---
    
    ```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);
    }
    ```

    ### Esempio

    ```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`)
  - Value: `""`
  - Descrizione: Parsing del totale dei prezzi del sito web raccolti con un regex ``(?i)total[\S\s]{0,20}?(?:(?:(?:USD|\$)\s*)?[\d\.,]+\s*(?:USD|\$)|(?:USD|\$)\s*[\d\.,]+)``, [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/websitePricesTotal.js)

- **Key 1278** (`integer`)
  - Value: `229.6`
  - Descrizione: Divisione per 10 del timing di runtime corrente `Math.trunc(performance.now()) / 10`
    
- **Key 1422** (`boolean`)
  - Value: `false`
  - Descrizione: Analizza se ci sono campi OTP/2FA sul sito web, [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/parseOTPFields.js)

- **Key 614** (`array`)
  - Value: `[1,0,0,Infinity]`
  - Descrizione: Informazioni sulla batteria del dispositivo, nel formato `[level,isCharging,chargingTime,dischargingTime]`

- **Key 2033** (`array`)
  - Value: `["0",-1,-1,999]`
  - Descrizione: Alcuni valori costanti della VM e timing di runtime della VM

- **Key 1313** (`array`)
  - Value: `["undefined",3]`
  - Descrizione: Controlli Android, Chrome, `[typeof window.android, Object.keys(window.chrome).length]`

- **Key 1994** (`array`)
  - Value: `[2,4,53324367238]`
  - Descrizione: `[navigator.hardwareConcurrency, navigator.deviceMemory, navigator.storage.estimate().qouta]`

- **Key 1310** (`array`)
  - Value: `["Google Inc. (Intel Inc.)","ANGLE (Intel Inc.,...`
  - Descrizione: Renderer WebGL, Vendor e Estensioni Totali, [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/webglSignals.js)

- **Key 291** (`array`)
  - Value: `[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,...`
  - Descrizione: Chiave hash di specifici prototipi di oggetti del browser, come `SpeechSynthesisEvent`, `NetworkInformation`, `HTMLElement`, ecc., [Esempio](https://github.com/elyelysiox/recaptcha/blob/main/hashBrowserProtos.js)

## Payload della Richiesta di Ricarica

Questo dato è serializzato usando protobuf (Protocol Buffers), un metodo efficiente e neutro per serializzare dati strutturati, sviluppato da 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,
]

Componenti

Modalità di sfida

ValoreDescrizione
qSfida reCAPTCHA V3
fiSfida reCAPTCHA V2/Invisibile
aSfida audio

Carico utile di telemetria (Idx 20)

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

root@kitploit:~
Il payload contiene:

- Informazioni sui tempi delle risorse
- Tempistiche di performance dei long-task
- Delta di esecuzione della VM di reCAPTCHA
- URL degli script del sito web
- Statistiche di raccolta degli oggetti del browser

### Struttura di base```js
[
  [recaptchaResources],
  [tasksTiming],
  [
      null,
      null,
      null,
      idleTimeoutDelta,
      deltaTiming,
      0,
      0,
      0,
  ],
  websiteScriptsUrls,
  [collectionElapsed, browserObjectsLength]
]

Formato di temporizzazione delle attività lunghe```js

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

root@kitploit:~
### reCAPTCHA Resource Timing Format```js
[
   resourceType,
   duration,
   startTime
]
Resource

Contatori di eventi (Idx 25)

Questo campo contiene contatori codificati in Base64 per gli eventi di interazione del browser raccolti durante l'esecuzione

Esempio decodificato:```js [ [ [5006, 43], [64607, 1], [45464, 1], [35837, 1] ] ]

root@kitploit:~
### Struttura del Contatore di Eventi```js
[
  [
    [eventType, count]
  ]
]

Hash di Eventi Noti

Struttura della Risposta```js

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

root@kitploit:~
## Descrizioni dei campi

| Indice | Nome | Descrizione |
|---|---|---|
| `0` | `rresp` | Identificatore del tipo di risposta restituito dall'endpoint di ricarica |
| `1` | `responseToken` | Token di risposta reCAPTCHA |
| `3` | `tokenExpiration` | Durata del token in secondi prima della scadenza |
| `4` | `pmeta` | Blocco di metadati della sfida contenente informazioni sul tipo di CAPTCHA, categoria e disposizione della griglia |
| `5` | `challengeType` | Tipo di sfida CAPTCHA |
| `8` | `usagePatternToken` | Pattern di utilizzo, memorizzati in `window.sessionStorage` e riutilizzati in future richieste `/reload` |
| `9` | `challengeImageToken` | Token utilizzato per recuperare il payload dell'immagine CAPTCHA dall'endpoint `/payload` |
| `12` | `humanVerificationToken` | Token di identificazione umana associato allo stato di Google reCAPTCHA e ai cookie del browser |
| `14` | `captchaSessionToken` | Token di sessione interno |
| `15` | `bftToken` | ... |

---

### `pmeta` Struttura

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

Valori di pmeta[1]


Tipi di Challenge


Recupero dell'immagine della challenge

Il valore a Idx 9 (challengeImageToken) viene utilizzato per recuperare l'immagine CAPTCHA:```txt https://www.google.com/recaptcha//payload ?p= &k=

root@kitploit:~
### Category Identifiers

| ID | Categoria |
|---|---|
| `/m/0pg52` | Taxi |
| `/m/01bjv` | Autobus |
| `/m/02yvhj` | Autobus scolastico |
| `/m/04_sv` | Motocicletta |
| `/m/013xlm` | Trattore |
| `/m/01jk_4` | Camino |
| `/m/014xcs` | Attraversamento pedonale |
| `/m/015qff` | Semaforo |
| `/m/0199g` | Bicicletta |
| `/m/015qbp` | Parcometro |
| `/m/0k4j` | Auto |
| `/m/015kr` | Ponte |
| `/m/019jd` | Barca |
| `/m/0cdl1` | Palma |
| `/m/09d_r` | Montagna / collina |
| `/m/01pns0` | Idrante antincendio |
| `/m/01lynh` | Scale |

## Payload della Richiesta UserVerify
Il payload `/userverify` viene inviato dopo che l'utente completa una sfida reCAPTCHA v2

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

Componenti

response Payload

Rappresenta gli indici/posizioni dei quadrati selezionati dall'utente nella griglia

Il payload viene successivamente codificato come JWT prima dell'invio


Esempio di griglia 3×3

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

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

Esempio di griglia MultiCaptcha 4×4

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

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

e Field

Il payload response può anche includere un campo e:```json { "response": [2, 3, 6, 14], "e": "bxCoiXVt49I7CTS_tNlVbGg" }

root@kitploit:~
Questo campo contiene metadati di interazione crittografati relativi alle azioni dei pulsanti CAPTCHA come:

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

### Struttura interna di `e`

Dopo la decifratura, la struttura assomiglia a:```txt
[[["9ffd9672"]]]

Ogni valore rappresenta un identificatore hash per la classe/azione del pulsante rc-button-default

L'hash è:

  • basato su SHA-256
  • Troncato a 8 caratteri

Sequenze di interazione più lunghe potrebbero apparire come:```txt [ [ ["9ffd9672"], ["9ffd9672"], ["9ffd9672"], ["9ffd9672"] ] ]

root@kitploit:~
### `oc` — Segnali VM crittografati

Utilizza lo stesso algoritmo di crittografia del campo `idx 16` del payload della richiesta `/reload`, con la chiave di crittografia caricata nell'ancora (indice 31) `1777752103288`

### `pm` — Payload di telemetria

Il campo `pm` contiene una struttura di telemetria codificata in Base64 simile al payload di telemetria utilizzato in `/reload`.

 
## Anti-debugging/Manomissione
- ***Tag di integrità basato su Symbol***
    reCAPTCHA imposta una chiave Symbol `Symbol(jas)` su ogni array e oggetto con un valore numerico utilizzato come controllo di integrità. Poiché i Symbol non sono enumerabili e invisibili alle operazioni di clonazione standard (come JSON.stringify), qualsiasi tentativo di sostituire o clonare queste strutture perde il tag, che reCAPTCHA rileva come manomissione

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

- ***Cattura di variabili closure***
    Alcuni valori ​​sono intenzionalmente inseriti nell'ambito di una funzione esterna e consumati solo all'interno di callback o closures annidate, la variabile non esiste mai nello stesso ambito in cui viene utilizzata

- ***Controlli di temporizzazione***
    reCAPTCHA incorpora meccanismi di rilevamento del debugging in fase di esecuzione. Se rileva che il codice viene analizzato da un debugger, riavvia la sessione di debugging, causando la perdita dello stato e del contesto di esecuzione

- ***Scheda di origine crash***

    https://github.com/user-attachments/assets/4ae3bf68-5ae7-4adc-a0b9-36cc11b64998
  
    Questo bug si verifica nei browser che utilizzano Chromium. Ci sono diversi bug che causano la chiusura imprevista del browser o degli strumenti di sviluppo, come quello mostrato qui:
    
    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
    
    Pertanto, è molto probabile che uno di questi bug venga attivato quando si verifica il timeout, poiché probabilmente non è qualcosa che accadrebbe nel flusso di un utente reale

## reCAPTCHA Botguard

Sebbene BotGuard sia stato rimosso da Google, spiegherò un po' come funziona internamente per chi è interessato a come è, e quanto sia diverso da altri tipi di botguard

Innanzitutto, il processo di generazione dei token: la VM genera token per errori persistenti durante l'esecuzione. Questi errori possono essere dovuti a deviazioni dell'offset del bytecode, registri VM mancanti, stato VM errato e scarsa integrità del flusso di controllo. Questi errori vengono catturati dal dispatcher, che chiama una funzione che scrive byte per il token.

La VM utilizza ARX Cipher, un algoritmo creato dalla NSA nel 2013, simile a Speck per crittografare i dati. Viene utilizzato anche in tutti i Google BotGuard. L'algoritmo cambia con ogni versione, così come la costante (3990), l'ordine delle operazioni e dei round. Si presenta così:```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];
}

Scrittore di Byte e Crittografia

La funzione di crittografia principale ha due modalità: crittografia e nessuna crittografia. La modalità di crittografia utilizza ARX Cipher, Bitwise + XOR per crittografare i dati e inserirli in un buffer. Ci sono 4 tipi di buffer:

  • Buffer principale 180
  • Buffer Entropy Pad 353
  • Buffer di errore 304
  • Buffer PoE (Proof of Execution) 243 (non utilizzato in questo tipo di botguard).

La modalità senza crittografia imposta semplicemente i byte già crittografati nel 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 questa è la funzione che gestisce gli errori e chiama il 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;
        }
    }
}

Alla fine dell'esecuzione, la VM chiama la funzione principale che prepara il payload con questi buffer e genera il token, che è una firma. A differenza di altre VM BotGuard, questa VM non ha un sistema di fingerprinting, Google Botguard né esegue queste emissioni di errori + scrittura di byte, ed è molto più semplice e facile da reverse engineering.

Disclaimer

Questo repository è esclusivamente per scopi educativi e di ricerca. Il codice, le tecniche e i concetti presentati qui sono intesi per lo studio accademico e la comprensione degli argomenti trattati.

Scarica lo strumento
yM5Us/j/fn6EDgtmPlP4Pxj605nMJN9dRYHyy5Mn
  • Hashato: true

  • Descrizione: Impronta digitale Bloom filter in base64 a 40 caratteri di tutti i nodi <HEAD>. Scorre ogni elemento figlio raccogliendo nomi di tag, attributi e contenuto testuale, serializzati e sottoposti a hash djb2.

    Ogni digest viene inserito in un BitHash(240 bit, 7 round, max 25 nodi) che imposta bit su una griglia 40×6, quindi codifica ogni segmento da 6 bit come carattere base64. I tag script di reCAPTCHA sono esclusi tramite un'espressione regolare dinamica su src.

  • Idx 17 (integer)

    • Valore: 2
    • Hashato: false
    • Descrizione: Verifica se è possibile accedere per leggere/scrivere cookie di terze parti, Esempio
  • Idx 18 (string)

    • Valore: a2hyNTFuNDI4NnA3
    • Hashato: false
    • Descrizione: Valore generato casualmente codificato in Base64
  • Idx 27 (string)

    • Valore: location.origin
    • Hashato: false
    • Descrizione: URL del sito web.
  • Idx 28 (boolean)

    • Valore: false
    • Hashato: false
    • Descrizione: window.parent != window ? true : window.frameElement != null ? true : false
  • Idx 29 (string)

    • Valore: e2a3cd70
    • Hashato: true
    • Descrizione: Corpo della funzione grecaptcha.execute hashato con SHA-256, Esempio
  • Idx 30 (integer)

    • Valore: 0
    • Hashato: false
    • Descrizione: L'indice dello script contenente lo Script reCAPTCHA https://www.gstatic.com/recaptcha/releases/<version>/, Esempio
  • Idx 31 (string)

    • Valore: AAgkAQI0SB
    • Hashato: true
    • Descrizione: Chiavi di document.cookie hashate, Esempio
  • Idx 32 (string)

    • Valore: ""
    • Hashato: false
    • Descrizione: URL del referrer document.referrer.
  • Idx 33 (integer)

    • Valore: 2

    • Hashato: false

    • Descrizione: Elemento del box reCAPTCHA in cui avviene il rendering.

      root@kitploit:~
      // come grecaptcha.execute('.grecaptcha') -> questo div
      // Fondamentalmente, restituisce un numero o la profondità/livello di quel div nel documento.
      
      // Esempio: html > body > main > form > fieldset > div.recaptcha.form-field
      // 5 4 3 2 1 0
      // out = 5
      
      nM = document.getElementsByClassName('grecaptcha-badge')[0] // o document.getElementsByClassName('g-recaptcha')[0] v2
      let count = 0;
      for (; nM = nM.parentElement || null;) {
        count++;
      }
      
      const result = count;
      
  • Idx 34 (string)

    • Valore: AAAAAAAAAA
    • Hashato: true
    • Descrizione: Nomi degli attributi di tutti gli <INPUT> hashati, Esempio
  • Idx 35 (string)

    • Valore: 0,DIV,f0c7414e
    • Hashato: true
    • Descrizione: document.activeElement Analisi se è un elemento di acquisto usando un'espressione regolare /buy|pay|place|order|donate|purchase/i con textContent, classNames e id, Esempio
  • Idx 36 (string)

    • Valore: h3, h2 o http/1.1
    • Hashato: false
    • Descrizione: nextHopProtocol della performance di navigazione performance.getEntriesByType("navigation")[0].nextHopProtocol
  • Idx 37 (integer)

    • Valore: -1
    • Hashato: false
    • Descrizione: performance.timing.unloadEventStart
  • Idx 38 (integer)

    • Valore: 96
    • Hashato: false
    • Descrizione: Ricerca DNS performance.timing.domainLookupStart - performance.timing.domainLookupEnd
  • Idx 39 (integer)

    • Valore: 0
    • Hashato: false
    • Descrizione: Tipo di navigazione performance.navigation.type
  • Idx 40 (integer)

    • Valore: 0
    • Hashato: false
    • Descrizione: Ultima posizione di scorrimento Y window.scrollY o document.defaultView.pageYOffset
  • Idx 41 (string)

    • Valore: DIV,a08cd360
    • Hashato: true
    • Descrizione: L'elemento :hover su cui si trovava il mouse in quel momento, ottiene l'ultimo elemento e ne calcola l'hash di tagName, classNames e id, Esempio
  • Idx 42 (string)

    • Valore: 9,e3b0c442
    • Hashato: true
    • Descrizione: Script di testo casuale hashato con SHA-256 più l'indice, Esempio
  • Idx 44 (string)

    • Valore: 2v591z63wq
    • Hashato: true
    • Descrizione: Elemento :hover, document.activeElement, tutti gli elementi <INPUT> hashati, location.url, window.scrollY, Esempio:
    • 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)

    • Valore: 4
    • Hashato: false
    • Descrizione: Lunghezza di window.history.
  • Idx 46 (string)

    • Valore: https://static.kogstatic.com/0000/34c...
    • Hashato: false
    • Descrizione: Si è verificato un errore in uno script sulla pagina e la linea:colonna in cui è accaduto.
  • Idx 47 (integer)

    • Valore: 0
    • Hashato: false
    • Descrizione: Restituisce la lunghezza del testo attualmente selezionato sulla pagina dall'utente window.getSelection().toString().length || 0
  • Idx 49 (string)

    • Valore: h2-0
    • Hashato: false
    • Descrizione: Trova la voce Performance Resource Timing per lo script reCAPTCHA, ottiene il suo nextHopProtocol e determina se la sua duration è zero. Restituisce il risultato nel formato protocol-isZero, Esempio
  • Idx 50 (array)

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

    • Hashato: true

    • Descrizione: Contiene comportamenti utente, elementi :hover hashati e un timeout che si incrementa ogni volta che viene raccolto un altro elemento :hover. Analizza le attivazioni utente per accumulare il numero di volte in cui l'utente ha interagito o è ancora presente sulla pagina calcolando (10 * IsActive + IsBeenActive)

      Formato base:

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

    • Valore: [0]
    • Hashato: false
    • Descrizione: Cerca in document.body.innerText corrispondenze con le parole "try again", "incorrect", "invalid" o "declined" e restituisce il numero totale di corrispondenze trovate. Altrimenti restituisce 0, Esempio
  • Idx 52 (integer)

    • Valore: 11
    • Hashato: false
    • Descrizione: 10 * navigator.userActivation.isActive + navigator.userActivation.hasBeenActive
  • Idx 53 (integer)

    • Valore: 4

    • Hashato: false

    • Descrizione: Prende l'URL corrente del sito web, lo converte in un array di caratteri, lo tronca a 100 caratteri e poi lo riconverte in una stringa, Esempio

      Poi è 5 se la lunghezza di quella stringa troncata è pari, o 4 se è dispari.

  • Idx 54 (boolean)

    • Valore: false
    • Hashato: false
    • Descrizione: Indica se il documento è nascosto all'utente, cioè se non è visibile sullo schermo, window.document.hidden
  • Idx 55 (array)

    • Valore: [[[1,"2v"],[1,"9z"],[1,"z8"],[1,"us"],[1,..
    • Hashato: false
    • Descrizione: Ordinamento dei codici dei segnali generati in base ai valori delle impronte digitali.
  • Idx 56 (string)

    • Valore: -1,-1
    • Hashato: false
    • Descrizione: Controlli di window.opener, restituisce "-1,-1" se nullo, Esempio
  • Idx 57 (string)

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

    • Hashato: false

    • Descrizione: Raccoglie gli host da src di tutti gli elementi <SCRIPT> presenti in document.scripts, Esempio

      Per ogni <SCRIPT> Se l'elemento ha l'attributo src (hasAttribute("src")), il valore di src viene preso e analizzato con un'espressione regolare di tipo URI (nd), estraendo solo il componente host (gruppo di cattura 3 dell'espressione regolare).

      Se il <SCRIPT> non ha un attributo src (è uno script inline), viene utilizzato il segnaposto "_".

  • Idx 58 (string)

    • Valore: mapslitepromosdismissed1
    • Hashato: false
    • Descrizione: Chiave di window.localStorage campionata.
  • Idx 59 (string)

    • Valore: ""
    • Hashato: false
    • Descrizione: Nome del contesto di navigazione di una finestra o scheda window.name
  • Idx 60 (string)

    • Valore: https://www.kogama.com,https://www.google.com,https://js.stripe.com
    • Hashato: false
    • Descrizione: URL per eventi di messaggi aperti, Esempio
  • Idx 61 (array)

    • Valore: [0,"AAAAAAAAAA","AAAAAAAAAA"]
    • Hashato: true
    • Descrizione: Hash dei nomi degli attributi e dei tipi di elementi target registrati da MutationObserver, Esempio
  • Idx 62 (string)

    • Valore: document.title
    • Hashato: false
    • Descrizione: Titolo completo del sito web.
  • Idx 63 (array)

    • Valore: []

    • Hashato: false

    • Descrizione: Estrae timestamp (numeri di 12-13 cifre che iniziano con 1[2-9], tipici di epoch millisecondi ~2008-2099) dai valori dei cookie, Esempio

      Accumula i seguenti valori su tutti gli ID trovati: count, min, max e media. Il risultato del valore finale è un array [count, min, max, avg]

  • Idx 64 (integer)

    • Valore: 55557
    • Hashato: false
    • Descrizione: Tempo di esecuzione (dall'ancora al ricaricamento).
  • Idx 65 (string)

    • Valore: sha384-3qc
    • Hashato: true
    • Descrizione: Integrità dello script reCAPTCHA configurato in https://www.google.com/recaptcha/api.js?render= (troncato a 10 caratteri)
  • Idx 67 (array)

    • Valore: [screen.width, screen.height, screen.availHeight, window.innerWidth, window.innerHeight, window.outerHeight]
    • Hashato: false
    • Descrizione: Risoluzione dello schermo, larghezza e altezza del viewport del browser e altezza della finestra del browser.
  • Idx 68 (array)

    • Valore: [300,null,1777685870223]
    • Hashato: false
    • Descrizione: Offset del fuso orario e timestamp Unix corrente [new Date().getTimezoneOffset(), null, Date.now()]
  • Idx 69 (string)

    • Valore: 09AKhCRwjrDFiHsrRA--o23-HB-eWqOtk_XQ-rLE1...
    • Hashato: false
    • Descrizione: Un token di sessione utilizzato per l'identificazione umana, memorizzato nei cookie del browser e incrementa il punteggio se valido.
  • Idx 70 (array)

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

    • Hashato: false

    • Descrizione: Estrae importi monetari totali (come Total: $50.00 o Total 150.00 EUR), Esempio

      da document.innerText cercando il simbolo o codice della valuta insieme all'importo numerico usando l'espressione regolare:

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

      total → Cerca la parola esatta "total"

      [\S\s]{0,20}? → Cerca tra (0) e (20) caratteri intermedi (come spazi, due punti o interruzioni di riga) prima di trovare il numero

      (((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR)) → Questo è il blocco principale che cattura il denaro ed è diviso in due opzioni separate

  • Idx 71 (array)

    • Valore: [jsHeapSizeLimit,usedJSHeapSize,totalJSHeapSize]
    • Hashato: false
    • Descrizione: Memoria HEAP JavaScript delle performance.
  • Idx 72 (array)

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

    • Hashato: false

    • Descrizione: Array di dati userAgent navigator.userAgentData un flag che indica se è mobile e la piattaforma, Esempio:

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

    • Valore: [[null,2,0,"Mozilla/5.0 (Windows NT 10.0;...
    • Hashato: false
    • Descrizione: Segnali Criptati VM.
  • Idx 77 (integer)

    • Valore: null
    • Hashato: false
    • Descrizione: Timestamp Unix, a volte appare.
  • Idx 78 (string)

    • Valore: ""
    • Hashato: false
    • Descrizione: Cookie Google GA, può apparire se il sito web utilizza Google Tag Manager.
  • IndiceValoreDescrizione
    0rreqIdentificatore del tipo di richiesta
    1U5VsmTDhJM1iO...Versione reCAPTCHA
    203AFcWeA5Els3...Token di validazione ottenuto dall'endpoint /anchor
    5-383788762Ha hashato l'intero payload dell'impronta digitale serializzata, Sample
    6qIndica la sfida o la modalità di richiesta in esecuzione
    705APQrAobTCFG...Pattern di utilizzo, contenenti la cronologia di utilizzo e i pattern di sfida precedentemente risolti. Possono aumentare significativamente il punteggio se validi
    8submitAzione specifica del sito che l'utente sta eseguendo sulla pagina al momento della verifica (ad es. signin, register)
    146LcAbwIqAAAA...Chiave del sito web
    160XA4cHhALxgM...Ha crittografato l'intero payload dell'impronta digitale serializzata con la chiave di crittografia proveniente da anchor (indice 18) 1777669303203
    20tbMywxNTQsOD...Struttura di telemetria codificata in Base64 contenente delta temporali della VM, tempi delle risorse, statistiche degli oggetti del browser raccolte e URL degli script del sito web
    210aAPQrAobqME...Token associato a un CAPTCHA precedentemente risolto. Utilizzato per la continuità della sessione e la correlazione della fiducia
    22BDAAYAIAGEcA...Ha hashato tutte le chiavi degli oggetti del browser
    25W1tbNTAwNiw...Contatori codificati in Base64 per eventi di interazione dell'utente come movimento del mouse, clic, tastiera e cambiamenti di focus
    qrRisposta rapida (nuovo)
    Type
    recaptcha/api.js3
    recaptcha/releases/<version>1
    https://www.google.com/recaptcha/api2/anchor2
    https://www.google.com/recaptcha/api2/bframe4
    HashTipo di Evento
    5006pointermove
    64607pointerdown
    45464pointerup
    31617keydown
    37178keyup
    35837focusin
    PosizioneValoreDescrizione
    0/m/013xlmIdentificatore di categoria interna per la classe dell'oggetto target
    23Numero di colonne della griglia
    33Numero di righe della griglia
    5nullCampo metadati riservato o opzionale
    6"Tractor"Etichetta di testo
    TipoDescrizione
    imageselectSelezione immagine standard CAPTCHA
    tileselectChallenge basata su tile dinamico dell'immagine
    dynamicChallenge dinamica in cui i tile si ricaricano dopo la selezione
    multicaptchaChallenge CAPTCHA a più passi
    audioChallenge di accessibilità basata su audio
    nocaptchaFlusso di verifica solo con checkbox
    doscaptchaNega CAPTCHA in caso di abuso
    CampoNomeDescrizione
    vrecaptchaVersionVersione di reCAPTCHA
    cchallengeTokenToken dello stato della challenge restituito da /replaceimage o da una richiesta precedente /userverify
    responsePayload codificato contenente gli indici delle tessere selezionate e metadati aggiuntivi dell'interazione
    tchallengeElapsedTempo trascorso dal caricamento iniziale della challenge
    ctcompletionTimeTempo totale impiegato dall'utente per risolvere e inviare il CAPTCHA
    chocHashHash dell'intero payload serializzato oc, Esempio
    ocencryptedVmSignalsSegnali crittografati raccolti dalla VM di reCAPTCHA, vedi qui.
    pmtelemetryPayloadStruttura di telemetria codificata in Base64 contenente delta dei tempi della VM, tempi delle risorse, statistiche degli oggetti del browser raccolte e metadati dello script del sito web