最近小编用上了 claude-science,要登录,但是我没账号,真是烦。

于是我想把登陆绕过去。用其他供应商的兼容 API key,比如 moonshot、deepseek 或者其他国产模型。但是,发现还是有一些坑的,记录一下。以下内容在"田螺姑娘"协助下完成,我是不懂的,好在她能力足够强,独自完成了任务。另外一个应该是A家没有做提高难度的封装什么的。

二进制锁死
claude-science 是个 Bun 单可执行文件,大小有158MB。JS 代码嵌在里面,按长度/偏移寻址,不能插入或删除一个字节------否则整个二进制启动就会崩溃,报SyntaxError。
这意味着所有修改只能是等长替换:改几个字符可以,塞新代码不行。
7 道关卡
原厂做了好几层防护。其实以下内容我也看不懂,没关系,实现了就可以的。需要我也可以分享我的结果。我在 v0.1.18 的时候使用opencode+hy3+oh my openagent摸清了 7 处需要改的地方,这次升级到 v0.1.20,大部分偏移变了,但思路没变:
P1 --- 会话伪造。 如果没有 OAuth 登录就没有 session,但程序是需要一个 account_uuid的。于是我直接把返回 session 的那个函数替掉,让它永远返回的是 {account_uuid:"local-owner", email:"owner@local"}。
坑:v0.1.18 的函数叫 A9(),v0.1.20 叫 R9(),长度也不一样(70B → 196B),得把整个 R9 和 qdz 两个函数一起替换,用 /*xxxxx*/ 注释对齐字节数。世界是个草台班子呀!
P2 --- 认证门。 V=Y(q);if(!V) 是检查 cookie 里有没有 token的。把 Y(q)(4 字节函数调用)替换成 1 (1 + 三个空格),让 V 永远是 1,if(!V)就永远不成立啦。
P3 --- 凭据解析。 原本是 throw Error("No credentials available...")。我把它改成了 return{auth_token:process.env.ANTHROPIC_API_KEY,...},这样就直接走环境变量的 key。
v0.1.18 只改 60 字节就够了,v0.1.20 要把整个 throw 语句加后面的 } 一起替掉(100 字节),否则后半段字符串的垃圾字节会卡在 return 的对象字面量里面。
P4 --- 签名校验。 if(!O)throw new h8("This build requires signing in..."),把 O 改成 1(一个字节),变成 if(!1),这样就是恒假了。
P5 --- require_token 默认值。 zod schema 里 require_token: C.boolean().default(!0),!0 在 minify 后的 JS 里就是 true。改成 !1(false)。
P6 --- 登录守卫。 这关是最容易漏的。即使 P5 把默认值改成了 false,原厂还有一段:if(!W.require_token) process.stderr.write("disabling login auth is not available..."); process.exit(1);。也就是说,只要 require_token 为 false,就会直接退出。
于是我把 if(!W.require_token(19 字节)替换成 if(0&&W.require_tok(也 19 字节)。注意 token 变成 tok 也是为了凑等长。
P7 --- 模型名白名单。 原本只允许 claude- 和 deepseek- 开头的模型。正则从 /^claude-/i 改成 /^.{1,99}/i,使其能够匹配任意非空字符串。
适配 v0.1.20 踩的坑
上面 7 个补丁在 v0.1.18 上是直接可用的。可是升到 v0.1.20 后就撞了三个问题:
-
P1 替换崩溃。 原来 70 字节替换后接收到的字节是
{z=e7.readdirSync这种无效代码。因为 v0.1.18 的 A9 函数后面恰好是合法续文,v0.1.20 的 R9 后面就不是了。解决方案是把整个 R9+qdz 函数(196B)一起替换掉,这样就不再依赖边界巧合。 -
P3 替换崩溃。 同理,原 60 字节替换后留了半截错误消息字符串在 return 语句里。扩大到 100 字节,就把整个 throw 加下一行的
}一起替换了。 -
P5 定位偏差。 搜索前缀
require_token:C.boolean().default(!里面带了!,导致替换位置偏了一个字节------把0)替换成了!1,直接 SyntaxError。就改成不带!的前缀require_token:C.boolean().default(就好了。
自动化补丁脚本
整个流程写了 Python 脚本,所有偏移通过 bytes.find() 动态定位(不硬编码),每个补丁做完立刻校验字节相等:
[P3] OK: 108956056 (100B, equal length)
[P4] OK: 103069897 (50B, equal length)
[P5] OK: 102022973 (2B, equal length)
[P1] OK: 110187297 (196B, equal length)
[P2] OK: 111566617 (4B, equal length)
[P6] OK: 111583254 (19B, equal length)
[P7] OK: 101913087 (11B, equal length)
新增:禁用自动更新
发现程序还是会自动更新,于是在补完 7 个补丁后,我加了个 P8,把自动更新关掉:
auto_update: C.boolean().default(!0)→default(!1)autoUpdate:!0→autoUpdate:!1
现在版本锁在 0.1.20,不会被官方悄悄更新覆盖。
验证
bash
# 干净环境测试------必须输出正常
env -i HOME=/home/zd200572 PATH="$PATH" \
ANTHROPIC_API_KEY=sk-dummy \
OPERON_AUTH_OWNER_NONCE=xxx \
./claude-science --version
# claude-science 0.1.20 (release, public)
# 启动守护进程
./claude-science serve --port 8733 &
curl http://127.0.0.1:8733/api/auth/status
# {"authenticated":true, "account_uuid":"local-owner"}
运行时要点
其实二进制破解只是第一步。其他的远程报错几乎都栽在这几件事上:
- env 没注入。 不要直接 运行
./claude-science,要用它配套的 launcherclaude-science-ll(会 source~/.claude-science.env)。或者确保ANTHROPIC_API_KEY在进进程之前就设好。 - BASE_URL 填根域名。 就比如
https://api.moonshot.cn/anthropic,二进制自己拼/v1/messages。带上完整路径会重复导致 404。 - 端口转发。 daemon 默认监听
127.0.0.1:8731,远程用记得做端口转发哦。
感想
这种二进制补丁的活,看起来粗暴,但核心思路很朴素:搞清楚程序在哪些节点做了认证检查,每处改一个字节也好、几十个字节也好,只要等长,就能在不破坏结构的前提下把逻辑拧过来。
过程里最折磨的不是改代码,而是定位偏移 和保证等长。你改错一个字节,误差可能不在当前行爆发,而是几十行之后才 SyntaxError------说它崩在哪,往往不是问题在哪。
如果你也用类似工具、类似的绕过需求,希望这份记录能让你少踩几个坑。
当然,也有有账号,切换供应商的方案,Release v1.2.0 --- Desktop 重构为 CLI GUI 包装层 · YuntaoOvO/CSSwitch-Linux不过我尝试了没成功,期待大佬后期的进展。
深知Dario反华急先锋,我们要努力,超越他,让他们没有骄傲的资本!
最后分享我的结果,如果你需要的话,欢迎交流。链接:https://pan.baidu.com/s/1znsV3In07XBSRWII83fUDg?pwd=gkai 提取码:gkai 复制这段内容后打开百度网盘手机App,操作更方便哦