npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cloak-pro-nopatch

v1.2.3

Published

Unlimited concurrent sessions for an already patched CloakBrowser Pro build, without touching the browser installation.

Readme

cloak-pro-nopatch

让 CloakBrowser Pro 解除并发席位限制,跑起来之后运行期完全不碰浏览器安装目录。

这个仓库里有两个东西,按顺序用:

| 部件 | 文件 | 做什么 | 是否写盘 | |---|---|---|---| | 一次性补丁 CLI | patch.js | 把 chrome.dll 里 4 处签名校验槽位改成 mov eax,1,并留一份 .orig 备份 | 写一次,之后不再动 | | 运行时模块 | index.ts → dist/ | 起进程内本地授权 API,把每次启动指过去,于是席位不再计数 | 不写,只读检查 |

补丁只做一次(换新版本构建时再做一次),运行时模块每次启动都只在内存里干活。

使用方法

1. 下载 Pro 版 Cloak Browser

解压到任意目录,记下根目录路径(里面有 chrome.exe 和 chrome.dll 的那一层),例如:

D:\packages\chromium-155.0.8059.39.1-pro

2. 打补丁

node ./patch.js "D:\packages\chromium-155.0.8059.39.1-pro"

引号别省,路径里有反斜杠。跑完会打印目标文件、sha256、识别到的构建版本、4 个槽位的状态,最后是 OK — license signature gate bypassed。首次执行会生成 chrome.dll.orig 备份。

保险起见,第一次可以先干跑,只看不改:

node ./patch.js "D:\packages\chromium-155.0.8059.39.1-pro" --dry-run

其它参数:

| 参数 | 说明 | |---|---| | --dry-run / -n | 只报告会改哪几个槽位,不写盘 | | --revert | 从 chrome.dll.orig 还原 | | --no-backup | 不建 .orig 备份 | | --sites 0x…,0x… | 手动指定槽位(自动识别失败时用) | | --verify-va 0x… | 手动指定 verify 例程地址 | | --json | 输出机器可读报告 | | --help / -h | 帮助 |

也可以直接传 chrome.exe 或 chrome.dll 的路径;一次传多个路径会批量处理。退出码:0 成功或无事可做,1 失败,2 用法错误。

patch.js 没有依赖、不联网、不启动浏览器,只改磁盘上的 DLL。

3. 正常使用

补丁打好后,直接用下面的模块起浏览器即可(也可以继续用官方 wrapper,但席位限制的解除来自模块起的本地授权 API)。

4. 跑一下测试

node ./test.js

它会先后开 3 个实例(百度 / example.com),逐个打印标题,能出三行标题就说明无席位限制。

test.js 里 import 的是 ./dist/index.js,所以第一次跑之前先构建一次: npm i && npm run build。

代码里怎么用

import { launch } from 'cloak-pro-nopatch';

const browser = await launch({
    headless: false,
    licenseKey: 'dev_local',
});

const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());

licenseKey 填任意非空字符串即可(本地授权 API 只对 sha256(key) 做一致性比对);'dev_local' 是常用的占位值。留空会让二进制自己 exit 77。

想显式锁定某个构建(多版本共存时推荐):

const browser = await launch({
    headless: false,
    licenseKey: 'dev_local',
    browserDir: 'D:\\packages\\chromium-155.0.8059.39.1-pro',
});

不传 browserDir / binaryPath 时,按 CLOAKBROWSER_BINARY_PATH → ensureBinary() → ~/.cloakbrowser 下最新 chromium-*-pro 解析。

和 cloak-pro-unlimited 的区别

| | cloak-pro-unlimited | cloak-pro-nopatch(本包) | |---|---|---| | 修改 chrome.dll | 自动打补丁 + 建 .orig 备份 | 不写、不备份、不还原,只读检查 | | 适合场景 | 手里是原版 Pro 安装 | 手里已有打好补丁的包(例如自己压的那个) | | 代码里的写操作 | patchDll / revertDll | 源码与编译产物中都不存在 | | 席位限制 | 消失 | 消失(前提:构建本身已绕过签名校验) | | 其它 | 版本升级后要重新打补丁 | 换包就换目录,模块不用动 |

