Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
recaptcha — Documentation et rétro-ingénierie de reCAPTCHA | Kitploit
Outils/GitHubGitHub/elyelysiox/recaptcha
Analyse StatiqueAnalyse Dynamique de Code (DAST)Rétro-ingénierieSécurité WebAnti-BotContournement de CAPTCHA
GitHubelyelysiox/recaptcha

recaptcha

Documentation et rétro-ingénierie de reCAPTCHA

Voir le dépôt
227385il y a 2 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Description

Ce dépôt contient une analyse technique de l'antibot de Google (reCAPTCHA), en se concentrant sur :

  • Structure et valeurs des charges utiles
  • Techniques d'empreinte numérique
  • Techniques d'obscurcissement
  • Techniques anti-débogage/anti-modification
  • Machines virtuelles

Contact

  • Discord : @g_recaptcha
  • Telegram : @lyxlobyx

Techniques d'obscurcissement

reCAPTCHA est l'un des systèmes anti-bot dotés des techniques d'obscurcissement les plus sophistiquées, employant une série de transformations qui rendent le code moins lisible et plus difficile à rétro-ingénier. La plupart des obscurcissements peuvent être facilement manipulés à l'aide de l'arbre syntaxique abstrait (AST), mais certains sont traités au moment de l'exécution, rendant l'AST inutile dans ce cas. Le polymorphisme est également appliqué au code pour modifier sa structure dans chaque version du script. Par exemple, le code n'effectue pas l'action directement. Au lieu de cela, il utilise des objets ou des fonctions qui changent de forme

  • Expressions de séquence Le code est aplati en convertissant chaque bloc d'instructions en une expression continue séparée par des virgules. Cela peut apparaître dans les instructions if, les arguments de fonction, et même à l'intérieur d'objets seq

