群晖被 C3RB3R 加密:冻结进程、从内存取回密钥的恢复思路

2026 年 10 月 29 日,群晖官方发布公告:有攻击者在利用 2024 年 12 月就已修复的漏洞,专门打没有升级 DSM 的设备,加密数据并索要赎金。中招后的典型特征是文件扩展名变成 .L0CK3D,目录里出现 read-me3.txt。

这篇笔记整理自两个公开的受害者自述案例(soimy/c3rb3r-rescue 与 Benjamin-zlt/c3rb3r-baremetal-rescue),重点不是"怎么付钱",而是在特定前提下"怎么不花钱解回来",以及事后怎么补上入口。

一、先明确这条路径的前提

这条恢复路径只有在加密进程还活着、设备还没重启时才成立。原理是:每文件的密钥由一把会话主密钥包裹,而这把主密钥只存在于进程内存中——进程一死,密钥就没了。

如果已经重启、进程已退出,或者发现时文件早已加密完毕并关机,本文的方法不适用,只能依赖备份或专业数据恢复。

二、第一时间:冻结,不要杀,不要重启

  1. 找到加密进程。它通常已把自身二进制从磁盘删除,所以在 /proc 里表现为 (deleted):
ls -l /proc/*/exe 2>/dev/null | grep deleted
# 本案为 /usr/bin/libgld (deleted)
  1. 冻结它,而不是杀掉:
kill -STOP <PID>
grep State /proc/<PID>/status    # 期望看到 T (stopped)

kill -9 或重启等于永久丢失密钥,这是整件事最关键的一步。

  1. 在冻结之后、导出完成之前,不要重启。同时切断入口:封掉反弹 shell 的 C2 地址、关闭对外的 telnet 与 SSH、在路由器上补上 IPv6 防火墙。
  1. 立刻导出进程内存和样本(需要 root,且目标分区要有足够空间)。

三、加密格式:先理解再动手

项目内容
文件加密ChaCha8,32 字节 key + 8 字节 nonce + 64 位计数器,每个文件独立随机 key
key 保护每文件 key 用会话主密钥(AES-256-CBC)包裹,存放在文件尾之前 48 字节
文件尾共 588 字节,其中第 568 字节是会话标记、572 是模式、574 是 crypto 模式、580 是原始大小
加密模式0x24 全文件、0x25 分段、0x26 仅前 1MiB
crypto 模式0x20 真加密、0x21 诱饵数据
主密钥位置只在进程内存里,全局指针 0x5427f8

最容易被误导的地方:文件尾还有一段 304 字节的公钥包裹数据,密钥随机数也来自 /dev/urandom 播种的 DRBG,看上去"没有攻击者的私钥就无解"。但实际上程序在整个会话期间一直把 AES 主密钥留在内存里,用它包裹每个文件的 key。只要进程没死,主密钥就在。

四、恢复流程

以物理机 DSM 为例,工具都在仓库的 tools/ 下:

# 1. 导出冻结进程的样本与可写内存(本案约 2GB)
python3 tools/dump_process_memory.py <PID> /volume1/rescue/ir

# 2. 核对样本哈希;若为 802ac85d…903d,可直接使用仓库自带的地址 profile
sha256sum ir/exe.bin

# 3. 从内存镜像中取出 48 字节会话主密钥(IV 16 字节 + AES-256 key 32 字节)
python3 tools/extract_master.py ir/ master.bin

# 4. 准备 numpy:DSM 没有 pip,在别的机器下载 wheel 后拷过去解压
python3 -m zipfile -e numpy-1.24.4-*.whl tools/lib/

# 5. 先用「加密文件 + 别处的完好副本」验证密钥,三种模式都要覆盖
python3 tools/verify_pairs.py master.bin pairs.tsv

# 6. 取会话标记:任意 .L0CK3D 文件倒数第 20 字节起的 4 字节
tail -c 20 some.jpg.L0CK3D | head -c 4 | od -An -tx1

# 7. 在 NAS 本地批量解密,原密文保留,不覆盖任何已有文件
cd /volume1/SHARE && find . -name '*.L0CK3D' | sed 's|^\./||' > /volume1/rescue/files.lst
setsid nohup python3 tools/bulk_decrypt_local.py --root /volume1/SHARE \
    --list /volume1/rescue/files.lst --master master.bin --marker <标记> \
    --state /volume1/rescue > /volume1/rescue/run.out 2>&1 < /dev/null &

三条原则:先小批试点再全量;解密结果写到原文件旁边,不覆盖;原密文保留到确认无误为止。

五、案例里的真实数字

  • 主共享约 388 万个文件,被加密 84,504 个(约 2.2%),合计约 942GB,被冻结时还没跑完。
  • 抽样 400 个加密文件,全部带同一个会话标记,说明是同一把主密钥。
  • i3-10100T 单进程约 110MB/s,940GB 约 2.5 小时。
  • 验证 40 对样本,39 对逐字节一致;唯一不一致的一对是配对选错了(同尺寸但不是同一个文件),并非解密失败。

六、比恢复更重要:入口在哪

本案的入口判断可信度较高:

  • NAS 直接拿到了公网 IPv6 地址,而路由器没有启用 IPv6 防火墙;
  • telnet 23(root 可登录)、SSH 22、DSM 5000/5001 全部对公网开放;
  • 反弹 shell 连接 208.87.128.140:4001,驻留 37 天后才开始加密。

另一个案例指向的是 CVE-2024-10441(DSM 登录插件环境变量注入)。两条路径都值得排查。

对应的加固措施:

  1. 立刻升级 DSM,并打开自动更新,别再依赖"我不用它就没风险"。
  2. 关闭 telnet;SSH 只在内网或 VPN 内开放。
  3. 路由器防火墙(尤其是 IPv6)默认拒绝入站,只放行确实需要的端口。
  4. 禁用默认 admin 账号,开启两步验证,限制登录来源。
  5. 快照加离线/异地备份——勒索软件会顺带加密挂载着的备份。
  6. 注意:btrfs 共享若开了 NoCOW(chattr +C),快照和旧树根恢复会直接失效,本案就是这种情况。

七、必须知道的风险

  • 工具来自受害者自述,未经第三方审计。使用前先读代码,只在自己拥有、自己负责的设备上使用。
  • 冻结期间 NAS 处于不可用状态;导出 2GB 内存需要 root 权限和对应空间。
  • 冻结后一旦断电或重启,内存里的密钥就没了,再没有第二次机会。
  • 数据极其重要时,先做块级磁盘镜像,再在镜像上操作。
  • 只对哈希匹配的样本有效;换一个变种,地址需要重新定位。
  • 跨受害者不可复用:每次运行都会生成新的会话密钥和标记。

小结

发现 .L0CK3D 时的第一反应不是重启,而是 kill -STOP 再导出内存——这一步决定了有没有机会免费拿回数据。但更值得记住的是另一面:这次能恢复,靠的是受害人发现问题时进程恰好还活着;而真正的解法,是升级 DSM、关掉 telnet、给 IPv6 配上防火墙,别让它有机会进来。

来源