patch.js 就是把 cloak-pro-unlimited 的补丁逻辑抽出来单独跑一次;之后交给本包做只读运行。

运行时模块做了什么

只做三件事,都不落盘:

  1. 只读检查 chrome.dll:定位 license runtime 的签名校验槽位,判断这个构建是否已经绕过。 检测方式是公钥锚定,与版本、与是否已补过都无关:内嵌的 32 字节服务端公钥正好位于 /api/license/session/end 字符串前 0x20 字节,找所有 lea r9, [rip+公钥],其后十几字节 内就是那个 5 字节槽位 —— E8 rel32 表示未补,B8 01 00 00 00 表示已补。所以自动更新到新 Chromium、或换成别的工具补过的包,都能正确识别(patched: true);
  2. 进程内起本地授权 API(随机端口,仅 127.0.0.1),每个实例发独立 business 租约;
  3. 注入两个变量再启动:CLOAKBROWSER_LICENSE_API(指向本地 API)和 executablePath / CLOAKBROWSER_BINARY_PATH(锁定到你指定的构建,避免包装层另下别的版本)。

内置 profile(sha256 为未打补丁原版的哈希,用于秒级识别与交叉校验):

| 版本 | 原版 sha256(前 16 位) | verify 例程 | 槽位数 | |---|---|---|---| | 154.0.8037.57.1 | 8a9f1e9020bac1f4… | 0x1888c3010 | 4 | | 155.0.8059.39.1 | 336f3af913c2a3cd… | 0x188b3eb50 | 4 |

API

| 导出 | 说明 | |---|---| | launch(opts) | 等价 cloakbrowser.launch,启动前自动 prepare() | | launchContext(opts) / launchPersistentContext(opts) | 同上,返回 context | | prepare(opts) | 解析构建 + 只读检查 + 起本地 API,返回 PreparedRuntime(含 sha256 快照) | | status(opts) | 只读体检:路径 / sha256 / 是否已打补丁 / 站点 / 是否有 .orig / 是否被改过 | | isPatched(opts) | 单个布尔:这个构建的签名校验是否已绕过 | | verifyUnmodified(snapshot) | 重新取哈希比对,被外部改动会抛错 | | snapshotBrowser(dll) | 拿 { sha256, size, mtimeMs } 快照 | | inspectBrowser(dll) / discoverSites / KNOWN_PROFILES | 纯只读底层工具 | | createLicenseServer(opts) | 单独用本地授权 API | | shutdown() / current() | 关服务 / 看当前准备好的状态 |

参数额外认:plan(默认 business)、requirePatched(默认 true)、 assertUnmodified(默认 false)、browserDir / binaryPath、log。

requirePatched: true 是这里的保险:如果指向的构建仍在校验签名,会直接拒绝并说明 「这个构建还没打补丁,启动会以 exit 78 失败」,而不是让你拿到一堆莫名其妙的报错。 若你的绕过方式不是这 4 处 call,传 requirePatched: false 跳过该判断。

只读保证怎么验证的

npm run test:readonly

它会:快照整个浏览器目录(26 个文件的 size + mtime)和 chrome.dll 的 sha256 → 并发起 3 个实例各加载一个页面 → 再快照比对 → 并且扫描本包编译产物里是否出现 writeFileSync / copyFileSync / renameSync / unlinkSync / mkdirSync / 'r+' 等写操作。

实测输出:

patched    : true (known:154.0.8037.57.1 (structural, patched))
#1 154.0.8037.57 "Example Domain"
#2 154.0.8037.57 "Example Domain"
#3 154.0.8037.57 "Example Domain"

files before/after: 26/26
chrome.dll.orig    : absent
write syscalls     : none found

PASS — 3 concurrent sessions, installation bit-identical, no write paths in the module

requirePatched 的拦截也单独验证过:把一份副本的 4 个槽位还原成原始 call 字节 (sha256 回到 8a9f1e90…),prepare() 立即报 this build still verifies the lease signature (4 unpatched site(s), known:154…),且没有写入该副本。

常见问题

补丁和模块的分工? patch.js 只改一次 DLL(这是唯一写盘的地方);本包运行期只读。 两者可以分开用:别的工具补过的构建,直接用本包就行。

