Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
recaptcha — reCAPTCHAのドキュメントとリバースエンジニアリング | Kitploit
ツール/GitHubGitHub/elyelysiox/recaptcha
静的分析動的コード分析 (DAST)リバースエンジニアリングウェブセキュリティアンチボットCAPTCHAバイパス
GitHubelyelysiox/recaptcha

recaptcha

reCAPTCHAのドキュメントとリバースエンジニアリング

リポジトリを見る
227381ヶ月前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Description

このリポジトリは、Googleのアンチボット(reCAPTCHA)の技術的分析を含んでおり、以下に焦点を当てています。

  • ペイロード構造と値
  • フィンガープリンティング技術
  • 難読化技術
  • デバッグ防止/改ざん防止技術
  • 仮想マシン

Contact

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

Obfuscation Techniques

reCAPTCHAは、最も高度な難読化技術を備えたアンチボットシステムの1つであり、コードを読みづらくし、リバースエンジニアリングを困難にする一連の変換を適用しています。ほとんどの難読化は抽象構文木(AST)を使って容易に操作できますが、一部は実行時に処理されるため、ASTはこの場合無効になります。また、コードにはポリモーフィズムが適用され、スクリプトのバージョンごとに構造が変更されます。例えば、コードは直接アクションを実行せず、代わりに形を変えるオブジェクトや関数を使用します。

  • シーケンス式 コードは、各ブロック文を連続したカンマ区切りの式に変換することでフラット化されます。これはif文、関数引数、さらにはオブジェクト内にも現れます。 seq

  • 混合ブール算術 算術演算(加算、減算、乗算)とビット演算(AND、OR、XOR、NOT)を織り交ぜて元のロジックを隠します。例:-2 * ~(h & H) + -2 + (h ^ H)

  • 間接関数テーブル 各関数はテーブル内に構築され、そのインデックスを使って呼び出されます。例:functions[index](https://github.com/elyelysiox/recaptcha/blob/HEAD/args)

  • インライン定数配列 ローカル配列リテラルが式の途中でインラインに代入されます。この配列は関数本体全体でインデックスアクセスを通じて再利用される定数(数値、文字列)をグループ化します。

    root@kitploit:~
    // b = [14, 1, "call"] はシーケンス式内でインライン代入される
    function(Y, Q, c, l, G, X, W, J, b, P) {
        (Y & 94) == Y && (b = [14, 1, "call"], ...)
        W[b[2]](J, G)   // W.call(J, G)
        Y >> b[1] & b[0]  // Y >> 1 & 14
    }
    
  • 関数多重化 複数の論理的に異なる関数が1つに統合され、数値パラメータをブロックセレクタとして使用します。アクティブなブロックは、パラメータをビット単位の条件に対して評価することで決定されます。呼び出し元は数値リテラルをセレクタとして渡します。

    root@kitploit:~
    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // ブロック1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // 値を文字列に変換するロジック
        }
    
        // ブロック2
        if ((N + 4 & 40) >= N && (N + 5 & C[0]) < N) {
            Y = bB();
            throw Error(Y === void 0 ? "unexpected value " + U + y : Y);
        }
    
        return u;
    }
    
  • 論理演算子による分岐 if文やif/elseブロックを論理演算子の短絡評価で置き換え、制御フローを式に変換します。シーケンス式と組み合わせることで、複数の分岐が単一の連続したカンマ区切りの式として現れます。

    root@kitploit:~
    // if (a) { block }
    a && (block)
    
    // if (!a) { block }
    a || (block)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // CFFとシーケンス式の組み合わせ:
    (Y | 1) & 14 || (c = Q.O, J = c.O.length + c.g.length),
    (Y ^ 59) >> 3 == 3 && (Q.classList
        ? Q.classList.add(c)
        : Z[31](31, Q, c) || (l = f[0](84, "string", "", Q), ...)),
    
  • ネイティブメソッド定数のバインド ネイティブブラウザメソッドを元のレシーバにバインドし、改ざんを防ぐために定数として保存します。

    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)
    
  • デッドコード アクセス不能または未使用のコードブロックがファイル全体に注入され、サイズが60,000行以上になります。これにより、静的解析やLLMベースのリバースエンジニアリングが困難になります。

  • 制御フローの平坦化 コードの各部分(宣言やループ)をフラットな状態機械に変換します。すべてのコードブロックを中央の「ディスパッチャ」ブロック経由でルーティングすることで、元の実行ロジックを隠します。

    ディスパッチャは形を変えることができます。2〜3個の状態変数を持つものもあり、ループ/条件のタイプが変わります。次のようになります。

    cff1

    これは2つの状態変数を持つCFFで、1つはcatchブロック、もう1つはtryブロックを処理します。

  • 暗号化文字列プール すべての文字列リテラル(DOM API、ブラウザプロパティ、CSS値、エラーメッセージなど)は、単一の巨大な文字列プールに暗号化されます。復号関数はシードとLCGベースのXOR暗号を使用して、実行時に各文字列を抽出します。

    コード全体に1990以上の呼び出し箇所があり、復号関数はデコードされたコードポイントを累積するランニングキーを使用するため、各文字は以前のすべての文字に依存します。

    root@kitploit:~
    X = function(J, b, P, F, U) {
        U = ["codePointAt", 127, "char encrypted pool"];
        for (F = (P = 0, b = "", l); P < Q; P++)
            J = (U[2][U[0]](c + P) ^ F) & U[1],  // ランニングキーとのXOR
            b += String.fromCodePoint(J),
            F += J; // キーを累積
        return G = b;
    }
    
    // 呼び出し箇所は各文字列を特定して復号するためにシードを渡す
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • 状態を持つ値イテレータ reCAPTCHAは状態を持つ関数を使用し、固定された順序で一連のランタイムオブジェクトや値(window、document.body、数値定数など)を返します。呼び出しごとに内部カーソルが進み、順序を無視して呼び出したり、何度も呼び出すと後続の読み取りがすべて破損します。タイムアウト機構により、一定時間後に状態が無効になり、遅延読み取りではnullが返されます。

    root@kitploit:~
    // 順次呼び出しで異なる値が返る:
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (タイムアウト切れ)
    
    l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12)
    // ↑ window                     ↑ window
    
    10 * l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12))
    
    c().querySelectorAll(a[X[2]](98, X[1], X[1]))
    // ↑ document.body  
    
    
  • 計算関数テーブル これは間接関数テーブルと似ていますが、ここでは取得する関数のインデックスが実行時にシードを使ってXORとModulusで計算されます。

    root@kitploit:~
    c = ((Q ^ no | U[1]) >> 5) + no
    A = mN[(c % U[2] + U[2]) % U[2]]  // mNは関数テーブル(50以上の関数)
    
    root@kitploit:~
    q[29](5, 6977)   // seed=6977  → インデックスはmN[X]の関数に解決
    q[29](53, 6187)  // seed=6187  → 異なるインデックス、異なる関数
    

    computed

  • 実行時値暗号化 一部の値(captcha設定パラメータ、アンカーパラメータなど)はプレーンテキストで保存されることはなく、収集直後に暗号化され、使用時のみ復号されます。先頭に接頭辞Bが付きます。

    hiddenv

  • 非同期制御フロー難読化 同期ロジックは、再帰的なPromiseチェーンでラップされたジェネレータベースの状態機械に変換されます。デバッガで値をトレースすると、複数の非同期ハンドラをステップ実行することになり、各.then()の境界で元の実行コンテキストが失われます。

