VividNightmareUnleashed/moderndeobf-forge
GitHub: VividNightmareUnleashed/moderndeobf-forge
Stars: 0 | Forks: 0
# Modern Runtime Deobfuscator (Forge)
Forge 1.20.1 mod. Rewrites SRG member tokens (`m__`, `f__`)
in logged stack traces and crash reports into readable Mojang names at
runtime.
Before:
java.lang.NullPointerException
at net.minecraft.client.renderer.GameRenderer.m_109093_(GameRenderer.java:869)
at net.minecraft.client.Minecraft.m_91383_(Minecraft.java:1184)
After:
java.lang.NullPointerException
at net.minecraft.client.renderer.GameRenderer.render(GameRenderer.java:869)
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1184)
Applies to the console, `latest.log`, and crash-report `.txt` files. Class
names, line numbers, and Forge's `{re:classloading}` decorations are left
alone. Only the SRG tokens swap.
## Why
In production Forge 1.20.1, class and package names are already readable
(`net.minecraft.client.renderer.GameRenderer`). Method and field names are
still SRG tokens (`m_109093_`). Fabric has StackDeobfuscator for this. On
Forge, Not Enough Crashes dropped runtime deobfuscation and now defers to
Crashy, a post-hoc web tool. No maintained Forge mod does it live in-game.
This one does.
## How
Three interception points share that table:
1. Every Log4j2 appender is wrapped with a `RemapAppender`. When a log
event carries a throwable, the wrapper walks the cause chain plus
suppressed list and replaces each `StackTraceElement[]` with a
remapped array using `Throwable.setStackTrace`. The per-`AppenderRef`
level filter, appender filter, error handler, and `ignoreExceptions`
behavior are preserved on rewrap. Losing the ref-level filter was the
1.0.0 bug that turned `latest.log` into a TRACE firehose.
2. A Mixin at `CrashReport.(String, Throwable)` runs the same
in-place rewrite. This covers the case where the `.txt` is written
before any Log4j appender sees the exception. If mappings are still
loading, crash-report construction waits briefly for the background load
to finish before falling back to the original trace.
3. Three custom Log4j2 `ThrowablePatternConverter`s registered via
`Log4j2Plugins.dat` override `%ex`, `%xEx`, and `%rEx`. Each delegates
to the matching built-in converter, so the rendered format is preserved
exactly (`%ex` stays plain, `%xEx` keeps the packaging suffix, `%rEx`
keeps root-cause-first ordering), then runs `MappingTable.remap` over
the rendered string. This catches SRG tokens inside exception messages,
since Java 14+'s "helpful NullPointerException" embeds method descriptors
into the message text, not the frames. Because these share converter keys
with Log4j2's built-ins and plugin key resolution order isn't guaranteed,
the hook re-resolves each key at install time and logs a warning if a
built-in won instead; frames are still covered by (1) in that case.
## Build
Needs JDK 17 on `JAVA_HOME`.
./gradlew shadowJar
Output: `build/libs/moderndeobf-forge--all.jar`. Drop into any Forge
1.20.1 client or dedicated-server `mods/` folder.
### Smoke-testing the mapping pipeline
A separate Gradle source set runs the composer against un-relocated
SrgUtils with no Forge dependency. Useful for sanity-checking that a
known token (`m_109093_` resolves to `render`) still works end-to-end
after any change to the mapping code.
./gradlew smokeMappings
Requires `mappings/raw/client.txt` and
`mappings/raw/mcp_config-1.20.1/config/joined.tsrg`. The runtime
downloader fetches the same files.
## Configuration
`/config/moderndeobf-common.toml`, auto-created on first launch:
| Key | Default | Effect |
|---|---|---|
| `enabled` | `true` | Master toggle. |
| `remapCrashReports` | `true` | Apply the rewrite at `CrashReport` construction. |
| `downloadMappingsIfMissing` | `true` | Fetch maps on first launch. Disable for air-gapped use and prepopulate the cache file yourself. |
## Limitations
- Pre-construction crashes. A hook installed at mod construction can't
see log lines that fired before our constructor ran. A handful of
early Mixin WARNs will keep their raw SRG tokens. Same limitation
StackDeobfuscator has on Fabric.
- Mapping-not-ready timeout. During a first launch, a crash can happen
while the mapping download/composition thread is still running. Throwable
log events wait briefly, and crash reports wait longer, but if the maps
still are not available after that bounded wait the trace is written raw
instead of hanging the game indefinitely.
- Plain log-message text. Mods that explicitly format SRG identifiers
into their own `LOGGER.info("text containing m_X_")` calls aren't
caught. Only stack traces and Java's helpful-NPE messages, the latter
via the `%ex` converter. Catching arbitrary log-message text would
mean overriding `%msg`, which imposes per-line work. Not currently
shipped.
- Parameter names. Mojang's mappings don't include parameter names;
this mod doesn't either.
## Mappings
This mod uses Mojang's official 1.20.1 obfuscation mappings to do the
deobfuscation. It does not ship them. The mappings are downloaded by
the running mod directly from Mojang's CDN, from a pinned object URL
whose contents are verified against a hardcoded SHA1 before use (the
same digest Mojang publishes for 1.20.1 `client.txt` in
`version_manifest_v2.json`). MCPConfig's zip and extracted `joined.tsrg`
are verified against hardcoded SHA-256 digests before use. Those inputs
are composed locally into a small flat `SRG -> Mojang` lookup stored
under `/moderndeobf/cache/`; the derived cache is sanity-checked
for size and a known SRG anchor before it is trusted. Mojang's mapping
license header reads:
Neither this repository nor the published jar contains any Mojang
mapping data. The only artifact that ever lives on disk per-user is
the derived index built from those mappings, on that user's own
machine. Use of the Minecraft client and its mappings is otherwise
governed by the
[Minecraft EULA](https://account.mojang.com/documents/minecraft_eula).
## Acknowledgments
- [StackDeobfuscator](https://github.com/booky10/StackDeobfuscator)
(Fabric, LGPL-3.0, by booky10). The design template. Same idea,
different loader.
- [Linkie](https://linkie.shedaniel.me/). Manual SRG / Mojang lookups,
invaluable for spot-checking output.
- [Not Enough Crashes](https://github.com/natanfudge/Not-Enough-Crashes)
and [Crashy](https://github.com/natanfudge/crashy-website). The
post-hoc tooling this mod complements.
- [SrgUtils](https://github.com/MinecraftForge/SrgUtils). The mapping
load / reverse / chain primitives.
## Disclaimer
This mod was originally written for personal use. [Claude](https://claude.ai) was used extensively throughout development.
No AI-generated assets are otherwise present (duh).
## License
MIT. See [LICENSE](LICENSE).
Use the source as inspiration, copy as much as you want. Please credit
this project (a link in your README or source-file header is fine) if
you reuse non-trivial chunks.
标签:域名枚举