VividNightmareUnleashed/moderndeobf-forge

GitHub: VividNightmareUnleashed/moderndeobf-forge

Minecraft Forge 1.20.1 的运行时模组,将堆栈跟踪和崩溃报告中的 SRG 混淆 token 实时重写为可读的 Mojang 方法与字段名。

Stars: 0 | Forks: 0

# 现代运行时反混淆器 (Forge) Forge 1.20.1 mod。将记录的堆栈跟踪和崩溃报告中的 SRG 成员 token(`m_<数字>_`、`f_<数字>_`)在运行时重写为可读的 Mojang 名称。 修改前: ``` java.lang.NullPointerException at net.minecraft.client.renderer.GameRenderer.m_109093_(GameRenderer.java:869) at net.minecraft.client.Minecraft.m_91383_(Minecraft.java:1184) ``` 修改后: ``` java.lang.NullPointerException at net.minecraft.client.renderer.GameRenderer.render(GameRenderer.java:869) at net.minecraft.client.Minecraft.runTick(Minecraft.java:1184) ``` 适用于控制台、`latest.log` 和崩溃报告 `.txt` 文件。类名、行号和 Forge 的 `{re:classloading}` 装饰保持不变。仅替换 SRG token。 ## 缘由 在生产环境的 Forge 1.20.1 中,类名和包名已经是可读的(`net.minecraft.client.renderer.GameRenderer`)。方法和字段名仍然是 SRG token(`m_109093_`)。Fabric 为此提供了 StackDeobfuscator。在 Forge 上,Not Enough Crashes 放弃了运行时反混淆,现在转而使用 Crashy(一种事后处理的 Web 工具)。目前没有维护中的 Forge mod 能在游戏内实时执行此操作。而这个 mod 做到了。 ## 原理 首次启动时,该 mod 会下载 Mojang 官方的 1.20.1 ProGuard mappings(通过 SHA1 校验)以及 MCPConfig 的 `joined.tsrg`(通过 SHA-256 校验),然后通过 SrgUtils 将它们组合成一个包含约 6.4 万条目的扁平化 `SRG -> Mojang` 查找表。结果会被缓存到 `/moderndeobf/cache/srg2mojang-1.20.1.txt`;缓存的表在使用前会进行完整性检查。后续启动只需读取该缓存文件。所有的下载和组合工作都在主线程之外运行。 三个拦截点共享该表: 1. 每个 Log4j2 appender 都被 `RemapAppender` 包装。当日志事件携带 throwable 时,包装器会遍历原因链以及被抑制的异常列表,并使用 `Throwable.setStackTrace` 将每个 `StackTraceElement[]` 替换为重映射后的数组。每个 `AppenderRef` 级别的过滤器、appender 过滤器、错误处理程序以及 `ignoreExceptions` 行为在重新包装时均会被保留。丢失引用级别的过滤器正是导致 `latest.log` 变成 TRACE 日志洪流的 1.0.0 版本 Bug。 2. 位于 `CrashReport.(String, Throwable)` 的 Mixin 会在原地执行相同的重写操作。这适用于 `.txt` 文件在任何 Log4j appender 看到异常之前就被写入的情况。如果 mappings 仍在加载中,崩溃报告的构建会短暂等待后台加载完成,然后再回退到原始跟踪记录。 3. 通过 `Log4j2Plugins.dat` 注册的三个自定义 Log4j2 `ThrowablePatternConverter` 覆盖了 `%ex`、`%xEx` 和 `%rEx`。每个转换器都委托给匹配的内置转换器,因此渲染格式会被完全保留(`%ex` 保持纯文本,`%xEx` 保留包装后缀,`%rEx` 保留根本原因优先的排序),然后通过 `MappingTable.remap` 处理渲染后的字符串。这能捕获异常消息中的 SRG token,因为 Java 14+ 的“有用的 NullPointerException”会将方法描述符嵌入到消息文本中,而不是堆栈帧中。由于这些转换器与 Log4j2 的内置插件共享 converter key,且插件 key 的解析顺序无法保证,因此钩子程序会在安装时重新解析每个 key,如果内置插件优先级更高,则会记录一条警告;在这种情况下,堆栈帧仍会被 (1) 覆盖。 ## 构建 需要在 `JAVA_HOME` 中设置 JDK 17。 ``` ./gradlew shadowJar ``` 输出:`build/libs/moderndeobf-forge--all.jar`。将其放入任何 Forge 1.20.1 客户端或专用服务器的 `mods/` 文件夹中即可。 ### 对 mapping pipeline 进行冒烟测试 有一个独立的 Gradle source set 针对未重定位的 SrgUtils 运行 composer,且不依赖 Forge。这对于在任何对 mapping 代码的更改之后,验证已知 token(例如 `m_109093_` 解析为 `render`)是否仍能实现端到端正常运行非常有用。 ``` ./gradlew smokeMappings ``` 需要 `mappings/raw/client.txt` 和 `mappings/raw/mcp_config-1.20.1/config/joined.tsrg`。运行时下载器会获取相同的文件。 ## 配置 `/config/moderndeobf-common.toml`,在首次启动时自动创建: | 键 | 默认值 | 效果 | |---|---|---| | `enabled` | `true` | 主开关。 | | `remapCrashReports` | `true` | 在 `CrashReport` 构建时应用重写。 | | `downloadMappingsIfMissing` | `true` | 在首次启动时获取 mappings。在物理隔离(无网络)环境下请禁用此项,并自行预先填充缓存文件。 | ## 限制 - 构建前的崩溃。在 mod 构建期间安装的钩子无法看到在我们的构造函数运行之前触发的日志行。少数早期的 Mixin WARN 将保留其原始的 SRG token。StackDeobfuscator 在 Fabric 上也有同样的限制。 - mapping 未就绪超时。在首次启动期间,可能会在 mapping 下载/组合线程仍在运行时发生崩溃。Throwable 日志事件会短暂等待,崩溃报告会等待更长时间,但如果在这些有限的等待时间后 mappings 仍不可用,则会直接写入原始跟踪,而不是让游戏无限期挂起。 - 普通日志消息文本。如果某个 mod 明确地将 SRG 标识符格式化到其自身的 `LOGGER.info("text containing m_X_")` 调用中,则无法被捕获。只有堆栈跟踪和 Java 的有用 NPE(NullPointerException)消息会被捕获,后者是通过 `%ex` converter 实现的。捕获任意日志消息文本意味着需要覆盖 `%msg`,这会增加每行日志的处理开销。当前未提供此功能。 - 参数名。Mojang 的 mappings 不包含参数名;因此该 mod 也没有提供。 ## Mappings 该 mod 使用 Mojang 官方的 1.20.1 混淆 mappings 来进行反混淆。它并未内置这些 mappings。这些 mappings 由正在运行的 mod 直接从 Mojang 的 CDN 下载,来源是一个固定的 object URL,其内容在使用前会与硬编码的 SHA1 进行校验(这与 Mojang 在 `version_manifest_v2.json` 中为 1.20.1 `client.txt` 发布的摘要相同)。MCPConfig 的 zip 包和解压后的 `joined.tsrg` 在使用前会与硬编码的 SHA-256 摘要进行校验。这些输入会在本地组合成一个小的扁平化 `SRG -> Mojang` 查找表,存储在 `/moderndeobf/cache/` 目录下;派生的缓存在被信任之前会对其大小和已知的 SRG 锚点进行完整性检查。Mojang 的 mapping 许可声明如下: 无论是此仓库还是已发布的 jar 包,均不包含任何 Mojang 的 mapping 数据。每个用户磁盘上留存的唯一工件就是根据这些 mappings 在用户自己的计算机上构建的派生索引。除此之外,Minecraft 客户端及其 mappings 的使用受 [Minecraft EULA](https://account.mojang.com/documents/minecraft_eula) 的约束。 ## 免责声明 该 mod 最初是为个人使用而编写的。在开发过程中广泛使用了 [Claude](https://claude.ai)。 不包含其他任何 AI 生成的资产(废话)。 ## 许可证 MIT。详见 [LICENSE](LICENSE)。 您可以将源代码作为灵感,随意复制。如果您复用了其中大量且有实际意义的代码,请注明本项目(在您的 README 或源文件头部添加链接即可)。
标签:Forge, JS文件枚举, Minecraft, 代码去混淆, 后台面板检测, 域名枚举, 日志处理, 模组开发