Anchor Payload/Response

Payload Structure

reCAPTCHAを初期化するためのコンポーネント``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

root@kitploit:~
### Response

応答には以下が含まれます:
- CAPTCHA iframe ウィンドウデザイン
- ペイロード検証に使用されるアンカートークン (/reload)
- 初期化のためのメイン設定で、`recaptcha.anchor.Main.init` メソッド内で実行され、recaptcha_en.js で受信します。

### Structure:

注:Recaptcha BotGuard は `04/01/2026` に削除されました。サンプルは [こちら](https://github.com/elyelysiox/recaptcha-payload/tree/main/botguard_scripts) でご確認いただけます。```javascript
[
    "ainput",
    [
        "bgdata",
        "",
        "LyogQW50aS1zcGFtLiBXYW50IHRvIHNheSBoZWxsbz8gQ29ud...", // BotGuard Script Base64-Encoded
        "YWVtZ0h5MGNCWXJDQ2lidGh0RW13RmhWdlc3aU5yeVpzSmx6U...", // BotGuard VM Bytecode Double Base64-Encoded 
        "wrB8fsOVU8K0YAzDsyQpw7ZHw6jDnMK1AMO6SRcvw53CsGlQw6/DuMO0wqr" // VM Config Bytecode Base64-Encoded
    ],
    null,
    [
        "conf",
        null,
        "6LfTV4gkAAAAACDVrUvp9_DalxUPvFSU7M2HJDO-", // Website Key
        0,
        null,
        null,
        null,
        1,
        // Indexes for fingerprinting or something else
        [16, 21, 125, 63, 73, 95, 87, 41, 43, 42, 83, 102, 105, 109, 121],
        [-7614991, 137],
        0,
        null,
        null,
        null,
        null,
        0,
        null,
        0,
        null,
        700, // Time Start for Time Variances of Fingerprint Values
        1,
        null,
        0,
        // Encoded metadata for the VM's main bytecode constructs
        "CvsCEg8I8ajhFRgAOgZUOU5CNWISDwjmjuIVGAA6BlFCb29IYxIPCMfm1DgYADoGZHhkTmlkEg8Is4qgOBgBOgZMV0o1a2ISDwiB7OgVGAA6Bkh1dlBqZhIPCK6e6zcYADoGR2JpT1FkEg8I94jmNxgAOgZvaWxlRGQSDwjwzeMVGAE6BmZJVkloYhIPCOLKoDcYAToGZ0xOQ0hjEg8I3r+3NxgBOgZlYXp1NmQSDwjY0oEyGAA6BkFxNzd2ZhIOCLjllDIYAToFUUJPRDASDwio7784GAA6BkdGVU5jZhIPCLWzqzgYAToGb3JZVjZkEg8I0tuVNxgAOgZmZmFXQWUSDwiV2JQyGAE6BlBxNjBuZBIPCKuRyjgYADoGQVo0TmJiEg8IxfOINxgAOgZhWG9pYWMSDwiNyoYyGAE6Bk93TjR0ZhIOCIr9iDcYADoFTWZJSTQaJwgDEiMdJv3NgTUZp4oJGYQKGZzijAIZzPMRGa+VQBnqsCYZ5a8MGQ==",
        0,
        1,
        null,
        null,
        1,
        null,
        null,
        0,
        null,
        null,
        0,
        0,
        "cf5e3c3a6ab6c494c829a7932d9577c1e6de862dd4912e55dc7fe2e40a1f7604"
    ],
    "https://who.clickbait.team:443", // Website URL:Port
    null,
    [
        3,
        1,
        1
    ],
    null,
    null,
    null,
    1,
    3600,
    [
        "https://www.google.com/intl/es/policies/privacy/",
        "https://www.google.com/intl/es/policies/terms/"
    ],
    "vQWNjTpMwdevQPWmE8akDzp8jsOZfa1VqTzVHaPiQ/c=",
    1,
    0,
    null,
    1,
    1777669303203, // Fingerprint Data Encryption Key
    0,
    0,
    [203], // Config Bytecode Key
    null,
    [185], // Config Bytecode Key
    "RC--rg1OSRnOD0ayA",
    null,
    null,
    null,
    null,
    null,
    // Bft Token, Used in reCAPTCHA V2
    "0dAFcWeA4RepD9zDjeMQE73pAT27pXZ7Nz_419U2K36QNqzHaKtLIDkwZQLi-Ud8OvSZHbDEcxQxusBQnsF5QQErMRpJMcUplaFg",
    1777752103288 // "oc" Data Encryption Key
]

フィンガープリント

値は最初のサンプルフィンガープリントの復号化された値に基づいています。こちらを参照してください。

フィンガープリント値の各サブフィールドには基本フォーマットがあります:

[value, key, elapsed]

ここで key は暗号化キーであり、elapsed はコレクターが値を取得して暗号化するのにかかった時間です。これにより、reCAPTCHAは以下を検出できます:

  • 過度に高速な実行
  • フック
  • ブレークポイントとサンドボックス

コレクターの実行順序

システムは内部スケジューラを使用します:``` [42, 45, 53, 30, 28, 54, 29, 31, 32, 33, 34, 35, 37, 36, 38, 39, 43, 40, 41, 46, 48, 57, 58, 60, 61, 62, 63, 64, 66, 68, 69, 71, 72, 79, 55]

root@kitploit:~
This represents:

- 実行順序
- コレクタパイプライン
- 信号生成シーケンス

### フィンガープリント信号コードと鍵導出
フィンガープリント信号を多段階導出パイプラインを通じて決定論的な暗号鍵に変換します

各フィンガープリント値は:

- 正規化され
- コンパクトな信号コードにエンコードされ
- 数値の暗号鍵に変換され
- 導出された鍵を使用して暗号化されます

このプロセスは決定論的であり、同じ入力値は常に同じ信号コードと暗号鍵を生成します```
Raw Value
   ↓
Signal Code Derivation
   ↓
Compact Signal Code
   ↓
Numeric Key Derivation
   ↓
Encryption Key
   ↓
Value Encryption

例

入力信号``` "BUTTON,195a81c9"

root@kitploit:~
***ステップ1 - 信号コードの導出***```javascript
deriveSignalCode("BUTTON,195a81c9")
// → "wg"

生成されたシグナルコードは、元の値に対するコンパクトな決定論的識別子です。

ステップ2 - 数値キーの導出```javascript deriveKey("wg") // → 3792

root@kitploit:~
信号コードは数値の暗号鍵に変換されます。

***ステップ3 — 値の暗号化***```javascript
encryptValueWithKey(3792, "wgia1z9pwq")
// → "bYVbh6BUsE_5pLA"

次の値は、コレクターの順序に従って、派生キーで暗号化されます。

集約フィンガープリント構造

すべての生成されたシグナルコードは、コンパクトなシリアライズ構造に集約されます。

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

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

Signals

  • Idx 4 (string)

    • Value: 3ccb

    • Hashed: true

    • 説明: window.localStorage.getItem("rc::a") + "6d" をバイト列に変換したものから HMAC 鍵を生成し、その鍵で HMAC-SHA256(siteKey) を計算し、結果の先頭 4 文字の 16 進数文字列を返します。

      rc::a の値はランダム生成された base64 です。

  • Idx 5 (integer)

    • Value: window.localStorage.length * 2
    • Hashed: false
    • 説明: window.localStorage の長さを 2 倍した値
  • Idx 16 (string)

    • Value: yM5Us/j/fn6EDgtmPlP4Pxj605nMJN9dRYHyy5Mn


特定の reCAPTCHA シグナルは利用不可であるか、収集に失敗する場合があります (デバッグ関連のタイムアウトによる)。その場合、欠落したシグナルはランダムに生成された base64 エンコード値で埋められます。例:``` ["CMXZyamk3ZHNjdGsyaQ==", 3249, 591]

root@kitploit:~
指紋構築が完了すると、それは文字列にシリアライズされ、アンカーフィールド(インデックス18)から読み込まれた暗号化キーを使用して暗号化されます。暗号化された結果は、`/reload` ペイロードのインデックス`16`フィールドに保存されます。

## VM シグナル
以下は、内部 reCAPTCHA VM によって取得されたブラウザの値と、シグナルキーです。一部の値はサンプルフィンガープリントに表示されていません。これは、VM が構成バイトコードから特定の値のみを抽出するためです。そのため、他の値が表示されます。詳細については、[こちら](https://github.com/elyelysiox/recaptcha-vm) を参照してください。

基本シグナル形式:```
[
  null,
  collectorElapsed,
  encryptElapsed,
  value
]

ここで、collectorElapsed はコレクターが値を取得するのにかかった時間(ms)を意味します そして、encryptElapsed は値の暗号化にかかった時間(ms)を意味します。 これらの時間は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: 完全なブラウザのユーザーエージェント

- **Key 727** (`array`)
  - Value: `[]`
  - Description: 製品価格ブロック。ウェブサイト上の商業製品の価格を含みます。これらはAmazon、eBay、AliExpressなどのマーケットプレイスウェブサイトに表示される可能性があります。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/findProductPricesBlock.js)

