Log4JExploitFix
基本信息
修复 Log4Shell(CVE-2021-44228)利用。配置开关 log4jExploitFix
(默认 true,分组 bugfixes)。
目标:无目标类 → 全局补丁
addPatcher(new Log4JLoggerWrapperPatcher("Log4JExploitFix"));
补丁构造:super(name, "", "", "") —— 目标类名为空串,
因此在 addPatcher() 中落入 globalPatchers 分支,
对每一个被加载的类执行检查(代价很高,见下)。
三重版本探测
启用前先判断 log4j 是否含 org/apache/logging/log4j/core/lookup/JndiLookup:
| 判定 | 常量 | 长度 |
|---|---|---|
| Mojang 官方已修补版 | JNDILOOKUP_MOJANG_SIZE |
738 |
| MultiMC 修补版 | JNDILOOKUP_MULTIMC_SIZE |
983 |
流程:
- 取
JndiLookup.class字节流,读入 8192 字节缓冲; - 按长度匹配 → 选定预期 SHA-256;
- 算实际 SHA-256 比对 —— 一致则打日志
\<source\> JndiLookup class detected; skipping Log4JExploitFix...并置vulnerableJndiLookupFound = false; - 类不存在则
Class.forName兜底判否; - 仍未判定为安全才
addPatcher。
⚠️ 资源流未关闭
异常分支里 jndiLookupStream.close() 只在 catch 内调用,
正常读完的路径不关闭流(BugfixModClassTransformer.java:477-490)。
每个日志级别仅执行一次,影响有限,但属资源泄漏。
⚠️ 全局补丁的性能代价
因为目标类名为空,本补丁进入 globalPatchers,
transform() 对每个类都调用一次 patch()。
AbstractPatcher.patch 首步即 new ClassReader(bytes)(失败静默返回),
在不支持的类(如 LiteLoader 相关)上会抛 NullPointerException 并被吞掉。
相关条目
源码
src/main/java/pl/asie/foamfix/coremod/patchers/Log4JLoggerWrapperPatcher.javasrc/main/java/pl/asie/foamfix/bugfixmod/coremod/BugfixModClassTransformer.java:432-488