Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
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.

FeedContattoPrivacy© 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
22738362 mesi 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/main/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.

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

    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.

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

    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.

    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.

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

    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mN è la tabella delle funzioni (50+ funzioni)
    
    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

Scarica lo strumento