Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
recaptcha — reCAPTCHA 的文档和逆向工程 | Kitploit
工具/GitHubGitHub/elyelysiox/recaptcha
静态分析动态代码分析 (DAST)逆向工程Web安全反机器人CAPTCHA 绕过
GitHubelyelysiox/recaptcha

recaptcha

reCAPTCHA 的文档和逆向工程

查看仓库
22738342个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

描述

此仓库包含对 Google 反机器人系统 (reCAPTCHA) 的技术分析,重点关注:

  • 载荷结构与值
  • 指纹识别技术
  • 混淆技术
  • 反调试/篡改技术
  • 虚拟机

联系方式

  • Discord: @g_recaptcha
  • Telegram: @lyxlobyx

混淆技术

reCAPTCHA 是拥有最复杂混淆技术的反机器人系统之一,它采用一系列变换使代码难以阅读且更难进行逆向工程。大多数混淆可以通过抽象语法树 (AST) 轻松处理,但有些是在运行时处理的,这使得 AST 在这种情况下毫无用处。多态性也被应用于代码,以在脚本的每个版本中改变其结构。例如,代码不会直接执行操作,而是使用形状变化的对象或函数。

  • 序列表达式 代码通过将每个块语句转换为连续的逗号分隔表达式而被扁平化,它可以出现在 if 语句、函数参数甚至对象内部 seq

  • 混合布尔算术 将算术运算(加、减、乘)与位运算(AND、OR、XOR、NOT)交织在一起以隐藏原始逻辑,例如 -2 * ~(h & H) + -2 + (h ^ H)

  • 间接函数表 每个函数构建在一个表中,并使用其索引调用,例如 functions[index](https://github.com/elyelysiox/recaptcha/blob/main/args)

  • 内联常量数组 一个局部数组字面量在表达式中内联赋值。该数组对在函数体内通过索引访问重复使用的常量(数字、字符串)进行分组

    // b = [14, 1, "call"] assigned inline inside a sequence expression
    function(Y, Q, c, l, G, X, W, J, b, P) {
        (Y & 94) == Y && (b = [14, 1, "call"], ...)
        W[b[2]](J, G)   // W.call(J, G)
        Y >> b[1] & b[0]  // Y >> 1 & 14
    }
    
  • 函数多路复用 多个逻辑上不同的函数合并为一个,使用一个数值参数作为块选择器。活动块通过根据位条件评估参数来确定。调用者传递一个数值字面量作为选择器

    function(N, y, U, Y, h, H, m, C, u) {
        C = [26, 47, 6];
    
        // block 1
        if ((N - 2 ^ 14) < N && (N - C[2] | 28) >= N) {
            // convert value to string logic
        }
    
        // block 2
        if ((N + 4 & 40) >= N && (N + 5 & C[0]) < N) {
            Y = bB();
            throw Error(Y === void 0 ? "unexpected value " + U + y : Y);
        }
    
        return u;
    }
    
  • 逻辑运算符分支 用逻辑运算符短路评估替换 if 语句和 if/else 块,将控制流转换为表达式。结合序列表达式,多个分支显示为单个连续的逗号分隔表达式

    // if (a) { block }
    a && (block)
    
    // if (!a) { block }
    a || (block)
    
    // if (a) { x } else { y }
    a ? x : y
    
    // combined with CFF and sequence expressions:
    (Y | 1) & 14 || (c = Q.O, J = c.O.length + c.g.length),
    (Y ^ 59) >> 3 == 3 && (Q.classList
        ? Q.classList.add(c)
        : Z[31](31, Q, c) || (l = f[0](84, "string", "", Q), ...)),
    
  • 绑定原生方法常量 将浏览器原生方法绑定到其原始接收者,将它们存储为常量以防止篡改

    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,一个处理 catch 块,另一个处理 try 块。

  • 加密字符串池 所有字符串字面量(DOM API、浏览器属性、CSS 值、错误消息等)被加密到一个巨大的字符串池中。一个解密函数使用种子和基于 LCG 的 XOR 密码在运行时提取每个字符串

    代码中有 1990 多个调用点,解密函数使用一个累积解码码点的运行密钥,使得每个字符依赖于所有前面的字符

    X = function(J, b, P, F, U) {
        U = ["codePointAt", 127, "char encrypted pool"];
        for (F = (P = 0, b = "", l); P < Q; P++)
            J = (U[2][U[0]](c + P) ^ F) & U[1],  // XOR with running key
            b += String.fromCodePoint(J),
            F += J; // accumulate key
        return G = b;
    }
    
    // call sites pass a seed to locate and decrypt each string
    Z[23](64, 4, 54961, 103)()  // → "lang"
    Z[23](66, 4, 54961, 103)()  // → "addEventListener"
    Z[23](32, 12, 20287, 852)() // → "inline-block"
    

    decstrings

  • 有状态值迭代器 reCAPTCHA 使用一个有状态函数,该函数按固定顺序返回一系列运行时对象和值(例如 window、document.body、数值常量),每次调用都会前进内部游标,乱序调用或调用次数过多会破坏所有后续读取。超时机制在固定间隔后使状态失效,对任何延迟读取返回 null

    // sequential calls return different values:
    c()  // → window
    c()  // → document.body
    c()  // → 123
    c()  // → null (timeout expired)
    
    l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12)
    // ↑ window                     ↑ window
    
    10 * l(c(), G[2], G[W[1]], G[1]) + l(c(), G[2], G[W[1]], 12))
    
    c().querySelectorAll(a[X[2]](98, X[1], X[1]))
    // ↑ document.body  
    
    
  • 计算函数表 这与 间接函数表 类似,但这里要获取的函数索引是在运行时使用种子计算的,使用 XOR 和模运算

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

    computed

  • 运行时值加密 某些值(验证码配置参数、锚点参数等)从不以明文形式存储;它们在收集后立即加密,仅在使用时解密,开头带有前缀 B

    hiddenv

  • 异步控制流混淆 同步逻辑被转换为基于生成器的状态机,这些状态机包装在递归 Promise 链中,通过调试器追踪任何值都会强制逐步执行多个异步处理程序,在每个 .then() 边界丢失原始执行上下文

锚点载荷/响应

载荷结构

初始化 reCAPTCHA 的组件``` ar: <WidgetInit?> k: co: hl: v: size: sa: anchor-ms: execute-ms: cb:

### 响应

响应包含:
- 验证码 iframe 窗口设计
- 用于载荷验证的锚点令牌 (/reload)
- 初始化的主要配置,在 `recaptcha.anchor.Main.init` 方法中执行,以便在 recaptcha_en.js 中接收

### 结构:
下载工具