- **Key 150** (`array`)
  - Value: `[\"Join And Get Free Trial!\",\"\",\"Captcha Solving Service\",\"Prod...`
  - Description: ウェブサイトの`<a>`要素から抽出されたリンク。VMがこれらの値を抽出することは稀です

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

- **Key 370** (`integer`)
  - Value: `0`
  - Description: 最大デバイスタッチポイント `navigator.maxTouchPoints`

- **Key 779** (`array`)
  - Value: `[null,null,null,null,"false"]`
  - Description: 配送/請求フィールドからデータを抽出します。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/formFieldScrape.js)
  
    `postal|postalcode|postalcode|postal_code|zip` → 郵便番号フィールドを検索
    
    `ship|deliver` → 配送セクション
    
    `billing|payment|credit` → 請求セクション
    
    `country` → 国セレクター
    
    `addr.*(match|equal)|(match|equal).*address` → 「住所が同じ」チェックボックス
    
    各要素のname、id、autocomplete、classNameを読み取ります
    3つのフェーズ: テキスト入力、SELECT要素、チェックボックス

- **Key 659** (`array`)
  - Value: `[[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]`
  - Description: ページ上で押された要素のデータを以下の形式で含みます: `[[[count,timestamp]],[[hashedElem,tagType,type,autoComplete]],pressedCount,behaviorChecksum]`
 
    ### 要素タイプ
    
    | 要素タイプ | ID |
    |-------------|----|
    | `""` | 1 |
    | `text` | 2 |
    | `button` | 3 |
    | `submit` | 4 |
    | `checkbox` | 5 |
    | `email` | 6 |
    | `password` | 7 |
    | `select-one` | 8 |
    | `select-multiple` | 9 |
    | `radio` | 10 |
    | `textarea` | 11 |
    | `file` | 12 |
    | `tel` | 13 |
    | `number` | 14 |
    | `date` | 15 |
    | `reset` | 16 |
    | `range` | 17 |

    ### 動作チェックサムアルゴリズム
    
    behaviorChecksumは、収集されたユーザーインタラクションデータから導出されるコンパクトな動作スコアです。
 
    各インタラクションについて:
    - インタラクションインデックスは1ずつ増加
    - タイムスタンプは調整されたインタラクションインデックスと結合
    - 要素ハッシュはモジュロ演算で縮小
    - 結果は実行中のスコアに累積
   
    ---

    ```javascript
    function computePressedElementsChecksum(pressedElementsArray) {
      let accumulator = 0;
    
      for (const [countTimestampPair, elementInfo] of zip(
        pressedElementsArray[0],
        pressedElementsArray[1],
      )) {
        const shiftedTimestamp = countTimestampPair[0] + 1;
        const baseValue = countTimestampPair[1] + shiftedTimestamp;
        const remainder = elementInfo[0] % baseValue;
        accumulator = remainder + accumulator;
      }
    
      const logTerm = Math.log(accumulator + 1) * 4;
      const modTerm = accumulator % 10;
      const behaviorChecksum = Math.floor(logTerm + modTerm);
    
      return JSON.stringify(pressedElementsArray);
    }

    function zip(a, b) {
      const length = Math.min(a.length, b.length);
      const result = [];
      for (let i = 0; i < length; i++) {
        result.push([a[i], b[i]]);
      }
      return result;
    }
    ```

    ### 例

    ```javascript
    const checksum = computePressedElementsChecksum([[[0,921],[1,2053]],[[235054,1,1,1],[164277,3,4,1]],2,39]);
    console.log(checksum); // → 39
    ```

- **Key 959** (`array`)
  - Value: `[[[0,0,979]],1,0]`
  - Description: ページセッション中に収集されたスクロール動作を含みます
 
    ### 基本形式
    ```
    [ [ [ scrollX, scrollY, timestamp ] ], count, behaviorChecksum ]
    ```

- **Key 895** (`array`)
  - Value: `[[[1,0]]]`
  - Description: `VisibilityStateEntry`はページの可視性ステータスを追跡し、ユーザーが現在ページを閲覧中か、または別のページに移動したかを示します。形式: `[[[isVisible, startTime]]]`

