Coding

TCaptcha 有哪些检测机制?

What does TCaptcha detect and collect?

JamzumSum · ·updated 2026年6月21日 · 4 min read
Crawler
Crawler Photo by @kevinmartinjose.

前言

由于我最近在做 QQQR 的验证码部分,比如 Image description,在 Qzone2TG 的前面一些版本里,我都是用 Selenium 爬取图像配合模拟拖动来做的,当然也需要一定程度的 CV 技术。

但上面这种办法虽说理论可行,但并非真的万无一失。事实上,在一开始开发的时候跑通之后,这个办法就再也没能稳定工作。等到后来我用 Selenium 抓二维码登录,乃至 QQQR 的第一个版本能够实现协议二维码登录的时候,我就更不倾向于依赖这种不可靠的办法了。

直到 QQQR 的开发到了 2.3.0,我重新开始研究验证码的破解之道,在长达十余天乃至数十天的研究中仔细分析抓包结果和 TCaptcha 相关的 JS 代码,我才终于意识到,使用 Selenium 这些模拟登录的办法究竟处在一种怎样危险的境地。

截至目前,我还没有解决 23003 网络环境异常 的问题。我相信唯一可能暴露的地方就在于验证码检测。尽管如此,我仍然发现了很多腾讯检测浏览器特征的机制。

2022 年 6 月 16 到 17 日腾讯似乎升级了 TCaptcha,然而应该只是简化流程,基本的逻辑、采集的信息都没有太大变化。

tdx.js

在加载 TCaptcha 的时候,页面会载入 tdx.js。这个 JS 本质上是一个虚拟机,准确来说是一个指令集加栈加纸带的组合。我在这方面的知识有限,有时不理解加密何以需要如此复杂的实现。但不得不承认,JS 混淆加上这种叫做 TENCENT_CHAOS_VM 的技术的确可以大大阻碍逆向分析。遗憾的是,腾讯曾举办过一场大赛,这种虚拟机的机制已经被参赛的研究者们看透。我这种一开始不明就里的人,在 GitHub 上查阅相关资料后便大致理解了。

上述指令集、栈与纸带的组合完全决定了程序的逻辑。我的目标就是在这段混淆代码中找出腾讯究竟收集了哪些信息,进而判断出当前环境异常。

我首先尝试了一些手动反汇编的办法,给每个命令加输出,类似编译器。但受限于我本身的水平,得到的结果不够准确,无法交给机器处理,实用性有限。不过从另一个角度,这一步让我真正深入到了指令运行的内部,从而为后面的调试打下了基础。

到底检测了什么

背景和步骤到此为止,下面列出一些检测的条目,给包括我在内的初学者一点警醒:Selenium 等模拟手段并不可靠。

自动化测试工具

这一类比较通用,用于检测客户端是否受自动化控制。

  • window.callPhantom
  • window._phantom
  • window.WebPage
  • window.fxdriver_id
  • window.__fxdriver_unwrapped
  • window.domAutomation
  • window.ubot
  • window.CasperError
  • window.casper
  • window.patchRequire
  • navigator.webdriver
  • document.$cdc_asdjflasutopfhvcZLmcfl_
  • document.__webdriver_script_fn

正常情况下这些属性的值应为 undefined。在使用某些特定工具时,这些值会被设置,从而可以直接断定当前访问受自动化控制。

例如 window.navigator.webdriver,使用 Selenium 时该项会被设为 truewindow.document.$cdc_asdjflasutopfhvcZLmcfl_ 是 ChromeDriver 的特征属性,正常的浏览器中并不存在。

环境信息

tdx.js 也会读取以下信息,通过分析这些数据可以判断客户端所处的环境。虽然没有直接证据,但我认为 23003 错误应该就是在此处触发的。

document.mozHidden

用于检查标签页是否可见,在 Chromium 上为 undefined

navigator

  • navigator.userAgent
  • navigator.appVersion
  • navigator.platform
  • navigator.cookieEnabled
  • navigator.languages
  • navigator.vendor
  • navigator.appName
  • navigator.plugins
  • navigator.getBattery

document & location

  • document.charset
  • document.cookie
  • document.referrer
  • document.documentElement.clientWidth
  • document.documentElement.clientHeight
  • document.getElementById
  • location.href

screen & other display properties

  • screen.colorDepth
  • screen.width
  • screen.height
  • screen.availHeight
  • screen.pixelDepth
  • window.innerWidth
  • window.innerHeight

上述属性和方法均是被检查的对象。这些也正是 Selenium 等工具的优势所在:它们能和正常浏览器保持一致。

对于普通的爬虫来说,通常不会有如此细致的检查,毕竟常见的场景仅限于爬取 HTML。但 QQQR 需要直接与验证码交互,其本质不仅仅是爬虫,使用的工具也是 requestsnodejs 的基础组合,因此这些细节都需要注意。

操作环境

TCaptcha 会尝试在环境中调用 CreateElementFindElementById 等函数,创建和修改包括 imgiframe 等在内的众多元素。目前尚不清楚创建这些元素是否关联其他操作,但这对我们使用的模拟环境也是一个考验。

用户操作

人类访问需要操作,而爬虫没有这个必要。因此 tdx.js 也会收集用户的动作(正常情况下通过 Listener 收集,但当 CreateElement 不可用时,会暴露 tdc.set_data 接口,允许外部传入模拟数据)。

  • 客户端类型(手机/PC)
  • 坐标系(验证码位置,缩放比)
  • 拖动拼图时鼠标的时间-坐标关系

未完待续

分享
作者
JamzumSum

Open-source developer, major language: Python, C++.

Comments

Hook this up to your favourite commenting platform — Giscus, Disqus, or your own.

Continue reading