Files
OpenZen/README.md
T
Shirona1337 9a72330c85 feat(loader): Qt6 GUI + strict wrap matcher + scaffold tweaks
Loader UI
  - Replace the Win32 ListView loader window with a Qt6 Widgets
    one. main.cpp + new MainWindow.h/cpp: QTableWidget showing
    PID / Window Title / Window Class, QTimer auto-refresh every
    1 s, double-click a row to inject. Title filter is built in
    (startsWith "Minecraft" and not containing "Launcher"), so
    HMCL / MultiMC / generic Java apps never show up.
  - Dark Fusion theme + inline QSS so the single EXE looks the
    same on any Windows version.
  - native/vcpkg.json declares qtbase[widgets] and build.gradle's
    new findVcpkg() detects VCPKG_ROOT / C:/vcpkg / D:/vcpkg /
    ~/vcpkg / D:/vcpkg-<version> and passes
    -DCMAKE_TOOLCHAIN_FILE + -DVCPKG_TARGET_TRIPLET=
    x64-windows-static so Qt is fully statically linked. Final
    OpenZenLoader.exe stays single-file (~30 MB) with no Qt6*.dll
    or vcruntime/msvcp DLL imports beyond Windows system DLLs.
  - Drop the old ui.cpp and the now-unused run_ui() entry on
    loader.h.

Patch transformer
  - asm.patchify.loader.PatchTransformer.wrapInvoke now tries a
    strict owner+name+desc match first, falling back to the
    historical (owner || name) matcher only if strict turns up
    nothing. The old loose matcher counted every Mth.*(FFF)F call
    against a wrap aimed at Mth.lerp(FFF)F, so a same-method
    sibling wrap that deleted its own site shifted later slice
    indices and made onRenderPitchLerp miss.

LivingEntityRendererPatch
  - With the strict matcher in place, onRenderPitchLerp's slice
    drops from (4,4) to (1,1) - there is exactly one
    Mth.lerp(FFF)F call site in LivingEntityRenderer.render
    (pitch lerp), as verified via javap on the runtime srg jar.
    onRenderHeadYawLerp keeps slice (2,2) (2nd of three
    Mth.rotLerp calls = head yaw). No more "no call site of
    m_14179_" warning at boot.

Scaffold
  - Rename the BooleanSetting field from advancedBlockSearch to
    sneak so the Java name matches the user-facing label ("Sneak").

README
  - Add the vcpkg / Qt prerequisites and update the injector
    usage section to describe the auto-refreshing UI + double-
    click flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:59:01 +08:00

