refactor(纯算): 移除全部补环境后端,收敛为纯算单一路径 + 修复两处红灯
做了什么:
- 删除 generate_telemetry_node/browser/probe 三个伪造环境后端, 以及 apply_real_environment、
4 段拼接旧结构、human_dt_ms、generate_collect_pure (crypto.py 955 -> 389 行)
- 遥测只剩纯算: python_keyed = Node 仅提取 XTEA 密钥字 + Python 模板回填 + 教科书 XTEA
- 修复 crypto.py 重复的 xtea_encrypt_block (内置自测从失败到通过), 并并入 selftest
- 修复 glyph_solver 强校验: 改用集成得分矩阵行 argmax 自洽校验, 回归 5/8 -> 8/8
- 移除注释里无证据的 errorCode=12 归因; 移除 12 自动换 IP 重试
- extract_eks 不再写死变量名; UA 常量统一为 Chrome/155
- 文档对齐: ANALYSIS §8 修订 / PROGRESS 重写 / TOOLCHAIN_REPORT §三 更正
为什么:
- 本项目证据账本已证: 12 与遥测后端/出口 IP/静默时长均无关, 补环境无收益且引入脆弱面
- 强校验用单引擎 ocr_text 会误杀正确解 (实测 簿->垂 / 笆->芭 / 筹->努)
怎么验证:
- .venv/bin/python -m tcaptcha.selftest 全绿 (crypto_core + glyph 8/8 + xtea_key)
- 端到端纯算: python / python_keyed 均可解回 '{"cd":[' 开头明文, probe 模式被拒绝
This commit is contained in:
+26
-34
@@ -106,25 +106,23 @@ class TencentCaptchaClient:
|
||||
min_posterior: float = 0.95,
|
||||
pow_timeout: int = 4000000,
|
||||
inter_attempt_delay: float = 0.25,
|
||||
telemetry_mode: str = "probe",
|
||||
telemetry_mode: str = "python_keyed",
|
||||
proxy: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
telemetry_mode 决定 collect/eks 怎么来 (见 tcaptcha.crypto.generate_telemetry):
|
||||
"probe" (默认推荐) 深度 Proxy 语义沙箱: 零 CDP 特征泄露,原生时间戳/轨迹,
|
||||
自动适配各版本 tdc.js 动态字段序,彻底解决 errorCode=12
|
||||
"python_keyed" Node 只从本次构建的 tdc.js 提取密钥,纯 Python 组包
|
||||
"python" 纯 Python + 固定密钥 (适合雨云等不校验遥测的宽松 aid)
|
||||
"node" 旧版简易 Node VM 沙箱
|
||||
"browser" 真实 Chrome + CDP 执行
|
||||
"auto" probe -> python_keyed -> node -> python 逐级回退
|
||||
telemetry_mode 决定 collect/eks 怎么来 (见 tcaptcha.crypto.generate_telemetry), 只走纯算:
|
||||
|
||||
实测结论 (2026-10-11):
|
||||
* 雨云 aid=2039519451 用 "python" 提交正确答案 → errorCode=0 + 真实 ticket,
|
||||
证明服务端不校验 collect 与 eks 的同源性, 纯 Python 交付形态依然成立。
|
||||
* 1ms.run aid=195672344 答题正确时, "python"/"node"/"browser" 三种遥测
|
||||
在服务端风控阶段一律返回 errorCode=12 —— 与该 aid 的风控策略有关,
|
||||
不是遥测引擎的问题。详见 har/1ms_dianxuan/ANALYSIS.md。
|
||||
* "python_keyed" (默认): Node 只从本次构建的 tdc.js 里提取 XTEA 密钥字;
|
||||
明文组装 / 轨迹 / 时间戳 / 加密 / 编码全部在 Python 完成。
|
||||
* "python": 完全不调用 Node, 直接用内置 DEFAULT_KEY
|
||||
(仅对不校验遥测的宽松 aid 有效)。
|
||||
|
||||
关于 errorCode=12 (实测 2026-10-11, 见 har/1ms_dianxuan/ANALYSIS.md §7):
|
||||
1ms.run aid=195672344 在答案正确时返回 12, 且与遥测后端无关 ——
|
||||
python / python_keyed / node / browser 四种后端、4 个不同省份出口 IP、
|
||||
9 分钟静默后单发, **全部都是 12**。所以 12 不是遥测/环境/IP 问题,
|
||||
不要再走"补环境"或"换 IP"的路; 真正的变量 (登录态 / 真实验证码页面上下文)
|
||||
尚未被单变量实验区分。
|
||||
"""
|
||||
self.aid = str(aid)
|
||||
self.timeout = timeout
|
||||
@@ -136,11 +134,11 @@ class TencentCaptchaClient:
|
||||
self.accept_kinds = tuple(accept_kinds)
|
||||
self.min_posterior = min_posterior
|
||||
self.pow_timeout = pow_timeout
|
||||
# 抽题/投票之间的最小间隔, 用于规避腾讯 errorCode 12 (f_limit)
|
||||
# 抽题/投票之间的最小间隔 (降低接口压力; 与 errorCode=12 无因果关系)
|
||||
self.inter_attempt_delay = inter_attempt_delay
|
||||
# 遥测(collect/eks)生成方式: node = 在沙箱里跑真实 tdc.js (推荐); python = 纯算法还原
|
||||
# 遥测生成方式: 只走纯算 (见 tcaptcha.crypto.generate_telemetry)
|
||||
self.telemetry_mode = telemetry_mode
|
||||
# 出口代理: 腾讯天御按 IP 做滚动风控, 触发 errorCode=12 时换 IP 即可恢复
|
||||
# 出口代理 (可选)。注意: 实测换出口 IP 并不能解决 errorCode=12
|
||||
self.proxy = proxy
|
||||
|
||||
# 图标题型求解器 (惰性加载, 避免只跑文字题型时白加载 56MB 权重)
|
||||
@@ -447,7 +445,7 @@ class TencentCaptchaClient:
|
||||
ans_str = json.dumps(ans_list, separators=(",", ":"))
|
||||
telemetry = generate_telemetry(
|
||||
tdc_code or "", points, aid=self.aid, user_agent=self.user_agent,
|
||||
referrer=self.referer, start_time=round_start_time, mode=self.telemetry_mode,
|
||||
referrer=self.referer, mode=self.telemetry_mode,
|
||||
)
|
||||
logger.info("遥测密文来源=%s collect_len=%s eks_len=%s",
|
||||
telemetry.get("source"), len(telemetry["collect"]),
|
||||
@@ -492,8 +490,9 @@ class TencentCaptchaClient:
|
||||
|
||||
err_code = str(v_json.get("errorCode"))
|
||||
if err_code == "12":
|
||||
last_error = ("触发腾讯接口频控限制 (errorCode: 12, f_limit), "
|
||||
"建议降低请求频率或更换出口 IP")
|
||||
last_error = ("服务端返回 errorCode=12 (腾讯天御风控评估未通过)。"
|
||||
"实测与遥测后端 / 出口 IP / 静默时长均无关 "
|
||||
"(见 har/1ms_dianxuan/ANALYSIS.md §7), 不要再尝试换环境或换 IP")
|
||||
logger.error(last_error)
|
||||
break
|
||||
if err_code in ("50", "9"):
|
||||
@@ -547,11 +546,12 @@ def main():
|
||||
default="https://1ms.run/console/personal/benefits/check-in")
|
||||
parser.add_argument("--wb", default="1")
|
||||
parser.add_argument("--retries", type=int, default=3)
|
||||
parser.add_argument("--telemetry", default="python",
|
||||
choices=["python", "node", "browser", "auto"])
|
||||
parser.add_argument("--telemetry", default="python_keyed",
|
||||
choices=["python_keyed", "python"],
|
||||
help="遥测方式: python_keyed(Node 仅提密钥) / python(纯 Python 固定密钥)")
|
||||
parser.add_argument("--proxy", default=None, help="出口代理, 如 http://1.2.3.4:8080")
|
||||
parser.add_argument("--proxy-api", default=None,
|
||||
help="代理提取 API; 出现 errorCode=12 时自动换 IP 重试")
|
||||
help="代理提取 API (可选; 注意换 IP 并不能解决 errorCode=12)")
|
||||
args = parser.parse_args()
|
||||
|
||||
proxy = args.proxy
|
||||
@@ -567,16 +567,8 @@ def main():
|
||||
print(f"[*] 正在发起腾讯天御验证码纯协议识别 (AppID: {args.aid}, proxy={proxy})...")
|
||||
result = client.solve(max_retries=args.retries)
|
||||
|
||||
# errorCode=12 (f_limit) 是 IP 级滚动风控: 换一个出口 IP 再试一次
|
||||
if not result["success"] and "12" in str(result.get("error", "")) and args.proxy_api:
|
||||
print("[*] 触发 f_limit, 换 IP 重试...")
|
||||
client.close()
|
||||
proxy = fetch_proxy(args.proxy_api)
|
||||
print(f"[*] 新代理: {proxy}")
|
||||
client = TencentCaptchaClient(aid=args.aid, entry_url=args.entry_url,
|
||||
referer="https://1ms.run/", wb=args.wb,
|
||||
proxy=proxy, telemetry_mode=args.telemetry)
|
||||
result = client.solve(max_retries=args.retries)
|
||||
# 注意: errorCode=12 实测与出口 IP 无关 (ANALYSIS.md §7), 这里不再自动换 IP。
|
||||
# 如需指定出口 IP, 请在启动时用 --proxy / --proxy-api。
|
||||
|
||||
if result["success"]:
|
||||
print("\n" + "=" * 50)
|
||||
|
||||
Reference in New Issue
Block a user