- **Key 1092** (`array`)
  - Value: `[886,2300,262.2099999997952,392.7600000009595,2050.2399999993577]`
  - Description: reCAPTCHAのパフォーマンス、PerformanceNavigationTimingおよびPerformanceEventTiming。形式: `[vmStart,vmEnd,domContentLoadedEventEnd,loadEventEnd,firstUserInteractionTime]`

- **Key 41** (`array`)
  - Value: `[[[1123,0,0]]]`
  - Description: タイムアウトクリア

- **Key 43** (`array`)
  - Value: `[[[1123,0]]]`
  - Description: タイムアウトクリア

- **Key 549** (`array`)
  - Value: `[0,null,null,null,null,null,null]`
  - Description: KeyboardEvent、計算されたキー+タイムスタンプ

- **Key 352** (`array`)
  - Value: `1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],...`
  - Description:
    構造は以下を含みます:

    - マウス移動のタイミング
    - カーソル座標
    - クリック時間
    - 押された要素の寸法
    - ポインタタイプ情報
    - 圧力メトリクス
    - カーソル移動距離
    - 動作タイミング統計

    ### 基本形式:
    ```
    [
      eventsCount,
      mouseEvents,
      [
        coalescedEventsCount,
        averageInterEventDelay,
        timingVarianceScore
      ],
      [
        totalPoints,
        clickSequenceScore,
        totalCursorDistance,
        totalPoints
      ],
      0,
      0,
      behaviorChecksum
    ]
    ```
    
    ### マウスイベント構造:
    
    mouseEvents内の各エントリは以下の構造に従います:
    
    ```
    [
      timestamp,
      clickDuration,
      clientX,
      clientY,
      [
        elementLeft,
        elementTop,
        elementWidth,
        elementHeight
      ],
      elementTagType,
      trackedElementIndex,
      pressure,
      pointerTravelDistance,
      pointerArea
    ]
    ```

    | 名前 | 説明 |
    |---|---|
    | `timestamp` | イベント開始からの相対タイムスタンプ |
    | `clickDuration` | `pointerdown`から`pointerup`までの時間 |
    | `clientX` | ... |
    | `clientY` | ... |
    | `elementBounds` | インタラクトされた要素のバウンディング矩形 |
    | `elementTagType` | インタラクトされた要素のエンコードされたDOMタグ識別子 |
    | `trackedElementIndex` | ランタイムインタラクションマップからのインタラクトされたDOM要素の内部識別子 |
    | `pressure` | 正規化されたポインタ圧力値に`100`を乗算 |
    | `pointerTravelDistance` | `pointerdown`から`pointerup`までの移動距離 |
    | `pointerArea` | `width * height`で計算された接触面積 |

    ### 要素タグタイプ

    これはreCAPTCHA VMの実行中に初期化されます

    | タイプ      | ID |
    |-----------|----|
    | `BODY`    | 1  |
    | `INPUT`   | 2  |
    | `BUTTON`  | 3  |
    | `SELECT`  | 4  |
    | `TEXTAREA`| 5  |
    | `FORM`    | 6  |
    | `A`       | 7  |
    | `AREA`    | 8  |
    | `AUDIO`   | 9  |
    | `VIDEO`   | 10 |
    | `IFRAME`  | 11 |
    | `DIV`     | 12 |
    | `SPAN`    | 13 |
    | `LABEL`   | 14 |

    ### 例
    ```
    [
      18342,
      91,
      742,
      381,
      [700, 320, 120, 38],
      3,
      1,
      50,
      1.4,
      16
    ]
    ```
    
    表す内容:
    
    - `18.342s`のイベント
    - `91ms`のクリック時間
    - `(742, 381)`でのクリック
    - `BUTTON`とのインタラクション
    - ポインタ圧力 `0.5` (50)
    - クリック中のわずかなカーソル移動
    - ポインタ接触面積 `16`
   
    ### 動作チェックサムアルゴリズム
 
    各マウスイベントについて:

    - クリック時間を増幅
    - その結果をイベントタイムスタンプと結合
    - カーソル座標と要素寸法を混合
    - 加重比率を計算
    - 比率を丸めて累積
    
    すべてのイベントが処理された後:
    
    - 累積スコアを総カーソル移動距離と結合
    - 結果を収集ポイント数で正規化
    - 対数変換を適用
    - 追加の移動統計を組み込む
    - 最終値をモジュロ演算で縮小
    - 結果を小さな整数スコアに丸める
    
    ---
    
    ```javascript
    function computeMouseBehaviorChecksum(mouseDataArray) {
      let totalSum = 0;
    
      for (let i = 0; i < mouseDataArray[1].length; i++) {
        const event = mouseDataArray[1][i];
    
        const scaledClickDuration = event[1] * 4;
        const xPlusScaledDuration = event[0] + scaledClickDuration;
        const combinedElementDims = event[2] + event[4][2] + event[4][1]; // clientY + elementWidth + elementTop
        const product = xPlusScaledDuration * combinedElementDims;
        const divisor = event[3] + event[4][3] + event[4][0] + 1; // elementTagType + elementHeight + elementLeft + 1
        const roundedValue = Math.round(product / divisor);
    
        console.log(roundedValue);
        totalSum += roundedValue;
      }
    
      const summaryArray = mouseDataArray[3]; // [totalPoints, clickSequenceScore, totalCursorDistance, totalPoints]
      const sumPlusCursorDistance = totalSum + summaryArray[2];
      const totalPointsPlusOne = summaryArray[0] + 1;
      const ratio = sumPlusCursorDistance / totalPointsPlusOne;
      const ratioPlusOne = ratio + 1;
      const logRatio = Math.log(ratioPlusOne);
      const scaledLog = logRatio * 4;
      const ratioPlusTotalPoints = ratio + summaryArray[0];
      const ratioPlusTotalPointsPlusScore = ratioPlusTotalPoints + summaryArray[1];
      const modResult = ratioPlusTotalPointsPlusScore % 11;
      const behaviorChecksum = Math.round(scaledLog + modResult);
      return JSON.stringify(mouseDataArray);
    }
    ```

    ### 例

    ```javascript
    const checksum = computeMouseChecksum([1,[[2050,125,633,266,[609,266,105,44],3,1,50,1,1]],[3,3,318],[28,777,858,28],0,0,25]);
    console.log(checksum); // → 25
    ```

- **Key 360** (`string`)
  - Value: `""`
  - Description: 収集されたウェブサイト価格合計$の解析、正規表現 `(?i)total[\S\s]{0,20}?(?:(?:(?:USD|\$)\s*)?[\d\.,]+\s*(?:USD|\$)|(?:USD|\$)\s*[\d\.,]+)` を使用。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/websitePricesTotal.js)

- **Key 1278** (`integer`)
  - Value: `229.6`
  - Description: 現在のランタイムタイミングを10で割った値 `Math.trunc(performance.now()) / 10`
    