137 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Open Zen
> 欢迎加群 523522206 讨论该项目。
> 截止至目前,Open Zen仍然处于早期构建阶段。大量特性可能仍不可用,请谅解!当您发现有不可用的功能时,欢迎开Issues描述或直接提交Pull Request,我们将不胜感激!
**Open Zen** 是 *Zen* Minecraft 客户端的反混淆源码版本,几乎是由 [Claude](https://claude.com/)协助逆向得到。目标版本为 **Minecraft 1.20.1 + Forge 47.4.20**。
原始 Jar 经过完整混淆:类/字段/方法重命名、控制流扁平化。我使用Opus 4.7对其进行了反混淆,并结合 [Enigma MCP](https://github.com/Margele/Enigma-MCP)和Sonnet 4.6对其的类/字段/方法重命名进行猜测,最后将其还原为了可读的 Java。最终产物是一个可以直接用 Gradle 构建的工程,而不是一个二进制 blob。
> ⚠️ 本仓库**仅供学习与研究目的发布** —— 用于研究客户端侧游戏改造、ASM 字节码补丁和混淆/反混淆技术。在你不拥有的服务器上使用作弊客户端违反绝大多数服务器规则,请自行承担后果。
## 许可
原始混淆字节码未授予任何许可。本仓库中的反混淆产物、构建脚本与文档**仅供研究与学习使用**。如果你是 Zen 的原作者并希望本仓库下架或重新授权,请提 Issues。虽然提了也不会搭理你。
## 截图
![Open Zen ClickGUI](img/screenshot.png)
## 原始 Jar + Mapping
[原始Jar](./mapping/zen-orignial.jar)
[Mapping](./mapping/zen.mapping)
需要说明的是,部分喜欢裸舞的忠实Zen用户认为本源码逆向自比较旧的Zen版本。可能是因为这部分用户的脑容量只允许自己导入其他配置,因此不认识Zen的老旧UI。因此必须要说明,此源码使用的原始Jar截止至2026年5月21日是最新的。
## 细节
经过Opus 4.7长达18秒的分析,Opus认为所有的类由惨遭魔改的Zelix KlassMaster混淆。除了Zelix的Invoke Dynamic和String Encryption外,还有部分未参与任何计算的Interger \ Long变量花指令代码和仅在部分方法中出现的Flow混淆。
其中大部分类都可以经过小修小补的现有Zelix反混淆器完成,关键部分的`cinit`被Native保护,导致在Java层中没有对应的Master Key可以对Invoke Dynamic和String反混淆。但可能由于精神马来西亚人的脑袋在马来西亚骑摩托被其他车创飞导致脑溢血,即使你没有通过客户端认证也可以完整加载Native并对Class进行注册。因此我们完整的还原了所有类的Invoke Dynamic和String混淆。
其他的混淆经过Opus长达30秒的分析,顺利写出了反混淆器。 但被Rename后的代码几乎不可读,因此我用Opus 4.7制作了[Enigma MCP](https://github.com/Margele/Enigma-MCP),接入Sonnet 4.6对其参照部分客户端进行了反混淆。
再使用Opus 4.7对本项目经过长达6小时的修复和少量的人工修复,便得到了这份源码。
## 后门
原版的Zen存在大量后门,例如上报QQ、屏幕截图、扫描文件、上传文件、远程执行命令等。因此我们不推荐任何用户继续使用原版Zen,除非你愿意现在把你身上的衣服脱掉然后去本地人最多的广场裸舞,然后把自己裸舞的视频发送到Zen的群内。
> Zen开发者称,所有的后门都未实现未引用,是由夏天完成的。但笔者在分析其Native时发现了完整引用,暂且蒙古。
经过分析,当你登录Zen后就会自动触发屏幕截图。同时已有用户反馈,当你狗叫Zen开发者后,其开发者将会把你的电脑屏幕截图发送至QQ群内,所以请你不要狗叫Zen开发者。
[详细分析](./mapping/BACKDOOR.md)
## 抄袭
此项目大部分功能模块几乎全部抄袭自Naven客户端,具体详见以下分析。
[详细分析](./paste/README.md)
## 状态与注意事项
- 这是**尽力而为的反混淆结果**,部分符号是根据上下文重建的,可能与原作者的命名意图不一致。
## 构建
OpenZen 支持两种交付形式:**Forge Mod (jar)** 和 **热注入器 (单文件 EXE,内嵌 DLL)**。Mod 路径只要 JDK,注入器路径还需要 MSVC 工具链。
### 共同前置
- **JDK 17**(推荐 Microsoft Build of OpenJDK / Temurin / Azul Zulu 任一)。
- 必须设置 `JAVA_HOME` 环境变量指向该 JDK 安装目录(PowerShell 验证:`echo $env:JAVA_HOME`)。
- 仓库根目录用 `gradlew.bat` 即可,**不需要**单独安装 Gradle。
首次执行会从 ForgeMaven 下载 1.20.1 + Forge 47.4.20 的 mappings 和依赖,耗时几分钟到十几分钟,取决于网络。
### 1. 构建为 Forge Mod (jar)
零额外依赖。
```powershell
.\gradlew.bat jar
```
产物:`build/libs/hey-1.0-SNAPSHOT.jar`。把它丢进 `.minecraft/mods/`,按正常 Forge mod 启动即可。Mod ID 是 `hey`,Mod 列表里不会显示(`MinecraftPatch.onTick` 启动时会把自己从 `ModList` 摘掉)。
### 2. 构建为热注入器 (单文件 EXE)
产出一个独立的 `OpenZenLoader.exe`,DLL 已经作为资源段嵌入 EXE 内部。用户分发只需要这一个文件,运行后 GUI 列出当前所有 `javaw.exe` 进程(含 Minecraft 窗口标题),选中后点 Inject 即可。
#### 额外前置 — 必须项
1. **Visual Studio 2022**(Community 版即可,免费)。安装时勾选:
- **"使用 C++ 的桌面开发"** 工作负载
- 该工作负载的可选组件里勾上 **"适用于 Windows 的 C++ CMake 工具"**("C++ CMake tools for Windows")
2. **`JAVA_HOME` 必须指向 JDK 17**(不只是 JRE)。CMake 需要它定位 `<JAVA_HOME>/include/jni.h` 和 `<JAVA_HOME>/include/win32/jvmti.h`。
3. **CMake**:VS 2022 自带,Gradle 会自动检测——也可以独立安装 [CMake](https://cmake.org/download/) 并加入 PATH。Gradle 的检测顺序:
1. `PATH` 上的 `cmake.exe`
2. 通过 `vswhere.exe` 找 VS 2022 自带的 CMake
3. 常见独立安装位置 (`%ProgramFiles%\CMake\bin\cmake.exe` 等)
4. **vcpkg**(注入器 GUI 用 Qt6,由 vcpkg 提供静态库)。一次性安装:
```powershell
git clone https://github.com/microsoft/vcpkg.git C:\vcpkg
C:\vcpkg\bootstrap-vcpkg.bat
```
Gradle 检测顺序:环境变量 `VCPKG_ROOT` → `C:\vcpkg` → `D:\vcpkg` → `%USERPROFILE%\vcpkg`。
**首次** `./gradlew dll` 时 vcpkg 会按 `native/vcpkg.json` 编译静态 Qt6(30 分钟到 2 小时,看 CPU),之后增量 build 几分钟。Qt 完全静态链接进 EXE,所以分发依然单文件——`OpenZenLoader.exe` 自带 Qt6 + OpenZen.dll,零运行时依赖。
#### 构建命令
```powershell
.\gradlew.bat dll
```
产物:`build/dist/OpenZenLoader.exe`(OpenZen.dll 已内嵌为 RCDATA 资源段)。
构建流程:
1. `jar` → 编译 Java 源码,执行 `reobfJar` 把字节码 mojmap→SRG
2. `stageNativeJar` → 拷 jar 到 `native/zen.jar`,等待 DLL 把它作为资源段嵌入
3. `configureNative` → CMake configure (`-A x64`)
4. `buildNative` → 先 build `OpenZen.dll`,CMake 自定义命令把 DLL 拷到 loader 的 binary dir,rc.exe 再嵌入到 `OpenZenLoader.exe`
5. `packageDist` → 把 EXE 拷到 `build/dist/`
#### 使用注入器
1. 用 HMCL / Forge 启动器正常启动 Minecraft 1.20.1 Forge(**不需要**任何特殊 JVM 参数)。
2. 双击 `OpenZenLoader.exe`(会弹一次 UAC 提权)。
3. GUI 自动列出系统里**所有 Minecraft 实例**(按窗口标题 startsWith `Minecraft` 且不含 `Launcher` 过滤),每秒自动刷新一次。
4. **双击对应的行**就开始注入。
5. 状态栏出现 `Injected into PID ...` 即成功;Minecraft 内右 Shift 触发 ClickGUI 验证。
诊断日志:
- Native 端:`%TEMP%\openzen.log`
- Java 端:Minecraft 自己的 `logs/latest.log`(搜索 `OpenZen-Bootstrap`、`GameLoaderBridge`、`PatchAgent`、`ZenBootstrap`)
## 常见问题
### 布吉岛反作弊绕过
截止至目前(2026/05/23),布吉岛并未检测本项目,考虑其反作弊为黑名单类名机制。
建议构建时修改类名。
## 致谢
- 原始混淆客户端:**Zen**。
- 反混淆、符号还原与工程脚手架:**Claude** 在人工监督下完成。
- [Java Deobfuscator](https://github.com/java-deobfuscator/deobfuscator)
- 从古墓中挖出的 [Themida](https://www.oreans.com/Themida.php)
- 惨遭魔改的 [Zelix](https://www.zelix.com/)
- [Enigma MCP](https://github.com/Margele/Enigma-MCP)