文章总结: 该文档通过逆向工程分析ClaudeCode2.1.196版本,发现其针对中国用户进行特殊指纹测绘。当用户设置自定义API端点时,程序会通过Unicode字符编码隐蔽传输三类信息:是否使用已知中国域名、是否包含AI实验室关键词、是否使用中国时区。分析确认了147个监控域名和11个AI实验室关键词列表,测绘数据随模型请求发送而非独立遥测。 综合评分: 85 文章分类: 代码审计,逆向分析,隐私分析,数据安全,应用安全
anthropic claude code针对中国用户遥测的分析
原创
闲聊趣说 闲聊趣说
闲聊趣说
2026年7月1日 00:49 河南
在小说阅读器读本章
去阅读
前言
刷推特偶然刷到claude code会针对中国用户进行特殊的指纹测绘,于是赶紧让codex(GPT 5.5)对claude code分析了一下,以下为AI分析结论,全量分析产生的文件可在
https://github.com/Chestnuts4/claude_code_rev
分析下来确实针对中国用户进行了特殊对待,使用prompt隐蔽传输测绘结果,单从域名/流量请求看没办法看出来携带了特殊测绘信息,甚至编码了一个中转站域名list,想来后面想杀的时候直接就可以将对应的账户封禁了。
作为封号的受害者,无数次问候达里奥全家了。
Claude Code 2.1.196 解包与隐私逻辑分析记录
生成日期:2026-06-30(Asia/Taipei)
本报告记录从样本确认、Bun 解包、源码格式化、混淆数据解码、控制流追踪到结论形成的完整过程。分析采用静态读取和本地重建测试,没有让 claude.linux 发起模型或 telemetry 网络请求。
1. 分析目标
- 将 Bun 打包的
claude.linux解包为可审阅的 JavaScript; - 核对 Reddit 帖子所称的自定义代理、时区和中国 AI 实验室标记逻辑;
- 确认信号如何进入网络请求;
- 区分模型上下文、独立 telemetry、错误报告和用户主动反馈;
- 保存可重复执行的脚本和分析产物。
参考帖子:https://www.reddit.com/r/ClaudeAI/comments/1ujila1/anthropic_embedded_spyware_in_claude_code_and/
官方数据使用说明:https://code.claude.com/docs/en/data-usage
官方环境变量说明:https://code.claude.com/docs/en/env-vars
2. 样本确认
执行:
file claude.linux
sha256sum claude.linux
./claude.linux --version
结果:
ELF 64-bit LSB executable, x86-64, dynamically linked, not stripped
SHA-256 eb933c6dd5534db89b83ba09009d5c0932bd1395f7e3bb0f34ba37eec37bbade
2.1.196 (Claude Code)
radare2 MCP 也成功打开样本,并识别出:
format: elf64
arch: x86
bits: 64
entrypoint: 0x01b38e00
compiler: GCC 13.1.0 / LLD 22.1.4
因此本地样本与帖子所指版本一致,而不是把其他版本的逻辑推断到本样本。
3. Bun 打包结构识别
readelf -S claude.linux 显示独立的 .bun section:
[30] .bun PROGBITS
offset 0x05238000
size 0x097bd0d1(约 152 MiB)
提取该 section:
objcopy --dump-section .bun=claude.bun-section.bin claude.linux
在 section 中找到 Bun trailer:
\n---- Bun! ----\n
并找到目标明文字符串:
ANTHROPIC_BASE_URL
Asia/Shanghai
Asia/Urumqi
Today${n}s date is
这证明目标应用代码以 minified JavaScript 存在于 Bun module graph 中,并非只能从 x86 机器码反编译。
4. 通用解包器失败与原因
首先测试了 @shepherdjerred/bun-decompile。它返回:
Corrupt module graph: Pointer extends beyond buffer:
offset=16779776, length=158616795
检查该解包器源码后发现,它按旧版 CompiledModuleGraphFile 的 36 字节记录解析;样本 trailer 中 module table 长度为 0x104(260)字节。实际记录可以稳定分成:
260 / 52 = 5 modules
按 52 字节解析时,各模块的 name pointer 和 contents pointer 均落在合法数据范围,且提取内容能被 file 正确识别。旧解析器把新版记录中的其他字段错当成 bytecode pointer,才造成越界。
5. 自建解包器与提取结果
为保留可重复性,编写了:
tools/extract-bun-1.3.js
该脚本执行以下步骤:
- 从文件尾向前寻找 Bun trailer;
- 读取 trailer 前 32 字节的 offsets structure;
- 计算
dataStart = trailerPos - 32 - byteCount; - 读取 module table pointer;
- 根据 table 长度选择 52 字节记录格式;
- 解析每个模块的 name 和 contents pointer;
- 做边界检查后写出模块和
manifest.json。
执行:
bun tools/extract-bun-1.3.js \
claude.linux \
decompiled-claude-2.1.196
关键 offsets:
trailerPos: 245321921
dataStart: 86212616
byteCount: 159109273
module entry size: 52
entry point id: 0
flags: 15
提取出 5 个模块:
| ID | Bun 内部路径 | 类型 | 大小 |
| — | — | — | — |
| 0 | /$bunfs/root/src/entrypoints/cli.js | JavaScript,入口 | 18,054,465 |
| 1 | /$bunfs/root/image-processor.js | JavaScript | 1,976 |
| 2 | /$bunfs/root/audio-capture.js | JavaScript | 1,974 |
| 3 | /$bunfs/root/image-processor.node | ELF native addon | 1,464,760 |
| 4 | /$bunfs/root/audio-capture.node | ELF native addon | 492,184 |
主模块哈希:
f936de85f33e25bb95c36f1dd3a73471a1c91a6a95ac5a22370f0f21e7a7559d bundled/0-cli.js
6. 格式化与源码定位
原始主模块是一份 minified JS。使用本地 Prettier 生成:
prettier --write decompiled-claude-2.1.196/claude-2.1.196.formatted.js
结果约 875,183 行,SHA-256:
e85a3592e6844f21848034b6e51bcdba80dd8ed8cbddbd1f8966d6c44226c5a7
目标逻辑位于格式化文件约 274037–274088 行,system context 调用位于约 278990–279016 行。相关 minified 符号为:
| 符号 | 作用 |
| — | — |
| $la | Base64 解码后逐字节 XOR 91,再按逗号拆分 |
| Wup | 读取 ANTHROPIC_BASE_URL 的 hostname |
| vrt / wrt | 判断是否为默认/官方 api.anthropic.com |
| ekt | 读取系统 IANA 时区 |
| qup | 生成 known、labKw、cnTZ、host 分类 |
| Vup | 根据两个 hostname 分类选择 Unicode 撇号 |
| Ola | 生成最终日期句子 |
qup() 在整个主模块中只有定义和 Ola() 中的一次调用。host 没有通过这条路径被其他代码直接上报。
7. 混淆列表解码
程序把两个列表保存为 Base64 字符串,运行时执行:
Buffer.from(encoded, "base64")
byte ^ 91
decoded.split(",")
编写 tools/extract-privacy-marker.js 独立复现该算法,并输出 decoded-marker-lists.json。结果包含:
- 147 个 known-domain 项;
- 11 个 AI-lab keyword。
AI-lab keyword 完整列表:
deepseek
moonshot
minimax
xaminim
zhipu
bigmodel
baichuan
stepfun
01ai
dashscope
volces
known-domain 列表包含 .cn 后缀标记、百度、阿里、字节、京东、网易、美团等企业域名,以及大量第三方 API 中转站域名。完整内容保存在 decoded-marker-lists.json,不在报告中重复 147 行。
域名判断为:
host === domain || host.endsWith("." + domain)
关键词判断为:
host.includes(keyword)
因此它只是字符串分类器,不是组织身份或账户隶属关系验证。
8. 精确控制流
8.1 启用条件
vrt() 的语义为:
if (!process.env.ANTHROPIC_BASE_URL) returntrue;
returnnewURL(value).host === "api.anthropic.com";
qup() 开头执行:
if (vrt()) returnnull;
所以以下情况不打标:
- 没有设置
ANTHROPIC_BASE_URL; - 设置为
https://api.anthropic.com。
启用对象是 Claude Code 的自定义 API base URL,不是通用的 HTTP_PROXY、HTTPS_PROXY 或 SOCKS 配置。把它简称为“代理检测”容易误导。
8.2 输入信号
启用后读取:
-
自定义 base URL 的 hostname;
-
Intl.DateTimeFormat().resolvedOptions().timeZone;
-
hostname 是否命中 known-domain;
-
hostname 是否包含 AI-lab keyword。
时区只判断两个精确值:
Asia/Shanghai
Asia/Urumqi
没有发现此路径进行 IP 定位、GPS 定位或读取真实地理位置。Asia/Taipei 不命中。
8.3 编码方式
| known | labKw | 字符 | Unicode |
| — | — | — | — |
| false | false | ' | U+0027 |
| true | false | ’ | U+2019 |
| false | true | ʼ | U+02BC |
| true | true | ʹ | U+02B9 |
当 cnTZ=true 时,日期中的 - 被替换为 /。
一个看似普通的日期句子因此能编码三个布尔分类位:known-domain、lab-keyword、China-timezone。
8.4 进入请求
Ola(FSe()) 的结果被赋给 user context 的 currentDate:
{
claudeMd,
userEmail,
attachedProject,
currentDate: Ola(FSe()),
}
随后该 context 进入 Claude 模型 system prompt。因此分类结果随正常模型请求发送到当前模型端点。它不是独立 telemetry event,也不是单独的 hostname 上传请求。
9. 本地重建验证
为了避免执行原程序网络路径,编写了 privacy-marker.reconstructed.js,只重建上述纯函数逻辑。测试结果:
未设置 base URL + Asia/Taipei
=> Today's date is 2026-06-30.
api.anthropic.com + Asia/Shanghai
=> Today's date is 2026-06-30.
proxyai.com + Asia/Taipei
=> Today’s date is 2026-06-30. U+2019
deepseek.example + Asia/Taipei
=> Todayʼs date is 2026-06-30. U+02BC
moonshot.ai + Asia/Shanghai
=> Todayʹs date is 2026/06/30. U+02B9 + slash date
这些输出与帖子描述的字符映射一致。
10. 会进入模型上下文的其他信息
同一 user_context 构造代码还可能加入:
- CLAUDE.md、用户 memory、项目 memory 的内容;
- attached project context;
- 登录账户邮箱,文本格式为
The user's email address is ...; - 当前日期及本报告确认的隐藏分类。
正常使用时,下列内容也会按照模型工作流发送给所选 API 端点:
- 用户输入;
- 用户明确附加的文件;
- 工具读取并加入会话上下文的代码和文件内容;
- 工具结果;
- 对话历史和模型输出。
这类“模型推理所需上下文”应与独立的产品 telemetry 区分。若使用自定义 ANTHROPIC_BASE_URL,该网关本身通常也能看到转发的模型请求正文。
11. 独立网络上报分类
根据本地源码开关和 Claude Code 官方说明:
| 类型 | 内容/行为 | 关闭方式 |
| — | — | — |
| Anthropic operational telemetry | 延迟、可靠性、使用模式;官方称不含代码和文件路径 | DISABLE_TELEMETRY=1 |
| Sentry error reporting | 运行错误报告 | DISABLE_ERROR_REPORTING=1 |
| /feedback | 用户主动提交时可包含会话历史和代码 | DISABLE_FEEDBACK_COMMAND=1 |
| Session quality survey | 会话质量调查 | CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY=1 |
| WebFetch safety preflight | 把待访问 URL 的 hostname 发给 api.anthropic.com | skipWebFetchPreflight: true |
| Auto updater | 版本检查/更新 | DISABLE_AUTOUPDATER=1 |
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 等价关闭 updater、feedback、error reporting 和 telemetry,但:
- 不关闭 WebFetch hostname 安全预检;
- 不关闭本报告确认的 system-prompt 日期标记;
- 不阻止正常模型请求携带会话上下文。
DISABLE_TELEMETRY 也不会关闭日期标记,因为目标代码路径没有检查该变量,且标记属于模型请求正文。
12. 对 Reddit 指控的逐项判断
| 指控 | 判断 | 依据 |
| — | — | — |
| 自定义 endpoint 会触发隐藏检测 | 属实 | vrt() / qup() 控制流 |
| 检测 HTTP/HTTPS 代理 | 不准确 | 实际只读 ANTHROPIC_BASE_URL |
| 检测用户是否在中国 | 夸大 | 只检查 Shanghai/Urumqi 时区,无 IP 定位 |
| 检测是否隶属中国 AI 实验室 | 夸大 | 只做 hostname 关键词包含判断 |
| 分类被隐式传给服务端 | 属实 | Unicode 撇号和日期格式进入 currentDate system prompt |
| 完整自定义 hostname 被此路径直接上传 | 未发现 | host 仅供本地分类,qup() 只有一个消费者 |
| 可用 DISABLE_TELEMETRY 关闭 | 不属实 | 标记不走 telemetry 开关 |
| 代码经过刻意隐藏 | 有事实基础 | 域名与关键词使用 Base64 + XOR 91;但 minification 本身不能单独证明主观意图 |
13. 最终结论
样本中确实存在一个未在正常 UI 中披露的环境分类机制。当用户配置非官方 ANTHROPIC_BASE_URL 时,它根据自定义 hostname 和两个中国时区生成三个分类位,并通过肉眼不易区分的 Unicode 撇号及日期格式嵌入 system prompt。该标记会随模型请求到达用户配置的 API 端点。
把这称为“完整代理地址或个人文件的秘密独立上报”并不准确:在已追踪的目标路径中,完整 hostname 不进入请求,只进入本地分类;代码和文件是否发送取决于正常模型上下文和工具使用。把它称为“检测用户真实位于中国或确认实验室隶属关系”同样超过代码证据。
更准确的表述是:Claude Code 2.1.196 对自定义 API endpoint 及特定系统时区进行本地分类,并将分类结果隐写进模型 system prompt;这一机制不受 telemetry opt-out 控制。
13.1 中转域名与 AI Lab 关键词的行为差异
有区别,但区别仅体现在隐藏 system-prompt 标记上。其他功能变化由“是否为非官方 ANTHROPIC_BASE_URL”决定。
| 域名分类 | 日期文本 |
| — | — |
| 两类都未命中 | Today's date is 2026-07-01. |
| 仅命中中转域名名单 | Today’s date is 2026-07-01. ,U+2019 |
| 仅包含 AI Lab 关键词 | Todayʼs date is 2026-07-01. ,U+02BC |
| 两类同时命中 | Todayʹs date is 2026-07-01. ,U+02B9 |
例如:
-
proxyai.com:在 147 个域名名单中,通常是“仅中转域名”;
-
deepseek.example:包含
deepseek,但不一定在域名名单中,属于“仅 AI Lab”; -
moonshot.ai:既在域名名单中,又包含
moonshot,属于“两者同时命中”。
如果系统时区是 Asia/Shanghai 或 Asia/Urumqi,以上日期还会变成:
2026/07/01
需要注意:
- “AI Lab 域名”并不是独立的精确域名表,而是 11 个 hostname 子串关键词;
- Remote Control 禁用、ToolSearch 默认关闭、部分 first-party 能力失效等行为,对所有非官方 base URL 都相同,不区分中转名单或 AI Lab;
- GrowthBook 上报完整
apiBaseUrlHost时也不区分这两个分类;服务端可以直接看到实际 hostname; - 没发现根据两类标记切换模型、降低回答质量、改变价格或直接封号的客户端逻辑。标记在服务端如何使用,无法从客户端二进制确定。
14. 局限性
- 本报告是目标逻辑的静态分析和纯函数重建,没有使用抓包对真实 Anthropic 服务端行为做动态验证;
- 没有声称穷举 18 MB 主模块中的每一种业务网络请求;
- Sentry 在具体异常下可能包含哪些堆栈字段,需要独立动态触发和抓包才能完整枚举;
- 本结论严格对应所列 SHA-256 的 Linux 2.1.196 样本,后续版本可能改变;
- 对开发者主观动机(反蒸馏、风控或其他用途)不从代码作无证据推断。
15. 落盘产物
decompiled-claude-2.1.196/
├── ANALYSIS.zh-CN.md 本完整报告
├── manifest.json Bun 模块清单和 offsets
├── bundled/
│ ├── 0-cli.js 原始 minified 主模块
│ ├── 1-image-processor.js
│ ├── 2-audio-capture.js
│ ├── 3-image-processor.node
│ └── 4-audio-capture.node
├── claude-2.1.196.formatted.js 格式化完整主模块
├── decoded-marker-lists.json 147 个域名和 11 个关键词
└── privacy-marker.reconstructed.js 可读重建及本地测试目标
tools/
├── extract-bun-1.3.js Bun 1.3 module graph 解包脚本
└── extract-privacy-marker.js 混淆列表解码脚本
复现核心过程:
bun tools/extract-bun-1.3.js claude.linux decompiled-claude-2.1.196
cp decompiled-claude-2.1.196/bundled/0-cli.js \
decompiled-claude-2.1.196/claude-2.1.196.formatted.js
prettier --write decompiled-claude-2.1.196/claude-2.1.196.formatted.js
bun tools/extract-privacy-marker.js \
decompiled-claude-2.1.196/claude-2.1.196.formatted.js
16. 全部静态加密字符串解码
进一步扫描完整格式化主模块中的以下模式:
-
Buffer.from(..., "base64");
-
atob(...);
-
String.fromCharCode(... ^ key);
-
crypto.subtle.decrypt、AES、JWT 与通用 decrypt helper;
-
静态常量到解码函数的调用关系。
扫描后,应用自身用于隐藏静态文本的解码器只有 $la(),调用关系只有:
$la(Uup)
$la(Fup)
因此可静态解密的应用字符串常量总数为 2:
| 常量 | 算法 | 解码结果 |
| — | — | — |
| Uup | Base64 decode,然后每字节 XOR 91 (0x5b) | 147 个域名 |
| Fup | Base64 decode,然后每字节 XOR 91 (0x5b) | 11 个 AI lab 关键词 |
已生成:
static-decoding/
├── all-decrypted-strings.txt
├── all-decoded-static-payloads.json
├── claude-2.1.196.deobfuscated.js
└── binary-assets/
└── FNf.glyph-table.bin
claude-2.1.196.deobfuscated.js 是完整 875,341 行分析副本,其中:
-
Uup的密文被替换为 147 项明文数组;
-
Fup的密文被替换为 11 项明文数组;
-
$la(Uup)和
$la(Fup)被替换为数组直接引用; -
文件已通过
node --check语法验证。
完整明文也单独保存在 all-decrypted-strings.txt,便于不加载 27 MiB JS 时直接审阅。
非字符串静态 payload
扫描还发现 FNf:
inflateRawSync(Buffer.from(FNf, "base64"))
它是终端截图渲染所用的压缩 glyph bitmap table,不是加密文本。为了完整处理静态编码 payload,已执行 Base64 解码和 raw-deflate 解压,输出为 FNf.glyph-table.bin。解压后首字段可解析为 glyph 数量;该二进制没有被错误转换成乱码文本。
无法预先解密的运行时数据
主模块包含 AES、JWT、WebCrypto 和通用 Base64 库代码,但这些函数的 ciphertext、key、IV 或 token 来自运行时参数。样本中没有与其配对的静态 ciphertext/key 常量,因此不存在可在静态分析阶段合法求值的更多明文。此类库函数被记录在 JSON 清单的 unresolved 字段,而不是虚构解密结果。
复现命令:
bun tools/decode-all-static-payloads.js \
decompiled-claude-2.1.196/claude-2.1.196.formatted.js
node --check \
decompiled-claude-2.1.196/static-decoding/claude-2.1.196.deobfuscated.js
文件哈希:
cf4f0c125d534377352039a5785891a61164e1929202ee3367b29fec6961228c all-decoded-static-payloads.json
7d418ad4ed87ced629393e981f29e8670fd51e08bc25921bc0e553b2772dd31f all-decrypted-strings.txt
05fa6754f8ed16ec84925c32c92eb35e525378c1e837228b9e0d78d8a02e9e34 claude-2.1.196.deobfuscated.js
f0980417a011379fab891fb38a92101ff83663b9633697512362c68c53db73cf FNf.glyph-table.bin
#
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:闲聊趣说 闲聊趣说 闲聊趣说《anthropic claude code针对中国用户遥测的分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论