pk-node小猿口算 PK 刷局 · 本地网页服务

⚠️ 仅供学习与技术交流 · 严禁商业/刷分滥用 · 如有侵权立即删除

一个零外部依赖的本地 Node 服务:起个网页,导入小猿登录态 → 选子账号 → 刷 PK 对局。 自带 SQLite 本地库、SSE 实时日志、管理后台,可选 Cloudflare 临时内网穿透。

仅供学习与研究。本项目用于研究 Android 客户端的协议与加固实现。 请勿用于任何违反服务条款或法律法规的用途,使用风险自负。

它是什么

零依赖

只用 Node 内置模块(node:sqlite / node:http / node:crypto),不需要 npm install。

三种添加账号方式

短信验证码登录 / 密码登录 / 粘贴 cookie —— 效果完全一致。

可配置刷局

costTime、画笔算法(弧线 / 七段码)、轮间隔、答题间隔、频控退避。

立即结束

基于 AbortController 的真中断:在途请求与等待都能秒断,不用等本轮跑完。

任务并行

任务之间可并行(默认上限 3),每个任务内部仍逐轮串行。

实时日志

SSE 推送每轮进度,带事件回放与轮询兜底,刷新页面不丢历史。

快速开始

要求 Node.js >= 22(用到内置 node:sqlite)。除此之外零依赖, 不需要 WSL / Docker / qemu,也不需要任何 arm64 原生库。

方式一:下载免安装包(推荐)

# 从 Releases 下载 zip,解压后:
#   Windows:双击 start.bat
#   Linux / macOS:./start.sh

下载最新版

方式二:从源码运行

git clone https://github.com/sxd91/pk-node.git
cd pk-node
./start.sh            # 默认 http://127.0.0.1:8787(被占用会自动往后找)
# Windows:start.bat

浏览器打开 → 用 admin / admin 登录 → 第一次登录后请立刻改密。

跑一遍自检

node bin/selftest.js
# 检查:编码链路 / sign 公式 / RSA 编码 / 笔画算法 / 提交体结构 / 模块导出

工作原理

原本两个关键环节是 arm64 原生实现,现在都已解除依赖,纯 JS 即可:

环节说明
内容编码器 已拆解为「固定密钥流 XOR」,纯 JS 实现。差分分析证明 c() 就是逐位置异或一条固定密钥流(128 KiB,bin/keystream.bin),在 1B~128KiB 各长度上逐字节等于原生结果,且与真机抓包密文一致。耗时 80–250ms → ~14ms。
sign PK 端点实测不需要,已默认关闭。不带 sign 时 match 与 submit 都返回 200;带 sign 反而遇到过 403。需要时设 PK_SIGN_MODE=on。
内容编码器 已用纯 JS 复现,不再需要原生库。差分分析证明 c() 就是「与固定密钥流逐位置 XOR」(翻转 1 bit 只变同位置 1 字节、in XOR out 的流恒定、与总长无关、确定性),因此编码全零即得密钥流。
纯 JS XOR 在 1B~128KiB 各长度逐字节等于原生结果,且与真机密文一致;耗时从 80–250ms 降到 ~14ms。

在 proot 里跑 Android so 的方式:

LD_LIBRARY_PATH=bin/native bin/native/linker64 bin/native/enc_device <so> <in> <out>
关于 GitHub Pages:本项目需要 Node 运行时与 SQLite, 无法在 GitHub Pages 上运行(Pages 只能托管静态文件)。 这个页面就是 Pages 能承载的部分 —— 项目介绍;真实运行请下载 免安装包。 想验证代码是否健康,请看 CI。

已知限制(如实说明)

项说明
子账号切换 做不到。服务端切号接口对非 App 客户端一律 417;而 userid cookie 被服务端忽略(改本地 cookie 无效,已实测)。身份由服务端会话绑定 —— 如需换号,请在原版 App 里切好再重新导入 cookie。
平台限制 已无 arm64 依赖:内容编码是纯 JS,sign 默认关闭。Windows / x86_64 可以完整刷局,不需要 WSL 或 qemu。bin/native/ 可整个删掉。
频控 出题与提交接口都有服务端频控。刷太快会 403 / 400「请求过于频繁」,这是正常保护,不是 bug。
风控头 x-shepherd-did 需自己从本机取(见 README)。留空则不发送。
cookie 存储 小猿 cookie 以明文存在本地 SQLite。谁能读到那个文件谁就能拿到登录态 —— 默认只监听回环,且已被 .gitignore 排除。
第三方二进制 bin/native/ 下的系统库与 App 库不属于本项目,不在 MIT 授权范围内,见 NOTICE。

目录结构

pk-node/
├── server.js              # HTTP 服务 + 路由(零依赖)
├── start.sh / start.bat   # Linux / Windows 启动脚本
├── src/
│   ├── config.js          # 配置与协议常量
│   ├── db.js              # SQLite 层(node:sqlite)
│   ├── http.js            # HTTP 客户端 + CookieJar(可中断)
│   ├── crypto-rsa.js      # RSA 编码(手机号 / 验证码 / 密码)
│   ├── sign.js            # sign 公式(纯 JS 复现的 4 轮 MD5 链)
│   ├── keystream.js       # 内容编码器(纯 JS:固定密钥流 XOR)
│   ├── native.js          # 编码链路封装 + sign 按 PK_SIGN_MODE 开关
│   ├── strokes.js         # 画笔算法:弧线 / 七段码
│   ├── leo.js             # 小猿协议层
│   ├── pk-engine.js       # 出题 → 组 body → 加密 → 提交
│   ├── jobs.js            # 任务调度(并行 / 立即结束 / SSE 缓冲)
│   ├── tunnel.js          # Cloudflare 快速隧道
│   └── services/          # auth / login / leo-accounts
├── public/                # 网页(原生 HTML+JS+CSS,无构建)
├── bin/
│   ├── keystream.bin      # 密钥流(128 KiB,内容编码器必需)
│   ├── selftest.js        # 命令行自检
│   └── pick-port.js       # 端口避让
├── tools/
│   ├── make-release.js    # 打免安装包
│   └── keystream-extract.js # so 换版本时重提密钥流
└── .github/workflows/     # CI:自检 + 启动冒烟 + 打 tag 出 Release

免责声明

本项目仅供学习与技术交流使用。严禁用于商业用途、批量刷分、代练或任何违反服务条款与法律法规的行为; 使用者自行承担全部风险与责任。本项目与「小猿口算」及其运营方无任何关联。 若权利人认为内容侵权,请通过 Issues 告知,核实后立即删除。 详见 DISCLAIMER.md。