- **Key 1422** (`boolean`)
  - Value: `false`
  - Description: ウェブサイトにOTP/2FAフィールドがあるかどうかを解析します。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/parseOTPFields.js)

- **Key 614** (`array`)
  - Value: `[1,0,0,Infinity]`
  - Description: デバイスのバッテリー情報。形式: `[level,isCharging,chargingTime,dischargingTime]`

- **Key 2033** (`array`)
  - Value: `["0",-1,-1,999]`
  - Description: 一部のVM定数値とVMランタイムタイミング

- **Key 1313** (`array`)
  - Value: `["undefined",3]`
  - Description: 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: WebGLレンダラー、ベンダー、総拡張数。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/webglSignals.js)

- **Key 291** (`array`)
  - Value: `[1542343452,0,105002991,3556653,96784904,-731949068,-902263026,...`
  - Description: ブラウザオブジェクトの特定のプロトタイプキーのハッシュ値。例: `SpeechSynthesisEvent`、`NetworkInformation`、`HTMLElement`など。[サンプル](https://github.com/elyelysiox/recaptcha/blob/main/hashBrowserProtos.js)

## リロードリクエストペイロード

このデータは、Googleが開発した構造化データを効率的かつ中立的にシリアル化する方法であるprotobuf(Protocol Buffers)を使用してシリアル化されています。```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,
]

コンポーネント

チャレンジモード

値説明
qreCAPTCHA V3 チャレンジ
fireCAPTCHA V2/不可視チャレンジ
a音声チャレンジ
qr

テレメトリペイロード(Idx 20)

デコード方法:```javascript atob("W1tbMywwLDgyOV0sWzEs...") // → [[[3,0,829],[1,42,863]],[[2,727,1341.300000011921]...

root@kitploit:~
ペイロードには以下が含まれます:

- リソースタイミング情報
- 長時間タスクのパフォーマンスタイミング
- reCAPTCHA VM実行デルタ
- ウェブサイトのスクリプトURL
- ブラウザオブジェクト収集統計

### 基本構造```js
[
  [recaptchaResources],
  [tasksTiming],
  [
      null,
      null,
      null,
      idleTimeoutDelta,
      deltaTiming,
      0,
      0,
      0,
  ],
  websiteScriptsUrls,
  [collectionElapsed, browserObjectsLength]
]

長いタスクのタイミング形式```js

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

root@kitploit:~
### reCAPTCHA リソースタイミングフォーマット```js
[
   resourceType,
   duration,
   startTime
]
Resource

イベントカウンター(Idx 25)

このフィールドには、実行中に収集されたブラウザインタラクションイベントのBase64エンコードされたカウンターが含まれています

デコード例:```js [ [ [5006, 43], [64607, 1], [45464, 1], [35837, 1] ] ]

root@kitploit:~
### イベントカウンター構造```js
[
  [
    [eventType, count]
  ]
]

既知のイベントハッシュ

レスポンス構造```js

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

root@kitploit:~
## フィールド説明

| インデックス | 名前 | 説明 |
|---|---|---|
| `0` | `rresp` | リロードエンドポイントから返される応答タイプ識別子 |
| `1` | `responseToken` | reCAPTCHA応答トークン |
| `3` | `tokenExpiration` | トークンの有効期限までの秒数 |
| `4` | `pmeta` | CAPTCHAの種類、カテゴリ、グリッドレイアウトに関する情報を含むチャレンジメタデータブロック |
| `5` | `challengeType` | CAPTCHAチャレンジの種類 |
| `8` | `usagePatternToken` | 使用パターン。`window.sessionStorage`に保存され、将来の`/reload`リクエストで再利用される |
| `9` | `challengeImageToken` | `/payload`エンドポイントからCAPTCHA画像ペイロードを取得するためのトークン |
| `12` | `humanVerificationToken` | Google reCAPTCHAの状態とブラウザのCookieに関連付けられた人間識別トークン |
| `14` | `captchaSessionToken` | 内部セッショントークン |
| `15` | `bftToken` | ... |

---

### `pmeta`構造

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

pmeta[1] 値


チャレンジタイプ


チャレンジ画像の取得

Idx 9(challengeImageToken)の値は、CAPTCHA画像を取得するために使用されます:```txt https://www.google.com/recaptcha//payload ?p= &k=

root@kitploit:~
### カテゴリ識別子

| ID | カテゴリ |
|---|---|
| `/m/0pg52` | タクシー |
| `/m/01bjv` | バス |
| `/m/02yvhj` | スクールバス |
| `/m/04_sv` | オートバイ |
| `/m/013xlm` | トラクター |
| `/m/01jk_4` | 煙突 |
| `/m/014xcs` | 横断歩道 |
| `/m/015qff` | 信号機 |
| `/m/0199g` | 自転車 |
| `/m/015qbp` | 駐車メーター |
| `/m/0k4j` | 自動車 |
| `/m/015kr` | 橋 |
| `/m/019jd` | ボート |
| `/m/0cdl1` | ヤシの木 |
| `/m/09d_r` | 山 / 丘 |
| `/m/01pns0` | 消火栓 |
| `/m/01lynh` | 階段 |

## UserVerify リクエストペイロード
`/userverify` ペイロードは、ユーザーが reCAPTCHA v2 画像チャレンジを完了した後に送信されます

# ペイロード構造```
v: hsFBb1u5wWWWkWP4in1ua2cQ
c: 03AFcWeA5RIHz5mI2COQqTcLjdrC7FiPpdfkX-hB-B2iFenI...
response: eyJyZXNwb25zZSI6WzMsMSw0LDksMCwxMSwxMCwxMywxNF0....
t: 24521
ct: 24521
ch: -4007845
oc: 0ZpqzzPgYKEEaN0xpfo3v_voeVUySZK3Ktf_fLVRdhnu3yeTy4BhO...
pm: 51bGwsbnVsbCxbbnVsbCxudWxsLG51bGwsWzEwLDQuMjcwMDAwMD....

コンポーネント

response ペイロード

グリッド内でユーザーが選択した正方形のインデックス/位置を表します。

ペイロードは送信前に JWT としてエンコードされます。


3×3 グリッドの例

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

root@kitploit:~
ペイロード例:```json
{
  "response": [2, 3, 6]
}

4×4 MultiCaptcha グリッドの例

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

root@kitploit:~
ペイロードの例:```json
{
  "response": [2, 3, 6, 14]
}

e フィールド

response ペイロードには e フィールドも含まれる場合があります:```json { "response": [2, 3, 6, 14], "e": "bxCoiXVt49I7CTS_tNlVbGg" }

root@kitploit:~
このフィールドには、CAPTCHAボタン操作に関連する暗号化されたインタラクションメタデータが含まれています。例:

- `確認`
- `次へ`
- `スキップ`

### `e`の内部構造

復号後、構造は次のようになります:
``````txt
[[["9ffd9672"]]]

各値は、rc-button-default ボタンのクラス/アクションに対するハッシュ化された識別子を表します。

ハッシュは次の通りです:

  • SHA-256ベース
  • 8文字に切り詰め

より長いインタラクションシーケンスは次のようになります:```txt [ [ ["9ffd9672"], ["9ffd9672"], ["9ffd9672"], ["9ffd9672"] ] ]

root@kitploit:~
### `oc` — 暗号化されたVMシグナル

`/reload`リクエストペイロードの`idx 16`フィールドと同じ暗号化アルゴリズムを使用し、暗号化キーはアンカー(インデックス31)`1777752103288`にロードされています。

### `pm` — テレメトリペイロード

`pm`フィールドには、`/reload`で使用されるテレメトリペイロードと同様のBase64エンコードされたテレメトリ構造が含まれています。

 
## アンチデバッグ/改ざん対策
- ***シンボルベースの整合性タグ***
    reCAPTCHAは、整合性チェックに使用される数値を持つすべての配列とオブジェクトにSymbolキー`Symbol(jas)`を設定します。Symbolは列挙不可であり、標準的なクローン操作(JSON.stringifyなど)では不可視であるため、これらの構造を置き換えたりクローンしようとするとタグが失われ、reCAPTCHAはそれを改ざんとして検出します

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

- ***クロージャ変数のキャプチャ***
    一部の値は意図的に外部関数でスコープされ、ネストされたコールバックやクロージャ内でのみ消費されるため、変数は使用されるスコープには決して存在しません

- ***タイミングチェック***
    reCAPTCHAは実行時デバッグ検出メカニズムを組み込んでいます。コードがデバッガによって分析されていることを検出すると、デバッグセッションを再起動し、実行状態とコンテキストが失われます

- ***クラッシュソースタブ***

    https://github.com/user-attachments/assets/4ae3bf68-5ae7-4adc-a0b9-36cc11b64998
  
    このバグはChromiumを使用するブラウザで発生します。ここに示すように、ブラウザや開発者ツールが予期せず閉じる原因となるバグがいくつかあります:
    
    https://blog.castle.io/detect-and-crash-chromium-bots-with-one-weird-trick-bots-hate-it/ 
    https://issues.chromium.org/issues/340836884?ref=blog.castle.io
    
    したがって、タイムアウトが発生するとこれらのバグのいずれかがトリガーされる可能性が高く、実際のユーザーフローでは起こりそうにありません

## reCAPTCHA Botguard

BotGuardはGoogleによって削除されましたが、内部でどのように動作し、他のタイプのBotGuardとどのように異なるのかに興味がある方のために少し説明します。

まず、トークン生成プロセス:VMは実行中の永続的なエラーに対してトークンを生成します。これらのエラーは、バイトコードオフセットのずれ、VMレジスタの欠落、VM状態の誤り、制御フロー整合性の低下などが原因で発生します。これらのエラーはディスパッチャによってキャプチャされ、トークンのバイトを書き込む関数を呼び出します。

VMはARX暗号を使用します。これは2013年にNSAによって作成されたアルゴリズムで、データの暗号化にSpeckに似ています。また、すべてのGoogle BotGuardで使用されています。アルゴリズムはバージョンごとに変更され、定数(3990)、演算順序、ラウンド数も変わります。次のようになります:```javascript
/*
D -> cipher state array
P -> seed
E -> byte index
*/
Vl = function(D, P, E, F, v) {
    F = D[3] | 0;
    D = D[2] | 0;
    for (v = 0; v < 14; v++) {
        E = E >>> 8 | E << 24;
        E += P | 0;
        E ^= D + 3990;
        P = P << 3 | P >>> 29;
        P ^= E;
        F = F >>> 8 | F << 24;
        F += D | 0;
        F ^= v + 3990;
        D = D << 3 | D >>> 29;
        D ^= F;
    }
    return [P >>> 24 & 255, P >>> 16 & 255, P >>> 8 & 255, P >>> 0 & 255, E >>> 24 & 255, E >>> 16 & 255, E >>> 8 & 255, E >>> 0 & 255];
}

バイトライターと暗号化

メインの暗号化機能には、暗号化モードと非暗号化モードの2つがあります。 暗号化モードでは、ARX Cipher、Bitwise + XORを使用してデータを暗号化し、バッファに設定します。 バッファには4つのタイプがあります:

  • メインバッファ 180
  • エントロピーパッドバッファ 353
  • エラーバッファ 304
  • PoE(実行証明)バッファ 243(このタイプのボットガードでは使用されません)

非暗号化モードでは、既に暗号化されたバイトをバッファに設定するだけです。```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:~
そして、これはエラーを処理してバイトライターを呼び出す関数です。```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;
        }
    }
}

At the end of the execution, the VM calls the main function that prepares the payload with these buffers and generates the token, which is a signature. Unlike other BotGuard VM, this VM does not have a fingerprinting system, Google Botguard nor does it perform these error-emitting + writing bytes, and is much simpler and easier to reverse engineer.

Disclaimer

This repository is exclusively for educational and research purposes. The code, techniques, and concepts presented here are intended for the academic study and understanding of the topics covered.

ツールをダウンロード
  • Hashed: true

  • 説明: すべての <HEAD> ノードの 40 文字 base64 ブルームフィルタフィンガープリント。各子要素を走査してタグ名、属性、テキストコンテンツを収集し、シリアライズして djb2 ハッシュを実行します。

    各ダイジェストは BitHash(240 ビット, 7 ラウンド, 最大 25 ノード) に投入され、40×6 のグリッドにビットを設定し、各 6 ビットセグメントを base64 文字にエンコードします。reCAPTCHA 自身のスクリプトタグは src に対する動的正規表現により除外されます。

  • Idx 17 (integer)

    • Value: 2
    • Hashed: false
    • 説明: サードパーティ Cookie の保存/読み取りアクセスが可能かどうかを確認します。サンプル
  • Idx 18 (string)

    • Value: a2hyNTFuNDI4NnA3
    • Hashed: false
    • 説明: Base64 でエンコードされたランダム生成値
  • Idx 27 (string)

    • Value: location.origin
    • Hashed: false
    • 説明: ウェブサイトの URL。
  • Idx 28 (boolean)

    • Value: false
    • Hashed: false
    • 説明: window.parent != window ? true : window.frameElement != null ? true : false
  • Idx 29 (string)

    • Value: e2a3cd70
    • Hashed: true
    • 説明: grecaptcha.execute 関数の本体を SHA-256 でハッシュ化したもの。サンプル
  • Idx 30 (integer)

    • Value: 0
    • Hashed: false
    • 説明: reCAPTCHA スクリプト https://www.gstatic.com/recaptcha/releases/<version>/ を含むスクリプトのインデックス。サンプル
  • Idx 31 (string)

    • Value: AAgkAQI0SB
    • Hashed: true
    • 説明: document.cookie のキーをハッシュ化したもの。サンプル
  • Idx 32 (string)

    • Value: ""
    • Hashed: false
    • 説明: リファラー URL document.referrer。
  • Idx 33 (integer)

    • Value: 2

    • Hashed: false

    • 説明: reCAPTCHA ボックスがレンダリングされる要素。

      root@kitploit:~
      // 例: grecaptcha.execute('.grecaptcha') -> この div
      // 基本的に、その div の文書内での番号または深さを返します。
      
      // 例: html > body > main > form > fieldset > div.recaptcha.form-field
      // 5 4 3 2 1 0
      // out = 5
      
      nM = document.getElementsByClassName('grecaptcha-badge')[0] // または document.getElementsByClassName('g-recaptcha')[0] v2
      let count = 0;
      for (; nM = nM.parentElement || null;) {
        count++;
      }
      
      const result = count;
      
  • Idx 34 (string)

    • Value: AAAAAAAAAA
    • Hashed: true
    • 説明: すべての <INPUT> 属性名をハッシュ化したもの。サンプル
  • Idx 35 (string)

    • Value: 0,DIV,f0c7414e
    • Hashed: true
    • 説明: document.activeElement を解析し、正規表現 /buy|pay|place|order|donate|purchase/i を使って textContent, classNames, id から購入要素かどうかを判定。サンプル
  • Idx 36 (string)

    • Value: h3, h2 または http/1.1
    • Hashed: false
    • 説明: ナビゲーションパフォーマンスの nextHopProtocol 値 performance.getEntriesByType("navigation")[0].nextHopProtocol
  • Idx 37 (integer)

    • Value: -1
    • Hashed: false
    • 説明: performance.timing.unloadEventStart
  • Idx 38 (integer)

    • Value: 96
    • Hashed: false
    • 説明: DNS ルックアップ時間 performance.timing.domainLookupStart - performance.timing.domainLookupEnd
  • Idx 39 (integer)

    • Value: 0
    • Hashed: false
    • 説明: ナビゲーションタイプ performance.navigation.type
  • Idx 40 (integer)

    • Value: 0
    • Hashed: false
    • 説明: 最後のスクロール Y 位置 window.scrollY または document.defaultView.pageYOffset
  • Idx 41 (string)

    • Value: DIV,a08cd360
    • Hashed: true
    • 説明: その瞬間にマウスが位置していた :hover 要素。最後の要素を取得し、tagName, classNames, id をハッシュ化。サンプル
  • Idx 42 (string)

    • Value: 9,e3b0c442
    • Hashed: true
    • 説明: ランダムなテキストスクリプトを SHA-256 でハッシュ化し、インデックスを加えたもの。サンプル
  • Idx 44 (string)

    • Value: 2v591z63wq
    • Hashed: true
    • 説明: :hover 要素、document.activeElement、すべての <INPUT> 要素のハッシュ、location.url、window.scrollY。例:
    • root@kitploit:~
      const element = document.querySelectorAll(":hover");
      const current = element[element.length - 1];
      
      const result = [
          deriveSignalCode(hash(current)),
          deriveSignalCode(hash(document.activeElement)),
          deriveSignalCode(hash(document.querySelectorAll('input'))),
          deriveSignalCode(location.url),
          deriveSignalCode(String(window.scrollY))
      ].join('')
      
  • Idx 45 (integer)

    • Value: 4
    • Hashed: false
    • 説明: window.history の長さ。
  • Idx 46 (string)

    • Value: https://static.kogstatic.com/0000/34c...
    • Hashed: false
    • 説明: ページ上のスクリプトでエラーが発生し、その line:column の情報。
  • Idx 47 (integer)

    • Value: 0
    • Hashed: false
    • 説明: ユーザーがページ上で現在選択しているテキストの長さを返します window.getSelection().toString().length || 0
  • Idx 49 (string)

    • Value: h2-0
    • Hashed: false
    • 説明: reCAPTCHA スクリプトの Performance Resource Timing エントリを見つけ、その nextHopProtocol を取得し、duration がゼロかどうかを判定します。結果を protocol-isZero の形式で返します。サンプル
  • Idx 50 (array)

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

    • Hashed: true

    • 説明: ユーザーの動作を含みます。ハッシュ化された :hover 要素と、別の :hover 要素が収集されるたびに増加するタイムアウト。ユーザーのアクティベーションを分析し、(10 * IsActive + IsBeenActive) を計算して、ユーザーがページとインタラクションした回数や現在もページ上に存在するかを累積します。

      基本フォーマット:

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

    • Value: [0]
    • Hashed: false
    • 説明: document.body.innerText から "try again", "incorrect", "invalid", "declined" の単語と一致するものを検索し、見つかった一致の総数を返します。それ以外の場合は 0 を返します。サンプル
  • Idx 52 (integer)

    • Value: 11
    • Hashed: false
    • 説明: 10 * navigator.userActivation.isActive + navigator.userActivation.hasBeenActive
  • Idx 53 (integer)

    • Value: 4

    • Hashed: false

    • 説明: 現在のウェブサイト URL を取得し、文字配列に変換して 100 文字に切り詰め、その後文字列に戻します。サンプル

      その切り詰めた文字列の長さが偶数の場合は 5、奇数の場合は 4 になります。

  • Idx 54 (boolean)

    • Value: false
    • Hashed: false
    • 説明: ドキュメントがユーザーから隠されているかどうか、つまり画面に表示されていないかどうかを示します。window.document.hidden
  • Idx 55 (array)

    • Value: [[[1,"2v"],[1,"9z"],[1,"z8"],[1,"us"],[1,..
    • Hashed: false
    • 説明: フィンガープリント値による生成されたシグナルコードの順序付け。
  • Idx 56 (string)

    • Value: -1,-1
    • Hashed: false
    • 説明: window.opener のチェック。null の場合は "-1,-1" を返します。サンプル
  • Idx 57 (string)

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

    • Hashed: false

    • 説明: document.scripts に存在するすべての <SCRIPT> 要素の src からホストを収集します。サンプル

      各 <SCRIPT> について: 要素に src 属性がある場合 (hasAttribute("src"))、src の値を取得し、URI タイプの正規表現 (nd) でパースし、ホスト部分のみを抽出します (正規表現のキャプチャグループ 3)。

      <SCRIPT> に src 属性がない場合 (インラインスクリプト)、プレースホルダー "_" が使用されます。

  • Idx 58 (string)

    • Value: mapslitepromosdismissed1
    • Hashed: false
    • 説明: サンプリングされた window.localStorage のキー。
  • Idx 59 (string)

    • Value: ""
    • Hashed: false
    • 説明: ウィンドウまたはタブのナビゲーションコンテキストの名前 window.name
  • Idx 60 (string)

    • Value: https://www.kogama.com,https://www.google.com,https://js.stripe.com
    • Hashed: false
    • 説明: メッセージイベントを開くための URL。例
  • Idx 61 (array)

    • Value: [0,"AAAAAAAAAA","AAAAAAAAAA"]
    • Hashed: true
    • 説明: MutationObserver によって記録された属性名とターゲット要素タイプのハッシュ。サンプル
  • Idx 62 (string)

    • Value: document.title
    • Hashed: false
    • 説明: ウェブサイトの完全なタイトル。
  • Idx 63 (array)

    • Value: []

    • Hashed: false

    • 説明: Cookie の値からタイムスタンプ (1[2-9] で始まる 12-13 桁の数字、典型的には ~2008-2099 年のエポックミリ秒) を抽出します。サンプル

      見つかったすべての ID に対して次の値を累積します: カウント、最小値、最大値、平均値。 最終的な値の結果は配列 [count, min, max, avg] です。

  • Idx 64 (integer)

    • Value: 55557
    • Hashed: false
    • 説明: 実行時間 (アンカーからリロードまで)。
  • Idx 65 (string)

    • Value: sha384-3qc
    • Hashed: true
    • 説明: https://www.google.com/recaptcha/api.js?render= に設定された reCAPTCHA スクリプトのインテグリティ (10 文字に切り詰め)。
  • Idx 67 (array)

    • Value: [screen.width, screen.height, screen.availHeight, window.innerWidth, window.innerHeight, window.outerHeight]
    • Hashed: false
    • 説明: 画面解像度、ブラウザのビューポートの幅と高さ、ブラウザウィンドウの高さ。
  • Idx 68 (array)

    • Value: [300,null,1777685870223]
    • Hashed: false
    • 説明: タイムゾーンオフセットと現在の Unix タイムスタンプ [new Date().getTimezoneOffset(), null, Date.now()]
  • Idx 69 (string)

    • Value: 09AKhCRwjrDFiHsrRA--o23-HB-eWqOtk_XQ-rLE1...
    • Hashed: false
    • 説明: 人間識別用のセッショントークン。ブラウザの Cookie に保存され、有効な場合スコアを増加させます。
  • Idx 70 (array)

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

    • Hashed: false

    • 説明: 合計金額 (例: Total: $50.00 や Total 150.00 EUR) を抽出します。サンプル

      document.innerText から、正規表現を使用して通貨記号またはコードと数値額を検索します:

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

      total → 正確な単語 "total" を検索

      [\S\s]{0,20}? → 0 から 20 文字の介在文字 (スペース、コロン、改行など) を検索してから数値を見つける

      (((R\$|\$|€|£|USD|EUR)\s*[\d\.,]+)|[\d\.,]+\s*(€|USD|EUR)) → 金額をキャプチャするメインブロックで、2 つの別々のオプションに分かれています

  • Idx 71 (array)

    • Value: [jsHeapSizeLimit,usedJSHeapSize,totalJSHeapSize]
    • Hashed: false
    • 説明: Performance JavaScript HEAP メモリ。
  • Idx 72 (array)

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

    • Hashed: false

    • 説明: userAgent データの配列 navigator.userAgentData。モバイルかどうかのフラグとプラットフォーム。サンプル:

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

    • Value: [[null,2,0,"Mozilla/5.0 (Windows NT 10.0;...
    • Hashed: false
    • 説明: VM 暗号化シグナル。
  • Idx 77 (integer)

    • Value: null
    • Hashed: false
    • 説明: Unix タイムスタンプ。時々出現します。
  • Idx 78 (string)

    • Value: ""
    • Hashed: false
    • 説明: Google GA Cookie。ウェブサイトが Google Tag Manager を使用している場合に表示されることがあります。
  • インデックス値説明
    0rreqリクエストタイプ識別子
    1U5VsmTDhJM1iO...reCAPTCHA バージョン
    203AFcWeA5Els3.../anchor エンドポイントから取得した検証トークン
    5-383788762シリアル化されたフィンガープリントペイロード全体をハッシュ化したもの、サンプル
    6q実行中のチャレンジまたはリクエストモードを示す
    705APQrAobTCFG...使用パターン。使用履歴と以前に解決されたチャレンジパターンを含む。有効な場合、スコアを大幅に向上させることができる
    8submit検証時にユーザーがページ上で実行している特定のサイトアクション(例: signin、register)
    146LcAbwIqAAAA...ウェブサイトキー
    160XA4cHhALxgM...アンカー(インデックス 18)からの暗号化キー 1777669303203 を使用して、シリアル化されたフィンガープリントペイロード全体を暗号化したもの
    20tbMywxNTQsOD...VM タイミングデルタ、リソースタイミング、収集されたブラウザオブジェクト統計、ウェブサイトスクリプト URL を含むテレメトリ構造の Base64 エンコード
    210aAPQrAobqME...以前に解決された CAPTCHA に関連付けられたトークン。セッション継続性と信頼相関に使用
    22BDAAYAIAGEcA...すべてのブラウザオブジェクトキーをハッシュ化したもの
    25W1tbNTAwNiw...マウスの動き、クリック、キーボード、フォーカス変更などのユーザーインタラクションイベントのカウンターを Base64 エンコードしたもの
    クイックレスポンス(新規)
    Type
    recaptcha/api.js3
    recaptcha/releases/<version>1
    https://www.google.com/recaptcha/api2/anchor2
    https://www.google.com/recaptcha/api2/bframe4
    ハッシュイベントタイプ
    5006pointermove
    64607pointerdown
    45464pointerup
    31617keydown
    37178keyup
    35837focusin
    位置値説明
    0/m/013xlm対象オブジェクトクラスの内部カテゴリ識別子
    23グリッド列数
    33グリッド行数
    5null予約済みまたはオプションのメタデータフィールド
    6"Tractor"テキストラベル
    タイプ説明
    imageselect標準画像選択CAPTCHA
    tileselectタイルベースの動的画像チャレンジ
    dynamic選択後にタイルが再読み込みされる動的チャレンジ
    multicaptcha複数ステップのCAPTCHAチャレンジ
    audio音声ベースのアクセシビリティチャレンジ
    nocaptchaチェックボックスのみの検証フロー
    doscaptcha不正使用がある場合CAPTCHAを拒否
    フィールド名前説明
    vrecaptchaVersionreCAPTCHA バージョン
    cchallengeToken/replaceimage または以前の /userverify リクエストから返されるチャレンジ状態トークン
    response選択されたタイルのインデックスと追加の操作メタデータを含むエンコードされたペイロード
    tchallengeElapsedチャレンジが最初に読み込まれてからの経過時間
    ctcompletionTimeユーザーが CAPTCHA を解いて送信するのにかかった合計時間
    chocHashシリアライズされた oc ペイロード全体のハッシュ、サンプル
    ocencryptedVmSignalsreCAPTCHA VM から収集された暗号化されたシグナル。こちらを参照。
    pmtelemetryPayloadBase64 エンコードされたテレメトリ構造。VM タイミングデルタ、リソースタイミング、収集されたブラウザオブジェクト統計、およびウェブサイトスクリプトメタデータを含む。