Télécharger l’outil
  • Arithmétique booléenne mixte Entremêle des opérations arithmétiques (addition, soustraction, multiplication) avec des opérations bit à bit (ET, OU, XOR, NON) pour masquer la logique originale, par exemple -2 * ~(h & H) + -2 + (h ^ H)

  • Table de fonctions indirecte Chaque fonction est construite dans une table et est appelée en utilisant son index, comme functions[index](https://github.com/elyelysiox/recaptcha/blob/main/args)

  • Tableau de constantes en ligne Un littéral de tableau local est affecté en ligne, au milieu d'une expression. Le tableau regroupe des constantes (nombres, chaînes) qui sont réutilisées dans tout le corps de la fonction via un accès par index

    root@kitploit:~
    // b = [14, 1, "call"] assigné en ligne dans une expression de séquence
    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
    }
    
  • Multiplexage de fonctions Plusieurs fonctions logiquement distinctes sont fusionnées en une seule, en utilisant un paramètre numérique comme sélecteur de bloc. Le bloc actif est déterminé en évaluant le paramètre par rapport à des conditions bit à bit. Les appelants passent un littéral numérique comme sélecteur.

    root@kitploit:~
    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // bloc 1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // logique de conversion de valeur en chaîne
        }
    
        // bloc 2
        if ((N + 4 & 40) >= N && (N + 5 & C[0]) < N) {
            Y = bB();
            throw Error(Y === void 0 ? "valeur inattendue " + U + y : Y);
        }
    
        return u;
    }
    
  • Branchement par opérateurs logiques Remplace les blocs if et if/else par l'évaluation en court-circuit des opérateurs logiques, convertissant le flux de contrôle en expressions. Combiné avec des expressions de séquence, plusieurs branches apparaissent comme une seule expression continue séparée par des virgules

    root@kitploit:~
    // if (a) { bloc }
    a && (bloc)
    
    // if (!a) { bloc }
    a || (bloc)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // combiné avec CFF et expressions de séquence :
    (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), ...)),
    
  • Liaison de constantes de méthodes natives Lie les méthodes natives du navigateur à leurs récepteurs d'origine, les stockant en tant que constantes pour empêcher toute modification

    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)
    
  • Code mort Des blocs de code inaccessibles ou inutilisés sont injectés dans tout le fichier, augmentant sa taille à plus de 60 000 lignes, ce qui rend l'analyse statique et la rétro-ingénierie par LLM difficiles

  • Aplatissement du flux de contrôle Transforme chaque partie du code (déclarations et boucles) en une machine d'état plate. Cela masque la logique d'exécution d'origine en acheminant tous les blocs de code via un bloc « répartiteur » central

    Les répartiteurs peuvent changer de forme ; certains ont 2-3 variables d'état, et le type de boucle/condition change. Ils ressemblent à ceci

    cff1

    Ceci est un CFF avec 2 variables d'état, l'une gère le bloc catch et l'autre le bloc try.

  • Pool de chaînes chiffrées Tous les littéraux de chaîne (API DOM, propriétés du navigateur, valeurs CSS, messages d'erreur, etc.) sont chiffrés en un seul pool de chaînes massif. Une fonction de déchiffrement utilise une graine et un chiffrement XOR basé sur LCG pour extraire chaque chaîne au moment de l'exécution

    Il y a plus de 1990 sites d'appel répartis dans le code. La fonction de déchiffrement utilise une clé courante qui accumule les points de code décodés, rendant chaque caractère dépendant de tous les précédents

    root@kitploit:~
    X = function(J, b, P, F, U) {
        U = ["codePointAt", 127, "pool chiffré de chars"];
        for (F = (P = 0, b = "", l); P < Q; P++)
            J = (U[2][U[0]](c + P) ^ F) & U[1],  // XOR avec clé courante
            b += String.fromCodePoint(J),
            F += J; // accumule la clé
        return G = b;
    }
    
    // les sites d'appel passent une graine pour localiser et déchiffrer chaque chaîne
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • Itérateur de valeurs avec état reCAPTCHA utilise une fonction avec état qui renvoie une séquence d'objets et de valeurs d'exécution (comme window, document.body, des constantes numériques) dans un ordre fixe ; chaque appel avance un curseur interne. L'appeler dans le désordre ou trop de fois corrompt toutes les lectures ultérieures. Un mécanisme d'expiration invalide l'état après un intervalle fixe, renvoyant null pour toutes les lectures tardives

    root@kitploit:~
    // les appels séquentiels renvoient des valeurs différentes :
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (expiration dépassée)
    
    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  
    
    
  • Table de fonctions calculée Ceci est similaire à la Table de fonctions indirecte, mais ici l'index de la fonction à obtenir est calculé au moment de l'exécution avec une graine, en utilisant XOR et Modulo

    root@kitploit:~
    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mN est la table de fonctions (50+ fonctions)
    
    root@kitploit:~
    q[29](5, 6977)   // seed=6977  → l'index se résout en fonction à mN[X]
    q[29](53, 6187)  // seed=6187  → index différent, fonction différente
    

    computed

  • Chiffrement des valeurs d'exécution Certaines valeurs (paramètres de configuration du captcha, paramètres d'ancrage, etc.) ne sont jamais stockées en texte clair ; elles sont chiffrées immédiatement après la collecte et déchiffrées uniquement au moment de l'utilisation, ont un préfixe B au début

    hiddenv

  • Obscurcissement du flux de contrôle asynchrone La logique synchrone est convertie en machines d'état basées sur des générateurs enveloppées dans des chaînes de Promesses récursives. Toute trace d'une valeur dans le débogueur force à parcourir plusieurs gestionnaires asynchrones, perdant le contexte d'exécution d'origine à chaque frontière .then()

  • Charge utile/Réponse de l'ancre

    Structure de la charge utile

    Composants pour initialiser reCAPTCHA``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

    root@kitploit:~
    ### Response
    
    La réponse contient :
    - Conception de la fenêtre iframe CAPTCHA
    - Jeton d'ancrage utilisé pour la validation de la charge utile (/reload)
    - La configuration principale pour l'initialisation, exécutée dans la méthode `recaptcha.anchor.Main.init` pour la recevoir dans recaptcha_en.js
    
    ### Structure :
    
    Note : Recaptcha BotGuard a été supprimé le `04/01/2026`, vous pouvez voir quelques exemples [ici](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
    ]
    

    Empreinte

    Les valeurs​ sont basées sur les valeurs déchiffrées de la première empreinte​ d'échantillon, regardez ici

    Chaque sous-champ des valeurs d'empreinte​​ a un format de base :

    [value, key, elapsed]

    Où key est la clé de chiffrement, et elapsed est le temps qu'il a fallu au collecteur pour obtenir et chiffrer la valeur. Cela permet à reCAPTCHA de détecter :

    • Exécution excessivement rapide
    • Hooks
    • Points d'arrêt et sandboxing

    Ordre d'exécution du collecteur

    Le système utilise un planificateur interne :``` [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:~
    Cela représente :
    
    - Ordre d'exécution
    - Pipeline de collecte
    - Séquence de génération de signaux
    
    ### Codes de signaux d'empreinte et dérivation de clé
    Transforme les signaux d'empreinte en clés de chiffrement déterministes via un pipeline de dérivation en plusieurs étapes
    
    Chaque valeur d'empreinte est :
    
    - Normalisée
    - Encodée en un code de signal compact
    - Convertie en une clé de chiffrement numérique
    - Chiffrée à l'aide de la clé dérivée
    
    Le processus est déterministe, ce qui signifie que la même valeur d'entrée génère toujours le même code de signal et la même clé de chiffrement```
    Raw Value
       ↓
    Signal Code Derivation
       ↓
    Compact Signal Code
       ↓
    Numeric Key Derivation
       ↓
    Encryption Key
       ↓
    Value Encryption
    

    Exemple

    Signal d'entrée``` "BUTTON,195a81c9"

    root@kitploit:~
    ***Étape 1 - Dériver le code de signal***```javascript
    deriveSignalCode("BUTTON,195a81c9")
    // → "wg"
    

    Le code de signal généré est un identifiant déterministe compact pour la valeur d'origine.

    Étape 2 - Dérivation de la clé numérique```javascript deriveKey("wg") // → 3792

    root@kitploit:~
    Le code du signal est transformé en une clé de chiffrement numérique.
    
    ***Étape 3 — Chiffrer la valeur***```javascript
    encryptValueWithKey(3792, "wgia1z9pwq")
    // → "bYVbh6BUsE_5pLA"
    

    La valeur suivante sera chiffrée avec la clé dérivée, en respectant l'ordre du collecteur.

    Structure d'empreinte agrégée

    Tous les codes de signal générés sont agrégés dans une structure sérialisée compacte.

    Processus``` 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"
    ]
    

    Signaux

    • Idx 4 (string)

      • Valeur : 3ccb

      • Haché : true

      • Description : Génère une clé HMAC à partir de window.localStorage.getItem("rc::a") + "6d" converti en octets, calcule HMAC-SHA256(siteKey) avec cette clé, et retourne les 4 premiers caractères hexadécimaux du résultat.

        La valeur de rc::a est un base64 généré aléatoirement.

    • Idx 5 (integer)

      • Valeur : window.localStorage.length * 2
      • Haché : false
      • Description : longueur de window.localStorage multipliée par 2
    • Idx 16 (string)

      • Valeur : yM5Us/j/fn6EDgtmPlP4Pxj605nMJN9dRYHyy5Mn

      • Haché : true

      • Description : Empreinte de filtre Bloom en base64 de 40 caractères de tous les nœuds <HEAD>. Parcourt chaque élément enfant en collectant les noms de balises, les attributs et le contenu textuel, sérialisé et passé dans un hachage djb2.

        Chaque condensé est introduit dans un BitHash(240 bits, 7 rounds, max 25 nodes) qui définit des bits sur une grille de 40×6, puis encode chaque segment de 6 bits en un caractère base64. Les balises de script de reCAPTCHA lui-même sont exclues via une expression régulière dynamique sur src.

    • Idx 17 (integer)

      • Valeur : 2
      • Haché : false
      • Description : Vérifie s'il existe un accès pour stocker/lire des cookies tiers, Exemple)
    • Idx 18 (string)

      • Valeur : a2hyNTFuNDI4NnA3
      • Haché : false
      • Description : Valeur générée aléatoirement encodée en Base64
    • Idx 27 (string)

      • Valeur : location.origin
      • Haché : false
      • Description : URL du site web.
    • Idx 28 (boolean)

      • Valeur : false
      • Haché : false
      • Description : window.parent != window ? true : window.frameElement != null ? true : false
    • Idx 29 (string)

      • Valeur : e2a3cd70
      • Haché : true
      • Description : Corps de la fonction grecaptcha.execute haché avec SHA-256, Exemple
    • Idx 30 (integer)

      • Valeur : 0
      • Haché : false
      • Description : L'index du script contenant le script reCAPTCHA https://www.gstatic.com/recaptcha/releases/<version>/, Exemple
    • Idx 31 (string)

      • Valeur : AAgkAQI0SB
      • Haché : true
      • Description : Clés de document.cookie hachées, Exemple
    • Idx 32 (string)

      • Valeur : ""
      • Haché : false
      • Description : URL du référent document.referrer.
    • Idx 33 (integer)

      • Valeur : 2

      • Haché : false

      • Description : Élément de la boîte reCAPTCHA où le rendu est effectué.

        root@kitploit:~
        // comme grecaptcha.execute('.grecaptcha') -> ce div
        // En gros, cela retourne un nombre ou la profondeur/niveau de ce div dans le document.
        
        // Exemple : html > body > main > form > fieldset > div.recaptcha.form-field
        // 5 4 3 2 1 0
        // out = 5
        
        nM = document.getElementsByClassName('grecaptcha-badge')[0] // ou document.getElementsByClassName('g-recaptcha')[0] v2
        let count = 0;
        for (; nM = nM.parentElement || null;) {
          count++;
        }
        
        const result = count;
        
    • Idx 34 (string)

      • Valeur : AAAAAAAAAA
      • Haché : true
      • Description : Tous les noms d'attributs <INPUT> hachés, Exemple
    • Idx 35 (string)

      • Valeur : 0,DIV,f0c7414e
      • Haché : true
      • Description : Analyse document.activeElement pour déterminer s'il s'agit d'un élément d'achat en utilisant une expression régulière /buy|pay|place|order|donate|purchase/i avec textContent, classNames et id, Exemple
    • Idx 36 (string)

      • Valeur : h3, h2 ou http/1.1
      • Haché : false
      • Description : nextHopProtocol de la performance de navigation performance.getEntriesByType("navigation")[0].nextHopProtocol
    • Idx 37 (integer)

      • Valeur : -1
      • Haché : false
      • Description : performance.timing.unloadEventStart
    • Idx 38 (integer)

      • Valeur : 96
      • Haché : false
      • Description : Recherche DNS performance.timing.domainLookupStart - performance.timing.domainLookupEnd
    • Idx 39 (integer)

      • Valeur : 0
      • Haché : false
      • Description : Type de navigation performance.navigation.type
    • Idx 40 (integer)

      • Valeur : 0
      • Haché : false
      • Description : Dernière position de défilement Y window.scrollY ou document.defaultView.pageYOffset
    • Idx 41 (string)

      • Valeur : DIV,a08cd360
      • Haché : true
      • Description : L'élément :hover où la souris était positionnée à ce même moment, obtient le dernier élément et hache tagName, classNames et id, Exemple
    • Idx 42 (string)

      • Valeur : 9,e3b0c442
      • Haché : true
      • Description : Un script texte aléatoire haché avec SHA-256 plus l'index, Exemple
    • Idx 44 (string)

      • Valeur : 2v591z63wq
      • Haché : true
      • Description : Élément :hover, document.activeElement, tous les éléments <INPUT> hachés, location.url, window.scrollY, Exemple :
      • 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)

      • Valeur : 4
      • Haché : false
      • Description : Longueur de window.history.
    • Idx 46 (string)

      • Valeur : https://static.kogstatic.com/0000/34c...
      • Haché : false
      • Description : Une erreur s'est produite dans un script sur la page et la line:column où cela s'est produit.
    • Idx 47 (integer)

      • Valeur : 0
      • Haché : false
      • Description : Retourne la longueur du texte actuellement sélectionné sur la page par l'utilisateur window.getSelection().toString().length || 0
    • Idx 49 (string)

      • Valeur : h2-0
      • Haché : false
      • Description : Trouve l'entrée Performance Resource Timing pour le script reCAPTCHA, obtient son nextHopProtocol, et détermine si sa duration est zéro. Retourne le résultat au format protocol-isZero, Exemple
    • Idx 50 (array)

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

      • Haché : true

      • Description : Contient les comportements de l'utilisateur, les éléments :hover hachés et un timeout qui s'incrémente à chaque fois qu'un autre élément :hover est collecté. Il analyse les activations de l'utilisateur pour accumuler le nombre de fois que l'utilisateur a interagi ou est toujours présent sur la page en calculant (10 * IsActive + IsBeenActive)

        Format de base :

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

      • Valeur : [0]
      • Haché : false
      • Description : Recherche dans document.body.innerText des correspondances avec les mots "try again", "incorrect", "invalid" ou "declined" et retourne le nombre total de correspondances trouvées. Sinon retourne 0, Exemple
    • Idx 52 (integer)

      • Valeur : 11
      • Haché : false
      • Description : 10 * navigator.userActivation.isActive + navigator.userActivation.hasBeenActive
    • Idx 53 (integer)

      • Valeur : 4

      • Haché : false

      • Description : Prend l'URL actuelle du site web, la convertit en un tableau de caractères, la tronque à 100 caractères, puis la reconvertit en chaîne, Exemple

        Ensuite, c'est 5 si la longueur de cette chaîne tronquée est paire, ou 4 si elle est impaire.

    • Idx 54 (boolean)

      • Valeur : false
      • Haché : false
      • Description : Indique si le document est masqué pour l'utilisateur, c'est-à-dire s'il n'est pas visible à l'écran, window.document.hidden
    • Idx 55 (array)

      • Valeur : [[[1,"2v"],[1,"9z"],[1,"z8"],[1,"us"],[1,..
      • Haché : false
      • Description : Ordre des codes de signaux générés par les valeurs d'empreinte.
    • Idx 56 (string)

      • Valeur : -1,-1
      • Haché : false
      • Description : Vérifications de window.opener, retourne "-1,-1" si null, Exemple
    • Idx 57 (string)

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

      • Haché : false

      • Description : Collecte les hôtes provenant de l'attribut src de tous les éléments <SCRIPT> présents dans document.scripts, Exemple

        Pour chaque <SCRIPT> : Si l'élément a l'attribut src (hasAttribute("src")), la valeur de src est prise et analysée avec une regex de type URI (nd), en extrayant uniquement le composant hôte (groupe de capture 3 de la regex).

        Si le <SCRIPT> n'a pas d'attribut src (c'est un script en ligne), le caractère de remplacement "_" est utilisé.

    • Idx 58 (string)

      • Valeur : mapslitepromosdismissed1
      • Haché : false
      • Description : Clé window.localStorage échantillonnée.
    • Idx 59 (string)

      • Valeur : ""
      • Haché : false
      • Description : Nom du contexte de navigation d'une fenêtre ou d'un onglet window.name
    • Idx 60 (string)

      • Valeur : https://www.kogama.com,https://www.google.com,https://js.stripe.com
      • Haché : false
      • Description : URLs pour les événements de message ouverts, Exemple
    • Idx 61 (array)

      • Valeur : [0,"AAAAAAAAAA","AAAAAAAAAA"]
      • Haché : true
      • Description : Hachages des noms d'attributs et des types d'éléments cibles enregistrés par MutationObserver, Exemple
    • Idx 62 (string)

      • Valeur : document.title
      • Haché : false
      • Description : Titre complet du site web.
    • Idx 63 (array)

      • Valeur : []

      • Haché : false

      • Description : Extrait les horodatages (nombres de 12-13 chiffres commençant par 1[2-9], typiques des millisecondes epoch ~2008-2099) des valeurs de cookies, Exemple

        Accumule les valeurs suivantes sur tous les IDs trouvés : count, min, max et average. Le résultat final est un tableau [count, min, max, avg]

    • Idx 64 (integer)

      • Valeur : 55557
      • Haché : false
      • Description : Temps d'exécution (de l'ancre au rechargement).
    • Idx 65 (string)

      • Valeur : sha384-3qc
      • Haché : true
      • Description : Intégrité du script reCAPTCHA configuré dans https://www.google.com/recaptcha/api.js?render= (tronqué à 10 caractères)
    • Idx 67 (array)

      • Valeur : [screen.width, screen.height, screen.availHeight, window.innerWidth, window.innerHeight, window.outerHeight]
      • Haché : false
      • Description : Résolution de l'écran, largeur et hauteur de la fenêtre d'affichage du navigateur et hauteur de la fenêtre du navigateur.
    • Idx 68 (array)

      • Valeur : [300,null,1777685870223]
      • Haché : false
      • Description : Décalage de fuseau horaire et horodatage Unix actuel [new Date().getTimezoneOffset(), null, Date.now()]
    • Idx 69 (string)

      • Valeur : 09AKhCRwjrDFiHsrRA--o23-HB-eWqOtk_XQ-rLE1...
      • Haché : false
      • Description : Un jeton de session utilisé pour l'identification humaine, stocké dans les cookies du navigateur et incrémente le score s'il est valide.
    • Idx 70 (array)

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

      • Haché : false

      • Description : Extrait les montants monétaires totaux (comme Total: $50.00 ou Total 150.00 EUR), Exemple

        à partir de document.innerText en recherchant le symbole ou le code de la devise avec le montant numérique en utilisant l'expression régulière :

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

        total → Recherche le mot exact "total"

        [\S\s]{0,20}? → Recherche entre 0 et 20 caractères intermédiaires (espaces, deux-points, sauts de ligne) avant de trouver le nombre

        (((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR)) → C'est le bloc principal qui capture l'argent et est divisé en deux options distinctes

    • Idx 71 (array)

      • Valeur : [jsHeapSizeLimit,usedJSHeapSize,totalJSHeapSize]
      • Haché : false
      • Description : Mémoire HEAP JavaScript de performance.
    • Idx 72 (array)

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

      • Haché : false

      • Description : Tableau de données userAgent navigator.userAgentData, un indicateur indiquant s'il est mobile et la plateforme, Exemple :

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

      • Valeur : [[null,2,0,"Mozilla/5.0 (Windows NT 10.0;...
      • Haché : false
      • Description : Signaux chiffrés par VM.
    • Idx 77 (integer)

      • Valeur : null
      • Haché : false
      • Description : Horodatage Unix, il apparaît parfois.
    • Idx 78 (string)

      • Valeur : ""
      • Haché : false
      • Description : Cookie Google GA, peut apparaître si le site web utilise Google Tag Manager.

    Certains signaux reCAPTCHA peuvent être indisponibles ou ne pas être collectés (en raison de délais d'attente liés au débogage). Dans ce cas, le signal manquant est rempli avec une valeur encodée en base64 générée aléatoirement. Par exemple :``` ["CMXZyamk3ZHNjdGsyaQ==", 3249, 591]

    root@kitploit:~
    Une fois la construction de l'empreinte terminée, elle est sérialisée en une chaîne et chiffrée à l'aide de la clé de chiffrement chargée depuis le champ d'ancrage (index 18). Le résultat chiffré est ensuite stocké dans le champ d'index `16` de la charge utile `/reload`.
    
    ## Signaux de la VM
    Voici les valeurs du navigateur ​​obtenues par la VM interne de reCAPTCHA, ainsi que la clé de signal. Certaines valeurs ​​ne sont pas affichées dans l'empreinte exemple car la VM n'extrait que certaines valeurs ​​du bytecode de configuration. Par conséquent, d'autres valeurs ​​seront affichées. Pour plus de détails, voir [ici](https://github.com/elyelysiox/recaptcha-vm)
    
    Format de signal de base :```
    [
      null,
      collectorElapsed,
      encryptElapsed,
      value
    ]
    

    Où collectorElapsed signifie combien de temps (ms) il a fallu au collecteur pour obtenir la valeur Et encryptElapsed signifie combien de temps (ms) il a fallu pour chiffrer la valeur. Ces temps sont mesurés pendant l'exécution de la 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...`
      - Description: User-Agent complet du navigateur
    
    - **Key 727** (`array`)
      - Value: `[]`
      - Description: Blocs de prix de produits, contient les prix des produits commerciaux sur le site web, ceux-ci peuvent apparaître sur des sites de places de marché comme Amazon, eBay, AliExpress, etc, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/findProductPricesBlock.js)
    
    - **Key 150** (`array`)
      - Value: `[\"Join And Get Free Trial!\",\"\",\"Captcha Solving Service\",\"Prod...`
      - Description: Liens extraits des éléments `<a>` du site web, la machine virtuelle extrait rarement ces valeurs
    
    - **Key 545** (`boolean`)
      - Value: `false`
      - Description: `navigator.webdriver`
    
    - **Key 370** (`integer`)
      - Value: `0`
      - Description: Nombre maximal de points de contact de l'appareil `navigator.maxTouchPoints`
    
    - **Key 779** (`array`)
      - Value: `[null,null,null,null,"false"]`
      - Description: Extrait les données des champs d'expédition/facturation, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/formFieldScrape.js)
      
        `postal|postalcode|postalcode|postal_code|zip` → recherche le champ de code postal
        
        `ship|deliver` → section d'expédition
        
        `billing|payment|credit` → section de facturation
        
        `country` → sélecteur de pays
        
        `addr.*(match|equal)|(match|equal).*address` → case à cocher "même adresse"
        
        Lit le nom, l'id, l'autocomplete, le className de chaque élément
        Trois phases : saisies de texte, instructions SELECT, cases à cocher
    
    - **Key 659** (`array`)
      - Value: `[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]`
      - Description: Contient les données des éléments pressés sur la page au format `[[[count,timestamp]],[[hashedElem,tagType,type,autoComplete]],pressedCount,behaviorChecksum]`
     
        ### Type d'élément
        
        | Type d'élément | 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 |
    
        ### Algorithme de somme de contrôle comportementale
        
        La behaviorChecksum est un score comportemental compact dérivé des données d'interactions utilisateur collectées.
     
        Pour chaque interaction :
        - L'indice d'interaction est incrémenté de un
        - L'horodatage est combiné avec l'indice d'interaction ajusté
        - Le hachage de l'élément est réduit à l'aide d'une opération modulo
        - Le résultat est accumulé dans un score courant
       
        ---
    
        ```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;
        }
        ```
    
        ### Exemple
    
        ```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]`
      - Description: Contient les mouvements de défilement collectés pendant la session de la page
     
        ### Format de base
        ```
        [ [ [ scrollX, scrollY, timestamp ] ], count, behaviorChecksum ]
        ```
    
    - **Key 895** (`array`)
      - Value: `[[[1,0]]]`
      - Description:` VisibilityStateEntry` suit l'état de visibilité de la page, indiquant si l'utilisateur consulte actuellement la page ou a navigué ailleurs, au format `[[[isVisible, startTime]]]`
    
    - **Key 1092** (`array`)
      - Value: `[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]`
      - Description: Performance reCAPTCHA, PerformanceNavigationTiming et PerformanceEventTiming, au format `[vmStart,vmEnd,domContentLoadedEventEnd,loadEventEnd,firstUserInteractionTime]`
    
    - **Key 41** (`array`)
      - Value: `[[[1123,0,0]]]`
      - Description: ClearTimeout
    
    - **Key 43** (`array`)
      - Value: `[[[1123,0]]]`
      - Description: ClearTimeout
    
    - **Key 549** (`array`)
      - Value: `[0,null,null,null,null,null,null]`
      - Description: KeyboardEvent, touches calculées + horodatages
    
    - **Key 352** (`array`)
      - Value: `1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],...`
      - Description:
        La structure contient :
    
        - Temporisation des mouvements de souris
        - Coordonnées du curseur
        - Durées des clics
        - Dimensions des éléments pressés
        - Informations sur le type de pointeur
        - Métriques de pression
        - Distance parcourue par le curseur
        - Statistiques temporelles comportementales
    
        ### Format de base :
        ```
        [
          eventsCount,
          mouseEvents,
          [
            coalescedEventsCount,
            averageInterEventDelay,
            timingVarianceScore
          ],
          [
            totalPoints,
            clickSequenceScore,
            totalCursorDistance,
            totalPoints
          ],
          0,
          0,
          behaviorChecksum
        ]
        ```
        
        ### Structure des événements souris :
        
        Chaque entrée dans mouseEvents suit cette structure :
        
        ```
        [
          timestamp,
          clickDuration,
          clientX,
          clientY,
          [
            elementLeft,
            elementTop,
            elementWidth,
            elementHeight
          ],
          elementTagType,
          trackedElementIndex,
          pressure,
          pointerTravelDistance,
          pointerArea
        ]
        ```
    
        | Nom | Description |
        |---|---|
        | `timestamp` | Horodatage de l'événement relatif au début de l'événement |
        | `clickDuration` | Durée entre `pointerdown` et `pointerup` |
        | `clientX` | ... |
        | `clientY` | ... |
        | `elementBounds` | Rectangle englobant de l'élément interactif |
        | `elementTagType` | Identifiant de balise DOM encodé de l'élément interactif |
        | `trackedElementIndex` | Identifiant interne de l'élément DOM interactif provenant de la carte d'interaction d'exécution |
        | `pressure` | Valeur de pression de pointeur normalisée multipliée par `100` |
        | `pointerTravelDistance` | Distance parcourue entre `pointerdown` et `pointerup` |
        | `pointerArea` | Zone de contact calculée comme `largeur * hauteur` |
    
        ### Type de balise d'élément
    
        Ceci est initialisé lors de l'exécution de la VM reCAPTCHA
    
        | Type      | 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 |
    
        ### Exemple
        ```
        [
          18342,
          91,
          742,
          381,
          [700, 320, 120, 38],
          3,
          1,
          50,
          1.4,
          16
        ]
        ```
        
        Représente :
        
        - événement à `18,342s`
        - durée du clic de `91ms`
        - clic à `(742, 381)`
        - interaction avec un `BOUTON`
        - pression du pointeur `0,5` (50)
        - léger mouvement du curseur pendant le clic
        - zone de contact du pointeur de `16`
       
        ### Algorithme de somme de contrôle comportementale
     
        Pour chaque événement souris :
    
        - La durée du clic est amplifiée
        - Le résultat est combiné avec l'horodatage de l'événement
        - Les coordonnées du curseur et les dimensions de l'élément sont mélangées
        - Un ratio pondéré est calculé
        - Le ratio est arrondi et accumulé
        
        Après le traitement de tous les événements :
        
        - Le score accumulé est combiné avec la distance totale du curseur
        - Le résultat est normalisé en utilisant le nombre de points collectés
        - Une transformation logarithmique est appliquée
        - Des statistiques de mouvement supplémentaires sont incorporées
        - La valeur finale est réduite à l'aide d'une opération modulo
        - Le résultat est arrondi en un petit score entier
        
        ---
        
        ```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);
        }
        ```
    
        ### Exemple
    
        ```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: `""`
      - Description: Analyse des prix totaux collectés du site web $ avec une expression régulière ``(?i)total[\S\s]{0,20}?(?:(?:(?:USD|\$)\s*)?[\d\.,]+\s*(?:USD|\$)|(?:USD|\$)\s*[\d\.,]+)``, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/websitePricesTotal.js)
    
    - **Key 1278** (`integer`)
      - Value: `229.6`
      - Description: Division par 10 du temps d'exécution actuel `Math.trunc(performance.now()) / 10`
        
    - **Key 1422** (`boolean`)
      - Value: `false`
      - Description: Analyse s'il y a des champs OTP/2FA sur le site web, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/parseOTPFields.js)
    
    - **Key 614** (`array`)
      - Value: `[1,0,0,Infinity]`
      - Description: Informations sur la batterie de l'appareil, au format `[level,isCharging,chargingTime,dischargingTime]`
    
    - **Key 2033** (`array`)
      - Value: `["0",-1,-1,999]`
      - Description: Certaines valeurs constantes de la VM et le timing d'exécution de la VM
    
    - **Key 1313** (`array`)
      - Value: `["undefined",3]`
      - Description: Vérifications Android, Chrome, `[typeof window.android, Object.keys(window.chrome).length]`
    
    - **Key 1994** (`array`)
      - Value: `[2,4,53324367238]`
      - Description: `[navigator.hardwareConcurrency, navigator.deviceMemory, navigator.storage.estimate().qouta]`
    
    - **Key 1310** (`array`)
      - Value: `["Google Inc. (Intel Inc.)","ANGLE (Intel Inc.,...`
      - Description: Rendu WebGL, Fournisseur et extensions totales, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/webglSignals.js)
    
    - **Key 291** (`array`)
      - Value: `[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,...`
      - Description: Clés de prototypes spécifiques hachées d'objets navigateur, comme `SpeechSynthesisEvent`, `NetworkInformation`, `HTMLElement`, etc, [Exemple](https://github.com/elyelysiox/recaptcha/blob/main/hashBrowserProtos.js)
    
    ## Charge utile de la requête de rechargement
    
    Ces données sont sérialisées à l'aide de protobuf (Protocol Buffers), une méthode efficace et neutre pour sérialiser des données structurées, développée par 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,
    ]
    

    Components

    IndexValeurDescription
    0rreqIdentifiant du type de requête
    1U5VsmTDhJM1iO...Version de reCAPTCHA
    203AFcWeA5Els3...Jeton de validation obtenu depuis le point de terminaison /anchor
    5-383788762Hachage de la totalité de la charge utile d'empreinte sérialisée, Exemple
    6qIndique le défi ou le mode de requête en cours d'exécution
    705APQrAobTCFG...Modèles d'utilisation, contenant l'historique d'utilisation et les motifs de défis précédemment résolus. Peut augmenter significativement le score si valide
    8submitAction spécifique du site que l'utilisateur effectue sur la page au moment de la vérification (ex. signin, register)
    146LcAbwIqAAAA...Clé du site Web
    160XA4cHhALxgM...Chiffrement de la totalité de la charge utile d'empreinte sérialisée avec la clé de chiffrement provenant de l'ancre (index 18) 1777669303203
    20tbMywxNTQsOD...Structure de télémétrie encodée en Base64 contenant les écarts de temporisation de la machine virtuelle, les temporisations des ressources, les statistiques des objets navigateur collectées et les URL des scripts du site
    210aAPQrAobqME...Jeton associé à un CAPTCHA résolu précédemment. Utilisé pour la continuité de session et la corrélation de confiance
    22BDAAYAIAGEcA...

    Modes de défi

    ValeurDescription
    qDéfi reCAPTCHA V3
    fiDéfi reCAPTCHA V2/Invisible
    aDéfi audio
    qrRéponse rapide (nouveau)

    Charge utile de télémétrie (Idx 20)

    Pour décoder :```javascript atob("W1tbMywwLDgyOV0sWzEs...") // → [[[3,0,829],[1,42,863]],[[2,727,1341.300000011921]...

    root@kitploit:~
    Le payload contient :
    
    - Informations de chronométrage des ressources
    - Chronométrage des performances des tâches longues
    - Deltas d'exécution VM de reCAPTCHA
    - URLs des scripts du site web
    - Statistiques de collecte d'objets du navigateur
    
    ### Structure de base```js
    [
      [recaptchaResources],
      [tasksTiming],
      [
          null,
          null,
          null,
          idleTimeoutDelta,
          deltaTiming,
          0,
          0,
          0,
      ],
      websiteScriptsUrls,
      [collectionElapsed, browserObjectsLength]
    ]
    

    Format de temporisation des tâches longues```js

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

    root@kitploit:~
    ### Format de Synchronisation des Ressources reCAPTCHA```js
    [
       resourceType,
       duration,
       startTime
    ]
    
    ResourceType
    recaptcha/api.js3
    recaptcha/releases/<version>1
    https://www.google.com/recaptcha/api2/anchor2
    https://www.google.com/recaptcha/api2/bframe4

    Compteurs d'événements (Idx 25)

    Ce champ contient des compteurs encodés en Base64 pour les événements d'interaction navigateur collectés lors de l'exécution

    Exemple décodé :```js [ [ [5006, 43], [64607, 1], [45464, 1], [35837, 1] ] ]

    root@kitploit:~
    ### Structure du compteur d'événements```js
    [
      [
        [eventType, count]
      ]
    ]
    

    Hachages d'événements connus

    HashType d'événement
    5006pointermove
    64607pointerdown
    45464pointerup
    31617keydown
    37178keyup
    35837focusin

    Structure de la réponse```js

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

    root@kitploit:~
    ## Descriptions des champs
    
    | Index | Nom | Description |
    |---|---|---|
    | `0` | `rresp` | Identifiant du type de réponse retourné par le point de terminaison de rechargement |
    | `1` | `responseToken` | Jeton de réponse reCAPTCHA |
    | `3` | `tokenExpiration` | Durée de vie du jeton en secondes avant expiration |
    | `4` | `pmeta` | Bloc de métadonnées du défi contenant des informations sur le type, la catégorie et la disposition de la grille du CAPTCHA |
    | `5` | `challengeType` | Type de défi CAPTCHA |
    | `8` | `usagePatternToken` | Modèles d'utilisation, stockés dans `window.sessionStorage` et réutilisés dans les futures requêtes `/reload` |
    | `9` | `challengeImageToken` | Jeton utilisé pour récupérer la charge utile de l'image CAPTCHA depuis le point de terminaison `/payload` |
    | `12` | `humanVerificationToken` | Jeton d'identification humaine associé à l'état Google reCAPTCHA et aux cookies du navigateur |
    | `14` | `captchaSessionToken` | Jeton de session interne |
    | `15` | `bftToken` | ... |
    
    ---
    
    ### Structure de `pmeta`
    
    Exemple :```js
    [
        "pmeta",
        [
            "/m/013xlm",
            null,
            3,
            3,
            3,
            null,
            "Tractor"
        ],
        null,
        [1]
    ]
    

    pmeta[1] Values

    PositionValeurDescription
    0/m/013xlmIdentifiant de catégorie interne pour la classe de l'objet cible
    23Nombre de colonnes de la grille
    33Nombre de lignes de la grille
    5nullChamp de métadonnées réservé ou optionnel
    6"Tractor"Étiquette textuelle

    Challenge Types

    TypeDescription
    imageselectCAPTCHA standard de sélection d'image
    tileselectDéfi dynamique d'image basé sur des tuiles
    dynamicDéfi dynamique où les tuiles se rechargent après la sélection
    multicaptchaDéfi CAPTCHA en plusieurs étapes
    audioDéfi d'accessibilité audio
    nocaptchaFlux de vérification par simple case à cocher
    doscaptchaRefuser le CAPTCHA en cas d'abus

    Challenge Image Retrieval

    La valeur à l'Idx 9 (challengeImageToken) est utilisée pour récupérer l'image CAPTCHA :```txt https://www.google.com/recaptcha//payload ?p= &k=

    root@kitploit:~
    ### Identifiants de catégorie
    
    | ID | Catégorie |
    |---|---|
    | `/m/0pg52` | Taxi |
    | `/m/01bjv` | Bus |
    | `/m/02yvhj` | Autobus scolaire |
    | `/m/04_sv` | Moto |
    | `/m/013xlm` | Tracteur |
    | `/m/01jk_4` | Cheminée |
    | `/m/014xcs` | Passage piéton |
    | `/m/015qff` | Feu de circulation |
    | `/m/0199g` | Vélo |
    | `/m/015qbp` | Parcomètre |
    | `/m/0k4j` | Voiture |
    | `/m/015kr` | Pont |
    | `/m/019jd` | Bateau |
    | `/m/0cdl1` | Palmier |
    | `/m/09d_r` | Montagne / colline |
    | `/m/01pns0` | Bouche d'incendie |
    | `/m/01lynh` | Escaliers |
    
    ## Payload de la requête UserVerify
    Le payload `/userverify` est soumis après que l'utilisateur ait terminé un défi d'image reCAPTCHA v2
    
    # Structure du payload```
    v: hsFBb1u5wWWWkWP4in1ua2cQ
    c: 03AFcWeA5RIHz5mI2COQqTcLjdrC7FiPpdfkX-hB-B2iFenI...
    response: eyJyZXNwb25zZSI6WzMsMSw0LDksMCwxMSwxMCwxMywxNF0....
    t: 24521
    ct: 24521
    ch: -4007845
    oc: 0ZpqzzPgYKEEaN0xpfo3v_voeVUySZK3Ktf_fLVRdhnu3yeTy4BhO...
    pm: 51bGwsbnVsbCxbbnVsbCxudWxsLG51bGwsWzEwLDQuMjcwMDAwMD....
    

    Components

    ChampNomDescription
    vrecaptchaVersionVersion reCAPTCHA
    cchallengeTokenJeton d'état du défi retourné par /replaceimage ou une requête précédente /userverify
    responseCharge utile encodée contenant les indices des tuiles sélectionnées et des métadonnées d'interaction supplémentaires
    tchallengeElapsedTemps écoulé depuis le chargement initial du défi
    ctcompletionTimeTemps total pris par l'utilisateur pour résoudre et soumettre le CAPTCHA
    chocHashHaché la totalité de la charge utile sérialisée oc, Exemple
    ocencryptedVmSignalsSignaux chiffrés collectés depuis la VM reCAPTCHA, voir ici.
    pmtelemetryPayloadStructure de télémétrie encodée en Base64 contenant les deltas de timing VM, les temporisations des ressources, les statistiques des objets du navigateur collectés et les métadonnées des scripts du site web

    response Charge utile

    Représente les indices/positions des carrés sélectionnés par l'utilisateur dans la grille

    La charge utile est ensuite encodée en JWT avant soumission


    Exemple de grille 3×3

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

    root@kitploit:~
    Exemple de charge utile :```json
    {
      "response": [2, 3, 6]
    }
    

    Exemple de grille MultiCaptcha 4×4

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

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

    Champ e

    La charge utile response peut également inclure un champ e :```json { "response": [2, 3, 6, 14], "e": "bxCoiXVt49I7CTS_tNlVbGg" }

    root@kitploit:~
    Ce champ contient des métadonnées d'interaction chiffrées liées aux actions des boutons CAPTCHA telles que :
    
    - `Vérifier`
    - `Suivant`
    - `Ignorer`
    
    ### Structure interne de `e`
    
    Après déchiffrement, la structure ressemble à :```txt
    [[["9ffd9672"]]]
    

    Chaque valeur représente un identifiant haché pour la classe/action de bouton rc-button-default

    Le hachage est :

    • Basé sur SHA-256
    • Tronqué à 8 caractères

    Des séquences d'interaction plus longues peuvent ressembler à :```txt [ [ ["9ffd9672"], ["9ffd9672"], ["9ffd9672"], ["9ffd9672"] ] ]

    root@kitploit:~
    ### `oc` — Signaux VM chiffrés
    
    Utilise le même algorithme de chiffrement que le champ `idx 16` de la charge utile de la requête `/reload`, avec la clé de chiffrement chargée dans l'ancre (index 31) `1777752103288`
    
    ### `pm` — Charge utile de télémétrie
    
    Le champ `pm` contient une structure de télémétrie encodée en Base64, similaire à la charge utile de télémétrie utilisée dans `/reload`.
    
     
    ## Anti-débogage/Altération
    - ***Étiquette d'intégrité basée sur les Symboles***
        reCAPTCHA attribue une clé Symbol `Symbol(jas)` à chaque tableau et objet avec une valeur numérique utilisée comme vérification d'intégrité. Étant donné que les Symboles ne sont pas énumérables et invisibles pour les opérations de clonage standard (comme JSON.stringify), toute tentative de remplacement ou de clonage de ces structures perd l'étiquette, ce que reCAPTCHA détecte comme une altération.
    
        ![tampon](https://raw.githubusercontent.com/elyelysiox/recaptcha/main/photos/849230834092888898.png)
    
    - ***Capture de variables de fermeture***
        Certaines valeurs sont intentionnellement définies dans la portée d'une fonction externe et consommées uniquement à l'intérieur de rappels ou de fermetures imbriqués ; la variable n'existe jamais dans la même portée que celle où elle est utilisée.
    
    - ***Vérifications temporelles***
        reCAPTCHA intègre des mécanismes de détection de débogage en cours d'exécution. S'il détecte que le code est analysé par un débogueur, il redémarre la session de débogage, ce qui entraîne la perte de l'état d'exécution et du contexte.
    
    - ***Onglet source de plantage***
    
        https://github.com/user-attachments/assets/4ae3bf68-5ae7-4adc-a0b9-36cc11b64998
      
        Ce bug se produit dans les navigateurs utilisant Chromium. Il existe plusieurs bugs qui provoquent la fermeture inattendue du navigateur ou des outils de développement, comme celui montré ici :
        
        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
        
        Par conséquent, l'un de ces bugs est très probablement déclenché lorsque le délai d'attente expire, car ce n'est probablement pas quelque chose qui se produirait dans le flux d'un véritable utilisateur.
    
    ## reCAPTCHA Botguard
    
    Bien que BotGuard ait été supprimé par Google, je vais expliquer un peu comment il fonctionne en interne pour ceux qui s'intéressent à ce qu'il est et à quel point il diffère des autres types de botguard.
    
    Premièrement, le processus de génération de token : la VM génère des tokens pour les erreurs persistantes lors de l'exécution. Ces erreurs peuvent être dues à des déviations de décalage de bytecode, des registres VM manquants, un état VM incorrect et une mauvaise intégrité du flux de contrôle. Ces erreurs sont capturées par le répartiteur, qui appelle une fonction qui écrit des octets pour le token.
    
    La VM utilise ARX Cipher, un algorithme créé par la NSA en 2013, similaire à Speck pour chiffrer les données. Il est également utilisé dans tous les Google BotGuard. L'algorithme change à chaque version, tout comme la constante (3990), l'ordre des opérations et les tours. Il ressemble à ceci :```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];
    }
    

    Écriture d'octets et chiffrement

    La fonction de chiffrement principale possède deux modes : chiffrement et non-chiffrement. Le mode chiffrement utilise ARX Cipher, Bitwise + XOR pour chiffrer les données et les placer dans un tampon. Il existe 4 types de tampons :

    • Tampon principal 180
    • Tampon de pad d'entropie 353
    • Tampon d'erreur 304
    • Tampon PoE (Preuve d'exécution) 243 (non utilisé dans ce type de botguard).

    Le mode non-chiffrement se contente de définir des octets déjà chiffrés dans le tampon.```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:~
    Et voici la fonction qui gère les erreurs et appelle le rédacteur d'octets.```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;
            }
        }
    }
    

    À la fin de l'exécution, la VM appelle la fonction principale qui prépare la charge utile avec ces tampons et génère le jeton, qui est une signature. Contrairement aux autres VM BotGuard, cette VM ne dispose pas d'un système d'empreinte, ni de Google Botguard, et n'effectue pas ces opérations d'émission d'erreurs + écriture d'octets, et est beaucoup plus simple et plus facile à rétro-ingéniérer.

    Avertissement

    Ce dépôt est exclusivement destiné à des fins éducatives et de recherche. Le code, les techniques et les concepts présentés ici sont destinés à l'étude académique et à la compréhension des sujets abordés.

    Hachage de toutes les clés des objets navigateur
    25W1tbNTAwNiw...Compteurs encodés en Base64 pour les événements d'interaction utilisateur tels que les mouvements de souris, les clics, le clavier et les changements de focus