仅用于授权的隔离 Windows 虚拟机。不要对真实用户机、生产环境或未授权设备运行。
notice.json -> actions.setup -> LaunchAdvanceRun:
2.99.0.1 的 12 键黑名单会拦截 LaunchAdvanceRun,payload 不会执行。notice.cfg + slientupdate -> ServerConfig -> update.zip -> PCL\Plain Craft Launcher 2.exe:
仍然可用,零点击;PCL 正常退出时执行下载的 exe。演示视频里方法一显示的是“被拦截”,不是计算器弹出。这是 2.99.0.1 的真实行为, 也是这次复查的结论:黑名单只堵了方法一,没有堵方法二。
analysis/2.99.0.1/vm-test/pcl-2.99.0.1-poc-demo.mp4
(2:03,1920×1080,烧录中文字幕)。analysis/2.99.0.1/vm-test/evidence/。vm/frames/final3/,1434 张 1920×1080 JPEG(8 fps)+
index.csv,约 270 MB;已保留,不删除。另有 vm/frames/final、
final2 两个布局调试 take。make-video.sh 不会删除源帧。repeat/
├── build-toolkit.sh # 生成带 MBR + FAT32 分区的 USB 工具盘 toolkit.img
├── init-vm.sh # 建 60G qcow2,复制 toolkit.img 到 VM_DIR
├── run-vm.sh # 启动 QEMU(install / demo 两个阶段)
├── record.sh # QMP 帧抓取录屏(自动按空格过 ISO 启动提示)
├── record.py / qmp.py # 录制与 QMP 客户端
├── extract-evidence.sh # 关机后从 FAT 镜像取出 evidence
├── make-video.sh # 按时间线裁剪 + 烧中文字幕 + 编码
├── make_srt.py # 从 demo-timeline.csv 生成 SRT
├── subtitles/captions.tsv # 事件 ID → 中文字幕
├── toolkit/
│ ├── autounattend.xml # Windows 10 LTSC 2021 无人值守
│ └── pcl-test/
│ ├── firstlogon.cmd # FirstLogonCommands 入口
│ ├── prepare.ps1 # 建 lab 环境、复制 PoC、注册重试任务
│ ├── demo.ps1 # 7 步演示的“导演”脚本
│ ├── lib-gui.ps1 # 分辨率、控制台字体、窗口排布
│ ├── arrange-windows.ps1
│ ├── close-pcl.ps1
│ ├── watch-staging.ps1
│ └── PCLPoC/ # PoC 脚本,不含 certs/ 私钥
└── README.md
sfdisk、mkfs.vfat(dosfstools)、mtools、ffmpeg(带 libass)、
Noto Sans CJK SC 字体。en-us_windows_10_enterprise_ltsc_2021_x64_dvd_d289cf96.iso。PCL 正式版 2.99.0.1.zip,SHA-256
4d239a62ed66fb9ebcf4633fd881eb098e9a7e4f296f0e414b58aa2f1f7f7830。ISO 和 PCL zip 不随本目录分发,请从合法来源自备。
cd repeat
# 1. 生成工具盘(默认在仓库根目录找 PCL*.zip,也可 PCL_ZIP=... 指定)
./build-toolkit.sh
# 2. 建 VM 磁盘;默认 $HOME/.HHD/PCLPoC-VM
./init-vm.sh
# 3. 先开录屏(后台),再启动安装
./record.sh frames/install &
./run-vm.sh install
wait
安装是无人值守的:约 10–25 分钟后进入首次登录,firstlogon.cmd -> prepare.ps1 -> demo.ps1
自动开始 7 步演示,最后关机。record.sh 会一直录到 QEMU 退出。
# 4. 取证据
./extract-evidence.sh
# 5. 裁出演示段、烧字幕
./make-video.sh frames/install pcl-2.99.0.1-poc-demo.mp4
如果第一次演示失败,VM 会关机。往工具盘放一个重试标记,再以 demo 阶段重启:
echo retry > /tmp/retry.flag
mcopy -i "$HOME/.HHD/PCLPoC-VM/toolkit.img@@1M" /tmp/retry.flag ::/pcl-test/retry.flag
./record.sh frames/demo &
./run-vm.sh demo
wait
prepare.ps1 注册了登录任务 PCLPoCRetry;它检查 pcl-test\retry.flag,存在就重跑
firstlogon.cmd。AutoLogon 次数为 999,所以 run-vm.sh demo 会自动登录并开始。
| 视频字幕事件 | 画面 |
|---|---|
step1 |
进入 Windows 桌面,终端左、桌面右,显示 OS/用户/分辨率 |
step2 |
终端复制 PCL 2.99.0.1.zip 到桌面,右侧资源管理器刷新 |
step3 |
解压 Desktop\PCL,显示 exe 大小与 SHA-256 |
step4 |
启动本地 HTTPS 公告服务器 + hosts + 自签 CA;PCL 在右侧打开 |
method1 |
notice.json 里的 setup.LaunchAdvanceRun |
blocked |
PCL 日志出现 被禁止的设置项:LaunchAdvanceRun,无 marker |
step6 |
删除整个 Desktop\PCL |
step7 |
重新解压,slientupdate 下载 update.zip 覆盖 PCL\Plain Craft Launcher 2.exe |
success |
PCL 退出后 marker 出现;staging exe 与 zip entry 哈希一致 |
end |
右侧 Notepad 展示 RESULT.txt,终端总结 |
QEMU usb-storage 的 removable 默认是 off。这样 Windows 会把工具盘当成固定磁盘,
Windows Setup 不会扫描它上面的 autounattend.xml,而是停在语言选择页。
run-vm.sh 里固定使用:
-device usb-storage,drive=usb0,bus=xhci.0,removable=on,serial=PCLTOOL
工具盘是 MBR + 单个 FAT32 分区(type 0x0c),autounattend.xml 在分区根目录。
Windows PE 把它挂成可移动盘后,Setup 会自动读取。
autounattend.xml 的 FirstLogonCommands 在 C:–K: 里找 pcl-test\firstlogon.cmd,
启动 prepare.ps1(最小化)→ demo.ps1(正常窗口)。prepare.ps1 负责:
HKCU\Software\PCL\SystemEulaVersion=2,跳过 PCL 用户协议;C:\PCLPoC;首次启动 SystemLastVersionReg=0 时 PCL 不会弹更新日志(源码条件
LastVersionCode > 0 && num < 413),所以不需要预跑 PCL。
Windows 10 LTSC 2021 默认可能是 150% 缩放。demo 会声明 DPI 感知,但控制台字体仍按 150% 放大;因此:
Set-ConsoleSize -Columns 66 -Rows 36),实际约 1190 px;HKCU\...\AppCompatFlags\Layers 的 ~ HIGHDPIAWARE 标记按 100% 渲染,
实际约 670 px,位于 x≈1250–1920;demo.log 里的 console=918 pcl=998 是计算值,
实际像素以录屏为准。字幕在 make-video.sh 里用 FontSize=9:libass 对无 PlayRes 的 SRT 会按 1080p
放大,9 约等于 34 px;不要按字面理解成 9 px。
demo.ps1 用 ChangeDisplaySettings 尝试 1920×1080(回退 1600×900/1366×768),
把控制台放在左侧;arrange-windows.ps1 每 500ms 把 PCL/calc 移到右侧。
这样终端不会被 PCL 挡住,PCL 也不会被终端挡住。
record.py 通过 QMP screendump 以约 8fps 抓帧,写 frames/frame-%06d.jpg
和 index.csv(帧号、epoch 毫秒)。demo.ps1 写 evidence/demo-timeline.csv(事件 ID、epoch 毫秒)。make_srt.py 找 step1 最近的帧作为视频起点,按事件 epoch 生成 demo.srt;
make-video.sh 从该帧开始编码并烧字幕。QMP 是单客户端协议。需要手动发键/截图时,先停掉 record.sh,否则第二个客户端
连不上。
方法一(-Mode launch):
/notice.cfg、/notice.json;执行 PCL 服务器公告动作失败(setup, ...),异常消息含
被禁止的设置项:LaunchAdvanceRun;%TEMP%\pcl-poc-marker.txt 不存在。方法二(-Mode update):
/notice.cfg、/ServerConfig.json、/notice.json、/update.zip;Desktop\PCL\PCL\Plain Craft Launcher 2.exe 出现(payload,约 4–5 KB);2026-... pid=... args=--update ...;staging.exe 与 update.zip 内 Plain Craft Launcher 2.exe 的 SHA-256 一致;poc-run.log 末尾有 [+] SUCCESS: payload executed.。RESULT.txt、demo.log、poc-run.log、server.out.log、PCL Log*.txt 都在
evidence/ 里。
New-SelfSignedCertificate 现生成,
退出时从证书库删除;certs/ 不复制进工具盘。certs/*.key、server.pfx 属于实验室私钥材料;不要发布。
repeat/.gitignore 已忽略 *.key、*.pfx 和 PCLPoC/certs/。lab,密码 PclPoC!2026 仅用于隔离实验;请按自己的环境修改
autounattend.xml 后重建工具盘。127.0.0.1;不要把该 VM 接入真实网络。$VM_DIR 应保持私有,不要分发。evidence/ 和录屏可能包含 lab VM 的路径/用户名/PID;公开前自行检查。LaunchAdvanceRun
真正执行,需要 2.99.0.0 + 一个可启动的 Minecraft 实例,不在本复现包范围内。calc.exe;marker 和 staging hash 才是执行证据。.HHD 在加密卷上会更慢。