这个包会不会在别的地方写文件? 不会。它不创建 .orig、不改 ~/.cloakbrowser/license.key、 不写缓存文件;唯一的进程状态是内存里的 HTTP 监听和 process.env。

node ./patch.js 报 could not locate the signature gate? 说明这个构建的槽位布局不是预期的 4 处 call。先用 --dry-run --json 看报告,再考虑 --sites / --verify-va 手动指定。

node ./test.js 报 dev_local is not defined? licenseKey 漏了引号,写成 'dev_local'。

我的构建要满足什么条件? chrome.dll 里的 4 处 call ED25519_verify 已改成 mov eax,1 (patch.js 的结果就是这样),或者干脆是没有 license runtime 的免费构建。 用 isPatched() / status() 一查便知。

key 填什么? 任意非空字符串即可:本地 API 用 sha256(key) 生成租约里的 license_key_hash,客户端只做一致性比对。留空会让二进制自己 exit 77。

会占真实席位吗? 不会。/api/license/session/start 被重定向到本地,服务端 active 始终是 0。

心跳怎么办? 本地 API 每 60s 应答一次 /heartbeat,长时间挂着不会被踢。

升级 / 换包怎么办? 对新构建再跑一次 node ./patch.js "新目录";模块侧直接换 browserDir 就行,不缓存构建(按选择器缓存的是 prepare() 结果,shutdown() 后清空)。

已知边界

  • 构建本身必须已绕过签名校验 —— patch.js 负责这件事,或由你已有的构建提供;
  • K_wrapped 是本地随机占位值,依赖该密钥的服务端素材不会被真正解开(实测不影响启动与指纹参数);
  • 只处理「按 license key 席位计费」这一层,不自造服务端其它权益。

目录

cloak-pro-nopatch/
├── patch.js            一次性补丁 CLI(无依赖,改 chrome.dll + .orig 备份 + --revert)
├── test.js             冒烟测试:连开 3 个实例打印页面标题
├── index.ts            公共 API:prepare / launch / status / isPatched / verifyUnmodified …
├── src/
│   ├── types.ts        全部类型(没有 PatchReport —— 运行期不存在写路径)
│   ├── inspect.ts      只读检查:站点识别、patched 判定、sha256 快照、可读写探测
│   ├── pe.ts           PE32+ 解析、VA↔偏移、字符串定位、RIP 引用扫描(全只读)
│   ├── resolve.ts      定位构建:binaryPath → browserDir → 环境变量 → ensureBinary → 目录扫描
│   ├── server.ts       进程内授权 API(随机端口,仅 127.0.0.1)
│   └── errors.ts       启动失败解码:退出码 → 根因(76/77/78/79、0xC0000135…)
├── example.ts          并发示例
├── diagnose.ts         一键自检(环境 / 目录清单 / 补丁状态 / API 自探 / 启动 / denial 文件)
├── test_readonly.ts    只读保证的自动化验证
├── tsconfig.json       strict / NodeNext / declaration
├── .gitignore          忽略 node_modules、dist、日志、浏览器载荷与 *.orig
└── dist/               npm run build 产物(不提交)

维护

| 命令 | 作用 | |---|---| | npm run build | 先清 dist/ 再编译(无 sourcemap,产物 20 个文件) | | npm run typecheck | strict + noUnusedLocals 类型检查 | | npm run diagnose | 一键自检,见上文输出 | | npm run test:readonly | 只读保证回归(目录快照 + 写调用扫描) | | npm run example | 并发示例(N=10 HEADED=1) | | npm run check | typecheck → build → 只读回归,一条命令验完 | | node ./patch.js "目录" | 给新构建打补丁(不打进 npm scripts,它是独立 CLI) |

代码约定:

  • 本包不允许出现 writeFileSync / copyFileSync / renameSync / unlinkSync / mkdirSync 或 'r+' 打开方式 —— test:readonly 会扫描编译产物强制这条约束(patch.js 是独立的写盘 CLI, 不在 dist/ 内,不受此约束);
  • 新增构建版本时只需往 KNOWN_PROFILES(运行时)和 patch.js 的 PROFILES(补丁 CLI)里各补一条, 其余场景由公钥锚定发现兜底。