🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

等长补丁器 loyalchiiina/dsh-asar-patch

DeepSeek Harness
loyalchiiina11 天前有提交已提供中文文档扫描:无法判定

原地改写 Electron 包内代码,无需重打包

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add loyalchiiina/dsh-asar-patch
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · dev
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 11 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/21) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
⚪ 扫描:无法判定尚无人工评估
展开查看扫描说明与证据 ↓

已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。

  • · 包内无可扫 JS
  • · TS 源码(可能为非 JS 实现或未发布源码),无法判定
扫描于 2026/11/1(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

Electron app.asar 等长就地补丁:不用重新打包、不用停应用,直接在 180MB 归档里改打包好的 bundle。

README

由 DeepSeek 最新模型翻译生成
dsh-asar-patch 给 Electron 应用(尤其 DSH 桌面端)的 app.asar 做「等长就地补丁」——改官方界面内部代码,不重建 180MB 包、不停应用。 起因:想改 DSH 桌面端「设置 → 模型 → 模型目录」的交互(让所有模型行默认展开),但那部分 UI 只存在于 resources/app.asar 里,app.asar.unpacked 没有副本,装同名插件又会被 dsh-client-modules 的重复源校验直接拦下。 结论:只要新内容与旧内容字节数完全相同,就能原地覆写 + 就地替换 header 里的 integrity hash。 全程 fileSize 不变、所有 offset 不变、应用运行中也能写。
展开完整文档(README 剩余 1 节)
dsh-asar-patch

给 Electron 应用(尤其 DSH 桌面端)的 app.asar 做「等长就地补丁」——改官方界面内部代码,不重建 180MB 包、不停应用。

起因:想改 DSH 桌面端「设置 → 模型 → 模型目录」的交互(让所有模型行默认展开),但那部分 UI 只存在于 resources/app.asar 里,app.asar.unpacked 没有副本,装同名插件又会被 dsh-client-modules 的重复源校验直接拦下。

结论:只要新内容与旧内容字节数完全相同,就能原地覆写 + 就地替换 header 里的 integrity hash。
全程 fileSize 不变、所有 offset 不变、应用运行中也能写。

它解决什么问题

| 你想做的事 | 常规做法 | 现实 |
| 改 Electron 应用里某个前端 bundle | 找到文件改掉 | 它在 app.asar 里,unpacked 目录没有 |
| 用插件覆盖官方 UI 模块 | 装一个同名包 | 多数宿主有「同名包多源解析」硬校验,直接报错 |
| 改 node_modules 里的副本 | 改掉重启 | 运行时从 asar 解析,改 node_modules 完全无效 |
| 重建整个 asar | @electron/asar 重打包 | 180MB 全量重写、header 变长导致所有偏移平移、风险高 |
| 等长就地补丁(本项目) | 原偏移覆写等长字节 + 替换 64 位 hex hash | 秒级完成、fileSize 与所有 offset 不变、可精确回滚 |

快速开始

0. 看清结构:哪些条目 packed、多大、有没有 integrity
node scripts/asar-verify.js --asar "<App>/resources/app.asar" --list

1. 导出原文(作为改前基线和 diff 对照)
node scripts/asar-extract.js --asar "<App>/resources/app.asar" \
--entry "node_modules/@scope/pkg/lib/client.js" \
--out "./client.orig.js"

2. 在副本上改代码,然后务必确认字节数相等 stat -c%s ./client.new.js # 必须 == 步骤 0 显示的 size

3. 干跑:长度不符 / 带 BOM / block 数变化都会被拦
node scripts/asar-patch.js --asar "<App>/resources/app.asar" \
--entry "node_modules/@scope/pkg/lib/client.js" \
--file "./client.new.js" --dry-run

4. 正式写(自动备份原始字节 + header 到 asar-backup-<时间戳>/)
node scripts/asar-patch.js --asar "<App>/resources/app.asar" \
--entry "node_modules/@scope/pkg/lib/client.js" \
--file "./client.new.js"

5. 全量校验:所有 packed 条目 integrity 全过 + 目标条目 == 你的文件
node scripts/asar-verify.js --asar "<App>/resources/app.asar" \
--entry "node_modules/@scope/pkg/lib/client.js" \
--file "./client.new.js"

回滚就是再打一次等长补丁(备份文件与原条目等长):

node scripts/asar-patch.js --asar "<App>/resources/app.asar" \
--entry "node_modules/@scope/pkg/lib/client.js" \
--file "<备份目录>/<entry>.orig"

三条硬约束

约束 1 新内容字节数 == 原条目 size → fileSize、dataOffset、所有 offset 全不变

约束 2 header 里只改 integrity 的 hex(64 字符等长替换) → jsonLen 不变,后续字节不挪位

约束 3 先写载荷、再写 header、都 fsync → 中途失败时 header 仍指旧内容,可被 hash 检出

文件内部字节可以自由增删,只有「总长度」必须相等。
所以改代码时:加了 1 个字符,就减掉 1 个缩进 tab;删了 20 字节,就在注释区补 20 个空格。

💡 凑等长最实用的技巧:语义反转代替新增逻辑。
本项目实战案例:把 expanded: expanded.has(index) 改成 expanded: !expanded.has(index),只加 1 个 !、减 1 个 tab 就等长了 —— 同时把「已展开集合」的语义反转为「已折叠集合」,空 Set 即全展开,state 声明和 toggle 逻辑一行都不用动。
最小语义改动 = 最容易满足等长 = 最好验证。

为什么必须先查 Electron fuse

asar header 里每条文件都带 integrity: { algorithm, hash, blockSize, blocks[] },但它生不生效取决于 Electron 的 fuse 开关:

在应用主 exe 里搜 sentinel 字符串 dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX,其后紧跟 1 字节 version、1 字节 count、count 字节 fuse 值。

按 Electron 官方 fuse 顺序:runAsNode / cookieEncryption / nodeOptionsEnv / nodeCliInspect / embeddedAsarIntegrityValidation(index 4) / onlyLoadAppFromAsar(index 5) / v8Snapshot / grantFileProtocolExtraPrivileges / …

- index 4 = 0(关闭) → 改 asar 字节不会被拦(本项目实测的 DSH 桌面端即属此类)
- index 4 = 1(开启) → Electron 启动会校验,必须同步改 hash(本脚本已做)或考虑重建

即便 fuse 关闭,本项目仍然同步更新 hash,因为:① 校验脚本要靠它证明「只有我改的条变了」; ② 将来 fuse 变化或应用升级时不会突然崩;③ @electron/asar 等工具交叉校验时会报不一致。

验证底线(缺一不可)

| 检查 | 证明什么 |
| asar-verify 全量 integrity 扫描 0 失配 | 除我改的条目,其它一个字节都没动 |
| fileSize 改前 == 改后 | asar 没有被意外重排 |
| header 里新 hash 反替换回旧 hash 后与备份逐字节相等 | header 除 hash 外一字未动 |
| 与正本做语义 diff,只差预期的那几行 | 写进去的确实是我的补丁,不是别的 |
| 相邻条目 offset 无重叠 | 没有把两个条目写重叠 |

四条真实踩过的坑

坑 1:dataOffset 公式错 4 字节 → 「备份」本身就是坏的

dataOffset = 16 + ((jsonLen + 3) & ~3) // ✓ 正确(= 8 + u32@4,两式恒等可互校验)
dataOffset = 16 + ((jsonLen + 7) & ~3) // ✗ 多 4 字节

用错公式时备份出来的 .orig 整体缺开头 4 字节(window.__ModuleLoader__ → ow.__ModuleLoader__),拿它回滚会把 bundle 头部写坏。

铁律:备份完必须回读校验。 拿一个「已知内容」验证偏移算对了 ——最方便的对象是某个 package.json(必须以 { 开头且是合法 JSON)。

坑 2:header JSON 尾部有 \0 对齐填充

直接 JSON.parse(headerBuf.toString('utf8')) 会报 SyntaxError: Unexpected token ':' —— 看着像 JSON 语法错,其实是尾部的 \0 填充。必须先剥:

const text = headerBuf.toString('utf8').replace(/\u0000+$/g, '');

坑 3:fs.readSync 返回字节数,不是 Buffer

const json = fs.readSync(fd, buf, 0, len, 16); // ✗ json 是数字 const n = fs.readSync(fd, buf, 0, len, 16); // ✓
if (n !== len) throw new Error('短读');
const json = buf.toString('utf8');

坑 4:运行时到底加载哪份文件,别靠目录结构猜

改了 ~/.app/profiles/node_modules/... 和 npm 全局包都界面毫无变化,因为运行时实际从 file:///<App>/resources/app.asar/node_modules/... 解析。

判据:看崩溃/报错堆栈里的 file:// URL 前缀,不要推 Node 的解析规则。
静态推导(createRequire(baseUrl).resolve(...) → profile 目录)曾把排查引向完全错误的方向。

什么时候不能用等长补丁

| 情形 | 后果 | 出路 |
| 新内容做不到与原文件等长 | 所有 offset 平移、整个包要重写 | 减字节凑等长(见上方技巧);或老实用 @electron/asar 重建 |
| 要新增/删除文件 | header 结构变 | 重建 |
| 目标条目是 unpacked | 内容不在 asar 里 | 直接改 app.asar.unpacked/ 下真实文件,不用碰 asar |
| fuse embeddedAsarIntegrityValidation 开启且无法关 | Electron 启动校验失败 | 重建 + 同步 hash;或走应用官方更新渠道 |

生效时机

客户端 bundle 只在应用启动时加载 → 必须重启应用(多数 Electron 应用的 Ctrl+R 只重载页面、不重载客户端 bundle)。

最干净的生效判据:app.asar 的 mtime 早于 应用进程的 CreationDate。

⚠️ 本方法改的是安装目录,应用每次升级/重装都会整份覆盖 app.asar → 补丁会被抹掉。
升级后重跑一遍脚本即可(脚本幂等)。

脚本说明

| 脚本 | 作用 |
| scripts/asar-lib.js | 零依赖读写库:解析 header、按路径取条目、遍历全树、计算/校验 integrity |
| scripts/asar-extract.js | 导出单文件或整个目录到本地(供阅读、diff、改完后打补丁) |
| scripts/asar-patch.js | 等长就地补丁:长度/BOM/block 数校验 → 备份 → 覆写载荷 → 替换 hash → 回读校验 |
| scripts/asar-verify.js | 全量校验:所有 packed 条目 integrity 扫描 + 偏移无重叠 + 指定条目内容断言 |

零外部依赖(只用 Node 内置 fs / crypto / path),Node ≥ 14 即可。

完整方法论(含 asar 二进制格式逐字段实测表)→ docs/asar-format-and-inplace-patch.md 配置层怎么改(模型目录的 maxTokens / 图片输入 / 推理等级)→ docs/model-catalog-config.md

许可证

MIT
预览分享卡片长什么样 ↓loyalchiiina/dsh-asar-patch
分享 · DeepSeek Harness Hub
loyalchiiina/dsh-asar-patch

原地改写 Electron 包内代码,无需重打包

回到顶部