群晖被 C3RB3R 加密后怎么自救:免密钥恢复 Btrfs 旧数据块
先说结论
如果你的群晖 NAS 被 C3RB3R(文件后缀 .L0CK3D,留 read-me3.txt 勒索信)加密了,先别急着认栽、也别付赎金。只要你的共享是 Btrfs 文件系统、且还没做 defrag / balance / 强制修复这类破坏性操作,有一大部分文件是可以在没有密钥的情况下找回来的。原因很反直觉:C3RB3R 是「原地改写」文件,而 Btrfs 的写时复制(CoW)会把被改写的旧内容留在盘上,原文件的明文就藏在这些没被回收的旧数据块里。
开源社区已经把这个恢复流程做成了一套工具:crt106/c3rb3r-btrfs-recovery(MIT 协议,只读,只用于恢复你有权处置的数据)。本文把它的原理、路线选择、分步操作和真实案例数据讲清楚。如果你还没中招,请先读上一篇《群晖 NAS 被勒索:先升 DSM,再开不可变快照》——防住比事后救重要得多。
一、两条自救路线,先选对
能不能拿回文件,第一步不是找工具,而是判断加密进程还在不在。这两条路线收益差很多:
路线 A:加密进程还活着(收益最大)
如果事发不久、NAS 没重启,加密进程(例:/usr/bin/libgld -n 308,程序文件可能已从磁盘删除)很可能还在内存里跑。这时要做的第一件事是:
- 用
kill -STOP <pid>把它冻结,不要 kill,更不要重启。 - 然后按另外两个仓库的方法,从进程内存里把会话主密钥取出来——这样能解开全部文件,收益远大于下面那条 Btrfs 路线:
- soimy/c3rb3r-rescue:证据保全、从 RAM 恢复密钥、复制解密
- Benjamin-zlt/c3rb3r-baremetal-rescue:在物理机 DSM 上冻结加密器、导出进程内存、提取会话密钥、全量解密(已有第二个独立受害者的完整解密案例)
路线 B:加密进程已退出(本仓库补的缺口)
如果 NAS 已经重启过,或者事发已经十几小时,内存里基本找不到密钥了(该项目作者做过一次穷尽式内存扫描,结果为零)。这时就走本仓库的 Btrfs 旧数据块恢复路线:不依赖密钥,只靠文件系统留下的旧明文。
本文重点讲路线 B。两条路线可以组合:先试拿密钥,拿不到再走 Btrfs。
二、原理:为什么没密钥也能找回明文
一句话:C3RB3R 只改写了文件的几段,而被改写的旧内容在 Btrfs 上整块留了下来。
具体怎么加密的:
- 小文件:整体加密;
- 1–5MB 的文件:只加密前 1MiB;
- 大文件:加密「头、中、尾」三段,合计约 12%。
Btrfs 是写时复制文件系统。当文件被原地改写时,新内容会写到新的位置,而原来的数据块(extent)只要还被文件里「没被加密的部分」引用,就整块保留在盘上。这些旧 extent 像书挡一样夹在文件两端,作者把这种现象叫 「bookend extent」。
恢复工具做的事就是:按 Btrfs 的 extent 树,把每一个被改写的字节映射回它原来的旧 extent,直接从块设备只读读出来,拼回原始字节。更妙的是,在开启了「数据校验和」的共享上,还能用 Btrfs 自带的 CRC32C 校验和逐块证明恢复出来的内容确实是对的。
举个具体的例子更好理解:一个 100MB 的家庭视频,C3RB3R 只加密了头、中、尾三段约 12MB,剩下近 88MB 的明文原封不动躺在旧 extent 里;而一个 50KB 的文档因为小于 1MiB、被整体加密,盘上就找不到旧明文了。所以文件越大、越开启校验和、写入越早(早于最近一次快照),能捞回来的比例越高;反过来,海量小文件、数据库的处境最差。
一个容易误解的点:没勾「数据校验和」的 NoCOW 共享也不代表没救。只要数据写入时间早于该子卷的最后一次快照(哪怕快照后来删了),覆盖时仍然会走写时复制——所以快照前的老数据照样能捞。
三、这个工具是什么
crt106/c3rb3r-btrfs-recovery 本质上是一个 AI Agent 技能(SKILL.md),给 Claude Code、Codex、Cursor 这类支持技能机制的 agent 用。它把一次真实恢复的完整流程、只读工具和验证方法整理成通用指南。核心设计原则有三个:
- 只读:NAS 端只做 ioctl 查询、读文件、读块设备,结果写到 NAS 以外的盘,绝不在数据卷上落文件、绝不改写任何东西;
- 可验证:恢复出来的每一块都能和 Btrfs 校验和对照,区分「精确恢复」和「推测解码」;
- 可回退:本地换候选字节时生成
*.c3rbak备份,字节级回滚。
四、详细步骤(Btrfs 恢复路线)
第 0 步:先守住红线(这步比恢复本身重要)
在动任何东西之前,这几件事绝对不要做:
- 不要删除、覆盖任何
.L0CK3D文件,也不要清空回收站。旧数据块正是靠这些密文文件「拽着」才没被文件系统回收——你一删,旧明文可能立刻被覆盖,就真没了; - 不要做 defrag、balance、
btrfs check --repair,这些会重写数据,直接毁掉旧块; - 不要付赎金,也不要运行来源不明的「解密器」(很多是二次诈骗);
- 尽快把 NAS 断电或断网保现场,减少写入。
第 1 步:安装
用 skills CLI:
# 安装到当前项目
npx skills add crt106/c3rb3r-btrfs-recovery
# 全局安装,或指定 agent
npx skills add crt106/c3rb3r-btrfs-recovery -g
npx skills add crt106/c3rb3r-btrfs-recovery -a claude-code
手动安装:把 skills/c3rb3r-btrfs-recovery/ 整个目录复制到 agent 的技能目录(如 Claude Code 的 ~/.claude/skills/)。
第 2 步:环境自检 preflight
在任何设备上先跑这一步,它会逐项给出 OK / WARN / FAIL 和处理建议:
cd skills/c3rb3r-btrfs-recovery/scripts
python mkjob.py -- preflight /volume1/某个文件.jpg.L0CK3D > job.sh
{ printf '%s\n' "$SUDO_PW"; cat job.sh; } | ssh admin@NAS "sudo -S -p '' sh -s"
这里 mkjob.py 负责把工具和路径列表打包,经 SSH 标准输入交给 NAS 执行,不在数据卷上落文件。
第 3~6 步:确定代数 → 单文件验证 → 全量普查 → 导出验证
这一步建议直接把情况交给 agent,它会按 SKILL.md 自动执行;也可以手动跑脚本。流程是:
- 确定攻击代数 G_ATTACK:不同代际的加密格式略有差异,先对齐;
- 用已知原件做单文件验证:拿一个你本地还留着原版的同名文件去对,确认恢复逻辑正确、再批量;
- 全量普查 survey:扫描整卷,标出每个文件哪些字节被改写、能不能从旧 extent 找回;
- 流式导出 + 多重验证:把找回的字节拼回,本地多进程解码验证、对照已知原件、挑选最佳候选,最后出报告。
实操时几个要盯紧的点:preflight 任何一项出现 FAIL(比如发现是 ext4 卷、或 NAS 上找不到 Python 3),就先别继续,按它给的建议处理;G_ATTACK 代数是后面所有匹配的基准,判错会导致整批对不上;单文件验证一定要用你确认本地原版无误的文件去对,验证通过再放手批量,别拿疑似损坏的副本去校验。
脚本分工一览
| 脚本 | 运行位置 | 作用 |
|---|---|---|
c3r_btrfs.py |
NAS(root,Python 3.6+ 标准库,只读) | preflight、env、gens、survey、extract、patch、csum、plan |
mkjob.py |
本地 | 把工具和路径列表打包,经 SSH 标准输入交给 NAS 执行,不在数据卷上落文件 |
c3r_local.py |
本地 | 解包 tar 流、多进程解码验证、对照已知原件、挑选最佳候选、打补丁换候选并可回退、统计 |
第 7 步:看懂报告
恢复报告会把结果分三类,别混为一谈:
- 精确恢复并经校验和证实:最可靠,Btrfs CRC32C 逐块对得上;
- 推测后解码通过:逻辑上拼回成功,但缺校验和佐证,建议保留待核;
- 失败:这部分就是真没了。
五、兼容性:你的环境能不能用
项目已在 群晖 DSM 7.2.1(SHR、cachedev、Python 3.8)上真机验证。其他环境请先跑 preflight,它会逐项给建议。已知适配/待验证的情况:
- DSM 6、OMV、Unraid、没有 Python 3 的设备、把盘拆下来接到 Linux 电脑离线处理——文档里有各自的定制引导和报错处理;
- 不适用于 ext4(多数 QNAP 卷、群晖老卷),ZFS 需要另一套工具链。
六、真实案例:到底救回了什么
作者公开的第一个案例,恢复结果如下:
| 范围 | 结果 |
|---|---|
| homes、photo 等 CoW 共享 | 35,445 个文件 / 229.9GB,经 SHA 核对和完整解码验证 |
| 精确恢复部分的校验和抽检 | 约 20 万个 4K 块,与 Btrfs CRC32C 全部一致 |
| NoCOW 共享中、快照前写入的数据 | 又找回约 6,100 个文件 / 约 346GB(另有约 3,800 个文件本地已有原件) |
| 救不回的部分 | 1MiB 以下被整文件加密的小文件、数据库文件、NoCOW 共享中快照后写入的文件 |
一句话总结:大文件、开启校验和的共享、快照前的老数据,恢复率高;整文件加密的小文件、数据库、快照后才写入的内容,基本没戏。
七、救不回什么,以及几点提醒
- 1MiB 以下的小文件被整体加密,盘上没有旧明文可捞;
- 数据库文件(如 SQLite/PostgreSQL 这类频繁整文件改写的)往往整块重写,旧块早被覆盖;
- NoCOW 共享里、最后一次快照之后才写入的数据,覆盖时没走 CoW,旧块不存在;
- 工具本身只读,但任何恢复操作都有风险:请先保全证据、先用已知原件做小样本验证,再批量操作;
- 这不是「一键还原全部文件」的方案,它是把文件系统里侥幸留下的旧明文尽量捞回来,能捞多少取决于写入量和时间——卷越满、事发越久,被覆盖的旧块越多。
三个仓库可以组合使用:soimy/c3rb3r-rescue 和 Benjamin-zlt/c3rb3r-baremetal-rescue 负责「进程还在时从内存拿密钥」,本仓库负责「密钥没了再靠 Btrfs 旧数据块」。
八、几个常见误区
- 「删掉勒索信、改个名就能用」:文件内容已被加密改写,改名不改变数据;删掉
.L0CK3D反而会让旧数据块失去引用、加速被文件系统回收,可能让原本能捞的也捞不回。 - 「我开了快照,肯定能还原」:快照救的是快照时点之后的新增和改动,而这次是加密进程直接改写「当前版本」的文件,快照覆盖不到已被改写的当前文件;本方案恰恰是利用「快照前的旧块」,没快照时旧块也可能因 CoW 留存,别把快照当成唯一指望。
- 「付费找人解密更省事」:来源不明的「解密服务」很多是二次诈骗,既拿不回数据又泄露隐私;本文方案只读、免费、可自检,优先走它。
- 「ext4 的群晖老卷、QNAP 也能用」:不适用。ext4 没有写时复制,旧块不会被保留,需要完全不同的思路。
免责声明
本项目按「现状」提供,只用于恢复你自己有权处置的数据。工具本身只读,但任何恢复操作都有风险:请先保全证据,先用已知原件做小样本验证,再批量操作。作者不对数据损失承担责任。本文只是对该开源方案的整理与说明,不构成任何专业技术服务承诺;真要动手前,请务必先读完仓库里的 SKILL.md 与 references 目录。

