minecraftforge / coremods Goto Github PK
View Code? Open in Web Editor NEWCoreMods
License: GNU Lesser General Public License v2.1
CoreMods
License: GNU Lesser General Public License v2.1
There currently doesn't seem to be a way to check the type of a LDC, since using cst.getClass().getName() is not allowed. In the debug environment I was able to get around this by doing instruction.cst.getClass() == "class java.lang.X
, but when running normally the check simply fails without any error. Is there any workaround to this?
Hi, could you please create a new draft security advisory and
invite me to it?
Any other private communication channel would also be fine.
I think I've found a potential security problem.
My disclosures always follow Github's 90-day disclosure policy (I'm not an employee of Github, I just like their policy).
I think there should be a way to see the final result of a transformed class/method after all transformers have run. In 1.12.2 I did this by compiling the class and creating text files containing all the instructions both pre-transform and post-transform. I think that something similar should be implemented that provides a way to dump the bytecode of specific transformed classes before and after transformations (which classes would depend on launch arguments passed in) for debugging.
The method ASMAPI#findFirstInstructionBefore
ignores the startIndex parameter and instead always starts searching from the end of the method.
Math.max
should be replaced with Math.min
to fix this.This was introduced as part of the permissions lockdown, and I can understand the reasoning behind it. However you can use ASMAPI.getMethodNode().instructions
to get anInsnList
so access to it isn't actually restricted. Because of this I think that it's odd that InsnList
is pretty much the only ASM related class that isn't allowed to be instantiated.
Related to #10
I think that there needs to be a way to change the modifications based on if the coremod is in a deobf environment or not so that field/method names can be handled properly. If something like #10 is not done I think that a simple method that returns a boolean in the ASMAPI would be alright.
ClassNode
is not on the allowed class list, so using Java.type('org.objectweb.asm.tree.ClassNode')
crashes. However ClassNode
is required to use the CLASS
target.
If we're to support J11, we should include an up to date version of nashorn, as the JDK will not include it in J11. Also addresses desire for more recent JS lib.
I think that its pretty essential that there should be something like ObfuscationReflectionHelper that coremods can use to remap names
CWE-829: Inclusion of Functionality from Untrusted Control Sphere
All of these build files include resolving dependencies over HTTP instead of HTTPS. Any of these artifacts could have been MITM to maliciously compromise them and infect the build artifacts that were produced. Additionally, if any of these JAR files were compromised, any developers using these could continue to be infected past updating to fix this.
Lines 48 to 51 in c94c813
This vulnerability has a CVSS v3.0 Base Score of 8.1/10
https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
This isn't just theoretical; POC code exists already to maliciously compromise jar file inflight.
See:
To fix: Update your build.gradle
so that artifacts are resolved over HTTPS instead of HTTP.
(Might be related to #16)
I am trying to apply a really simple transformer through JS.
This is the JavaScript code:
function initializeCoreMod() {
print("Initializing Coremod");
return {
'loader': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/gui/GuiPlayerTabOverlay'
},
'transformer': function(classNode) {
print("Transforming ", classNode.name);
}
}
}
}
This prints:
Initializing Coremod
[...]
Transforming net/minecraft/client/gui/GuiPlayerTabOverlay
but then errors out:
[CoreMod/XFORM]: Error occurred applying transform of coremod coremod.js function loader
java.lang.ClassCastException: jdk.nashorn.internal.runtime.Undefined cannot be cast to org.objectweb.asm.tree.ClassNode
at net.minecraftforge.coremod.CoreModClassTransformer.transform(CoreModClassTransformer.java:35)
at net.minecraftforge.coremod.CoreModClassTransformer.transform(CoreModClassTransformer.java:14)
at cpw.mods.modlauncher.TransformerHolder.transform(TransformerHolder.java:23)
at cpw.mods.modlauncher.ClassTransformer.performVote(ClassTransformer.java:145)
at cpw.mods.modlauncher.ClassTransformer.transform(ClassTransformer.java:93)
at cpw.mods.modlauncher.TransformingClassLoader$DelegatedClassLoader.findClass(TransformingClassLoader.java:218)
at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:109)
at cpw.mods.modlauncher.TransformingClassLoader.loadClass(TransformingClassLoader.java:79)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
etc.
I also tried adding actual transformer code, but the result is the same.
If it's any relevant, I'm on:
Hi! As I hear that this is going to be the replacement for the current coremod/transformer system at some point in the foreseeable future, I was wondering if, at any point, this will be made able to load transformers from the old system (even if it's only possible with e.g. a config option that's off by default). This seems great for mods that only make a few small changes, but for mods that have hundreds of base edits (like CubicChunks) this seems more of a pain, and would force the clean, easily readable ASM code using tools like Mixin to be replaced with a scrambled, nearly incomprehensible mess of opcodes.
If you plan not to allow this, would you mind explaining why not?
Thanks in advance!
As per JEP 372 (Remove the Nashorn JavaScript Engine), Nashorn has now been removed from Java.
Methods like AbstractInsnNode.clone(Map<LabelNode, LabelNode> clonedLabels)
cannot be called from Nashorn without using Java.type("java.util.HashMap")
or some other Map
type, but CoreModEngine
does not allow access to java.util.HashMap
(Java.type("java.util.HashMap")
fails with java.lang.ClassNotFoundException: java.util.HashMap
).
As far as I can tell, Javascript objects in Nashorn are Map
s, but only support String
keys. Doing something like
var LabelNode = Java.type("org.objectweb.asm.tree.LabelNode");
var instruction = new LabelNode();
var map = {};
instruction.clone(map);
will give an error like:
key should be a String. It is org.objectweb.asm.tree.LabelNode instead. java.lang.ClassCastException: key should be a String. It is org.objectweb.asm.tree.LabelNode instead. at jdk.nashorn.api.scripting.ScriptObjectMirror.checkKey(ScriptObjectMirror.java:884) at jdk.nashorn.api.scripting.ScriptObjectMirror.get(ScriptObjectMirror.java:381) at org.objectweb.asm.tree.LabelNode.clone(LabelNode.java:73) at jdk.nashorn.internal.scripts.Script$Recompilation$5$18587A$\^eval\_.ASMHelper#cloneInsnList(<eval>:453) at jdk.nashorn.internal.scripts.Script$Recompilation$1$909$\^eval\_.initializeCoreMod(<eval>:58) at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
[16:44:58] [main/ERROR]: Error occurred applying transform of coremod coremods/field_to_method.js function flowing_fluid_block
java.lang.IllegalStateException: Field f_54689_ is not private and an instance field
at net.minecraftforge.coremod.api.ASMAPI.redirectFieldToMethod(ASMAPI.java:260) ~[coremods-5.0.1.jar%234!:?]
at org.openjdk.nashorn.internal.scripts.Script$Recompilation$110$707A$^eval_.initializeCoreMod#transformer-1(:21) ~[?:?]
at org.openjdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:648) ~[nashorn-core-15.3.jar%2320!:?]
at org.openjdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[nashorn-core-15.3.jar%2320!:?]
at org.openjdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:520) ~[nashorn-core-15.3.jar%2320!:?]
at org.openjdk.nashorn.api.scripting.ScriptObjectMirror.call(ScriptObjectMirror.java:111) ~[nashorn-core-15.3.jar%2320!:?]
at net.minecraftforge.coremod.NashornFactory.lambda$getFunction$0(NashornFactory.java:18) ~[coremods-5.0.1.jar%234!:5.0.1+15+master.dc5a2922]
at net.minecraftforge.coremod.transformer.CoreModClassTransformer.runCoremod(CoreModClassTransformer.java:18) ~[coremods-5.0.1.jar%234!:?]
at net.minecraftforge.coremod.transformer.CoreModClassTransformer.runCoremod(CoreModClassTransformer.java:10) ~[coremods-5.0.1.jar%234!:?]
at net.minecraftforge.coremod.transformer.CoreModBaseTransformer.transform(CoreModBaseTransformer.java:38) ~[coremods-5.0.1.jar%234!:?]
at cpw.mods.modlauncher.TransformerHolder.transform(TransformerHolder.java:41) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.ClassTransformer.performVote(ClassTransformer.java:179) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.ClassTransformer.transform(ClassTransformer.java:117) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.TransformingClassLoader.maybeTransformClassBytes(TransformingClassLoader.java:50) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.cl.ModuleClassLoader.getMaybeTransformedClassBytes(ModuleClassLoader.java:242) ~[securejarhandler-0.9.54.jar:?]
at cpw.mods.modlauncher.TransformingClassLoader.buildTransformedClassNodeFor(TransformingClassLoader.java:58) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.LaunchPluginHandler.lambda$announceLaunch$10(LaunchPluginHandler.java:100) ~[modlauncher-9.0.7.jar%235!:?]
at org.spongepowered.asm.launch.MixinLaunchPluginLegacy.getClassNode(MixinLaunchPluginLegacy.java:222) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.launch.MixinLaunchPluginLegacy.getClassNode(MixinLaunchPluginLegacy.java:207) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.ClassInfo.forName(ClassInfo.java:2005) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinInfo.getTargetClass(MixinInfo.java:1017) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinInfo.readTargetClasses(MixinInfo.java:1007) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinInfo.parseTargets(MixinInfo.java:895) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinConfig.prepareMixins(MixinConfig.java:867) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinConfig.prepare(MixinConfig.java:775) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinProcessor.prepareConfigs(MixinProcessor.java:539) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinProcessor.select(MixinProcessor.java:462) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinProcessor.checkSelect(MixinProcessor.java:438) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinProcessor.applyMixins(MixinProcessor.java:290) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.mixin.transformer.MixinTransformer.transformClass(MixinTransformer.java:250) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.service.modlauncher.MixinTransformationHandler.processClass(MixinTransformationHandler.java:131) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at org.spongepowered.asm.launch.MixinLaunchPluginLegacy.processClass(MixinLaunchPluginLegacy.java:131) ~[mixin-0.8.5.jar%2319!:0.8.5+Jenkins-b310.git-155314e6e91465dad727e621a569906a410cd6f4]
at cpw.mods.modlauncher.serviceapi.ILaunchPluginService.processClassWithFlags(ILaunchPluginService.java:156) ~[modlauncher-9.0.7.jar%235!:9.0.7+91+master.8569cdf]
at cpw.mods.modlauncher.LaunchPluginHandler.offerClassNodeToPlugins(LaunchPluginHandler.java:88) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.ClassTransformer.transform(ClassTransformer.java:120) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.TransformingClassLoader.maybeTransformClassBytes(TransformingClassLoader.java:50) ~[modlauncher-9.0.7.jar%235!:?]
at cpw.mods.cl.ModuleClassLoader.readerToClass(ModuleClassLoader.java:110) ~[securejarhandler-0.9.54.jar:?]
at cpw.mods.cl.ModuleClassLoader.lambda$findClass$16(ModuleClassLoader.java:213) ~[securejarhandler-0.9.54.jar:?]
at cpw.mods.cl.ModuleClassLoader.loadFromModule(ModuleClassLoader.java:223) ~[securejarhandler-0.9.54.jar:?]
at cpw.mods.cl.ModuleClassLoader.findClass(ModuleClassLoader.java:213) ~[securejarhandler-0.9.54.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:632) ~[?:?]
at java.lang.Class.forName(Class.java:545) ~[?:?]
at net.minecraftforge.fml.loading.targets.CommonServerLaunchHandler.lambda$launchService$0(CommonServerLaunchHandler.java:46) ~[fmlloader-1.18.1-39.0.9.jar%2323!:?]
at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:53) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:71) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.Launcher.run(Launcher.java:106) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.Launcher.main(Launcher.java:77) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.BootstrapLaunchConsumer.accept(BootstrapLaunchConsumer.java:26) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.modlauncher.BootstrapLaunchConsumer.accept(BootstrapLaunchConsumer.java:23) [modlauncher-9.0.7.jar%235!:?]
at cpw.mods.bootstraplauncher.BootstrapLauncher.main(BootstrapLauncher.java:90) [bootstraplauncher-0.1.17.jar:?]
Somewhat related to #10, an INameMappingService
can map class names just like it can do methods and fields but there's nothing exposed in the coremod API to be able to use this. Whilst obviously not useful from the context of using MCP names it does open up using other possible (class) names in dev (say Yarn or Mojang's if legal ever allow it).
We all know js isn't compiled thus leading to security issues as it could be altered. I prefer compiled mods and I can take a look in the jar and go hey this is a mod and hey I doubt this has been altered in any way. Or hey this jar looks suspicious because it has classes that don't look like a minecraft mod.
The next major concern I am going to adress is does the js even support file input streams? I need it to repalace method instructions for methods that simply don't work. I get the input stream create a class node and get a method node then port over the instructions to the original class node thus overriding it and patching any instructions/local variables. The alternative would be inject an if statement around all instructions and then manually inject the bytecode line by line which is way slower process for a computer to do and alot more mistakes will likely to happen making the mod unstable
Another thing is custom class writers. Most people using asm experience class not found exceptions being thrown only in compiled enviorment and the only way to fix it is to make a custom class writer and override the getsuper class. This is fixed with this class found here but, it needs to be a custom class writer. https://github.com/squeek502/ASMHelper/tree/1.10.x/raw/squeek/asmhelper
also I heard lex wanted signed jars which is even more secure. I think js is two steps downhill in security I hope this leans your decision away from it.
See http://openjdk.java.net/jeps/335
Considering the point of most of this rework was to keep things working on newer Java versions it seems a bit unwise to depend on something already deprecated and likely to be removed in the mid-future.
As of writing; the ability for coremods to access properties is broken due to the method of boolean conversion.
It currently uses Boolean.getBoolean which reads the given string as a property name and the looks at what the value of that property is. To make a flag "flag" be true pass `-Dcoremod.flag=true -Dtrue=true'
Responsible line:
A discussion over in Fabric's farlands led to the realization that Nashorn's load() can be used to execute JavaScript code, which injects arbitrary Java code, from an URL - a malicious entity could have some fun with it, probably. (Of course, this is already doable with regular old mods -- but the coremod API wants to be especially sandboxed.)
One way to solve this would be to just remove load():
jsContext = jsEngine.getContext()
jsContext.removeAttribute("load", jsContext.getAttributesScope("load"));
(While at it, quit() should be removed or replaced as well - right now it just quits the runtime)
Related to #7
load and quit functions were deleted, so loadWithNewGlobal and exit should probably be deleted as well
This needs the ability to read the final transformed state of the class the wrapper is being generated for
In javascript it will create LDC with a double value, which I have to add D2F after it. Maybe add a method in ASMAPI which will return a LdcInsnNode containing a float value.
Update ASM to 7
Discussed this a bit on stream before, so I'm making an issue to figure out the approach.
I generate a log with all instructions of the transformed method when the transformer fails, which makes it really easy to diagnose issues with two mods transforming the same method. This is what I used in 1.12
and older:
TraceMethodVisitor visitor = new TraceMethodVisitor(new Textifier());
for(Iterator<AbstractInsnNode> iter = method.instructions.iterator(); iter.hasNext();){
iter.next().accept(visitor);
}
// print visitor.p.getText()
with an example section of the output:
ALOAD 0
GETFIELD bud.S : Ljava/util/Random;
INVOKEVIRTUAL java/util/Random.nextFloat ()F
LDC 0.4
On stream you said Textifier
is no longer available as asm-util
is not included anymore, so I could either:
asm-util
and add a utility method to ASMAPI
with the code above, orTextifier
output, this could perhaps also include remapped namesLet me know what you think, I could PR this sometime next week.
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html
As per title you can write this in script
print(java.lang.Thread.currentThread().getContextClassLoader());
or
com.exidex.examplemod.ExampleMod.print();
It can be disabled via nashorn args
ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine("--no-java", "-doe");
(-doe is enabled by default, prints stacktrace on error)
But as ASM uses some java classes like lists, those need to be whitelisted manually
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.