diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/ASMShellGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ASMShellGenerator.java new file mode 100644 index 00000000..d717e4f1 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ASMShellGenerator.java @@ -0,0 +1,18 @@ +package com.reajason.javaweb.memshell.generator; + +import com.reajason.javaweb.memshell.config.ShellConfig; +import com.reajason.javaweb.memshell.config.ShellToolConfig; + +/** + * @author ReaJason + * @since 2025/5/27 + */ +public abstract class ASMShellGenerator implements ShellGenerator { + protected final ShellConfig shellConfig; + protected final T shellToolConfig; + + protected ASMShellGenerator(ShellConfig shellConfig, T shellToolConfig) { + this.shellConfig = shellConfig; + this.shellToolConfig = shellToolConfig; + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java index 432aad59..e5b80c77 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/AntSwordGenerator.java @@ -1,14 +1,8 @@ package com.reajason.javaweb.memshell.generator; -import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; -import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; -import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.memshell.config.AntSwordConfig; import com.reajason.javaweb.memshell.config.ShellConfig; -import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; -import org.apache.commons.lang3.StringUtils; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -16,44 +10,15 @@ import static net.bytebuddy.matcher.ElementMatchers.named; * @author ReaJason * @since 2025/02/18 */ -public class AntSwordGenerator { - private final ShellConfig shellConfig; - private final AntSwordConfig antSwordConfig; - - public AntSwordGenerator(ShellConfig shellConfig, AntSwordConfig antSwordConfig) { - this.shellConfig = shellConfig; - this.antSwordConfig = antSwordConfig; +public class AntSwordGenerator extends ByteBuddyShellGenerator { + public AntSwordGenerator(ShellConfig shellConfig, AntSwordConfig shellToolConfig) { + super(shellConfig, shellToolConfig); } - public DynamicType.Builder getBuilder() { - if (antSwordConfig.getShellClass() == null) { - throw new IllegalArgumentException("antSwordConfig.getClazz() == null"); - } - if (StringUtils.isBlank(antSwordConfig.getPass())) { - throw new IllegalArgumentException("antSwordConfig.getPass().isBlank()"); - } - DynamicType.Builder builder = new ByteBuddy() - .redefine(antSwordConfig.getShellClass()) - .name(antSwordConfig.getShellClassName()) - .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); - - if (shellConfig.isJakarta()) { - builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); - } - - if (shellConfig.isDebugOff()) { - builder = LogRemoveMethodVisitor.extend(builder); - } - - return builder.field(named("pass")).value(antSwordConfig.getPass()) - .field(named("headerName")).value(antSwordConfig.getHeaderName()) - .field(named("headerValue")).value(antSwordConfig.getHeaderValue()); - } - - public byte[] getBytes() { - DynamicType.Builder builder = getBuilder(); - try (DynamicType.Unloaded make = builder.make()) { - return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink()); - } + @Override + protected DynamicType.Builder build(DynamicType.Builder builder) { + return builder.field(named("pass")).value(shellToolConfig.getPass()) + .field(named("headerName")).value(shellToolConfig.getHeaderName()) + .field(named("headerValue")).value(shellToolConfig.getHeaderValue()); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java index 4d478cc5..a29083e3 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/BehinderGenerator.java @@ -1,15 +1,9 @@ package com.reajason.javaweb.memshell.generator; -import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; -import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; -import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.memshell.config.BehinderConfig; import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.utils.DigestUtils; -import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; -import org.apache.commons.lang3.StringUtils; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -17,46 +11,15 @@ import static net.bytebuddy.matcher.ElementMatchers.named; * @author ReaJason * @since 2024/12/21 */ -public class BehinderGenerator { - private final ShellConfig shellConfig; - private final BehinderConfig behinderConfig; - - public BehinderGenerator(ShellConfig shellConfig, BehinderConfig behinderConfig) { - this.shellConfig = shellConfig; - this.behinderConfig = behinderConfig; +public class BehinderGenerator extends ByteBuddyShellGenerator { + public BehinderGenerator(ShellConfig shellConfig, BehinderConfig shellToolConfig) { + super(shellConfig, shellToolConfig); } - public DynamicType.Builder getBuilder() { - if (behinderConfig.getShellClass() == null) { - throw new IllegalArgumentException("behinderConfig.getClazz() == null"); - } - if (StringUtils.isBlank(behinderConfig.getPass())) { - throw new IllegalArgumentException("behinderConfig.getPass().isBlank()"); - } - String md5Key = DigestUtils.md5Hex(behinderConfig.getPass()).substring(0, 16); - - DynamicType.Builder builder = new ByteBuddy() - .redefine(behinderConfig.getShellClass()) - .name(behinderConfig.getShellClassName()) - .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); - - if (shellConfig.isJakarta()) { - builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); - } - - if (shellConfig.isDebugOff()) { - builder = LogRemoveMethodVisitor.extend(builder); - } - + public DynamicType.Builder build(DynamicType.Builder builder) { + String md5Key = DigestUtils.md5Hex(shellToolConfig.getPass()).substring(0, 16); return builder.field(named("pass")).value(md5Key) - .field(named("headerName")).value(behinderConfig.getHeaderName()) - .field(named("headerValue")).value(behinderConfig.getHeaderValue()); - } - - public byte[] getBytes() { - DynamicType.Builder builder = getBuilder(); - try (DynamicType.Unloaded make = builder.make()) { - return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink()); - } + .field(named("headerName")).value(shellToolConfig.getHeaderName()) + .field(named("headerValue")).value(shellToolConfig.getHeaderValue()); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/ByteBuddyShellGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ByteBuddyShellGenerator.java new file mode 100644 index 00000000..368edff6 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ByteBuddyShellGenerator.java @@ -0,0 +1,47 @@ +package com.reajason.javaweb.memshell.generator; + +import com.reajason.javaweb.ClassBytesShrink; +import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor; +import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; +import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; +import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; +import com.reajason.javaweb.memshell.config.ShellConfig; +import com.reajason.javaweb.memshell.config.ShellToolConfig; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.dynamic.DynamicType; + +/** + * @author ReaJason + * @since 2025/5/27 + */ +public abstract class ByteBuddyShellGenerator implements ShellGenerator { + protected final ShellConfig shellConfig; + protected final T shellToolConfig; + + protected ByteBuddyShellGenerator(ShellConfig shellConfig, T shellToolConfig) { + this.shellConfig = shellConfig; + this.shellToolConfig = shellToolConfig; + } + + protected abstract DynamicType.Builder build(DynamicType.Builder builder); + + @Override + public byte[] getBytes() { + DynamicType.Builder builder = build(new ByteBuddy() + .redefine(shellToolConfig.getShellClass()) + .name(shellToolConfig.getShellClassName()) + .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))); + + if (shellConfig.isJakarta()) { + builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); + } + + if (shellConfig.isDebugOff()) { + builder = LogRemoveMethodVisitor.extend(builder); + } + + try (DynamicType.Unloaded unloaded = builder.make()) { + return ClassBytesShrink.shrink(unloaded.getBytes(), shellConfig.isShrink()); + } + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/CustomShellGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/CustomShellGenerator.java index 38d242a1..1037d4f5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/CustomShellGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/CustomShellGenerator.java @@ -12,25 +12,21 @@ import java.util.Base64; * @author ReaJason * @since 2025/3/18 */ -public class CustomShellGenerator { - - private final ShellConfig shellConfig; - private final CustomConfig customConfig; +public class CustomShellGenerator extends ASMShellGenerator { public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) { - this.shellConfig = shellConfig; - this.customConfig = customConfig; + super(shellConfig, customConfig); } + @Override public byte[] getBytes() { - String shellClassBase64 = customConfig.getShellClassBase64(); + String shellClassBase64 = shellToolConfig.getShellClassBase64(); if (StringUtils.isBlank(shellClassBase64)) { throw new IllegalArgumentException("Custom shell class is empty"); } - - byte[] bytes = ClassRenameUtils.renameClass(Base64.getDecoder().decode(shellClassBase64), customConfig.getShellClassName()); - + byte[] classBytes = Base64.getDecoder().decode(shellClassBase64); + byte[] bytes = ClassRenameUtils.renameClass(classBytes, shellToolConfig.getShellClassName()); return ClassBytesShrink.shrink(bytes, shellConfig.isShrink()); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java index 7bf5dd6a..1f6c3918 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/GodzillaGenerator.java @@ -1,15 +1,10 @@ package com.reajason.javaweb.memshell.generator; import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; -import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; -import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.memshell.config.GodzillaConfig; import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.utils.DigestUtils; -import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; -import org.apache.commons.lang3.StringUtils; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -17,49 +12,20 @@ import static net.bytebuddy.matcher.ElementMatchers.named; * @author ReaJason * @since 2024/11/23 */ -public class GodzillaGenerator { - private final ShellConfig shellConfig; - private final GodzillaConfig godzillaConfig; +public class GodzillaGenerator extends ByteBuddyShellGenerator { public GodzillaGenerator(ShellConfig shellConfig, GodzillaConfig godzillaConfig) { - this.shellConfig = shellConfig; - this.godzillaConfig = godzillaConfig; + super(shellConfig, godzillaConfig); } - public DynamicType.Builder getBuilder() { - if (godzillaConfig.getShellClass() == null) { - throw new IllegalArgumentException("godzillaConfig.getClazz() == null"); - } - if (StringUtils.isBlank(godzillaConfig.getKey()) || StringUtils.isBlank(godzillaConfig.getPass())) { - throw new IllegalArgumentException("godzillaConfig.getKey().isBlank() || godzillaConfig.getPass().isBlank()"); - } - String md5Key = DigestUtils.md5Hex(godzillaConfig.getKey()).substring(0, 16); - String md5 = DigestUtils.md5Hex(godzillaConfig.getPass() + md5Key).toUpperCase(); - - DynamicType.Builder builder = new ByteBuddy() - .redefine(godzillaConfig.getShellClass()) - .name(godzillaConfig.getShellClassName()) - .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); - - if (shellConfig.isJakarta()) { - builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); - } - - if (shellConfig.isDebugOff()) { - builder = LogRemoveMethodVisitor.extend(builder); - } - - return builder.field(named("pass")).value(godzillaConfig.getPass()) + @Override + public DynamicType.Builder build(DynamicType.Builder builder) { + String md5Key = DigestUtils.md5Hex(shellToolConfig.getKey()).substring(0, 16); + String md5 = DigestUtils.md5Hex(shellToolConfig.getPass() + md5Key).toUpperCase(); + return builder.field(named("pass")).value(shellToolConfig.getPass()) .field(named("key")).value(md5Key) .field(named("md5")).value(md5) - .field(named("headerName")).value(godzillaConfig.getHeaderName()) - .field(named("headerValue")).value(godzillaConfig.getHeaderValue()); - } - - public byte[] getBytes() { - DynamicType.Builder builder = getBuilder(); - try (DynamicType.Unloaded make = builder.make()) { - return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink()); - } + .field(named("headerName")).value(shellToolConfig.getHeaderName()) + .field(named("headerValue")).value(shellToolConfig.getHeaderValue()); } } \ No newline at end of file diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java index 98cdfd99..62974ec5 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/NeoreGeorgGenerator.java @@ -1,12 +1,7 @@ package com.reajason.javaweb.memshell.generator; -import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; -import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; -import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.memshell.config.NeoreGeorgConfig; import com.reajason.javaweb.memshell.config.ShellConfig; -import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -15,37 +10,14 @@ import static net.bytebuddy.matcher.ElementMatchers.named; * @author ReaJason * @since 2025/2/12 */ -public class NeoreGeorgGenerator { - private final ShellConfig shellConfig; - private final NeoreGeorgConfig neoreGeorgConfig; - +public class NeoreGeorgGenerator extends ByteBuddyShellGenerator { public NeoreGeorgGenerator(ShellConfig shellConfig, NeoreGeorgConfig neoreGeorgConfig) { - this.shellConfig = shellConfig; - this.neoreGeorgConfig = neoreGeorgConfig; + super(shellConfig, neoreGeorgConfig); } - public DynamicType.Builder getBuilder() { - DynamicType.Builder builder = new ByteBuddy() - .redefine(neoreGeorgConfig.getShellClass()) - .name(neoreGeorgConfig.getShellClassName()) - .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); - - if (shellConfig.isJakarta()) { - builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); - } - - if (shellConfig.isDebugOff()) { - builder = LogRemoveMethodVisitor.extend(builder); - } - - return builder.field(named("headerName")).value(neoreGeorgConfig.getHeaderName()) - .field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue()); - } - - public byte[] getBytes() { - DynamicType.Builder builder = getBuilder(); - try (DynamicType.Unloaded make = builder.make()) { - return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink()); - } + @Override + protected DynamicType.Builder build(DynamicType.Builder builder) { + return builder.field(named("headerName")).value(shellToolConfig.getHeaderName()) + .field(named("headerValue")).value(shellToolConfig.getHeaderValue()); } } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/ShellGenerator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ShellGenerator.java new file mode 100644 index 00000000..152c7475 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/ShellGenerator.java @@ -0,0 +1,10 @@ +package com.reajason.javaweb.memshell.generator; + +/** + * @author ReaJason + * @since 2025/5/27 + */ +public interface ShellGenerator { + + byte[] getBytes(); +} diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java b/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java index 546b06d9..e133acec 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/generator/Suo5Generator.java @@ -1,12 +1,7 @@ package com.reajason.javaweb.memshell.generator; -import com.reajason.javaweb.ClassBytesShrink; -import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; -import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper; -import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.Suo5Config; -import net.bytebuddy.ByteBuddy; import net.bytebuddy.dynamic.DynamicType; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -15,38 +10,16 @@ import static net.bytebuddy.matcher.ElementMatchers.named; * @author ReaJason * @since 2025/2/12 */ -public class Suo5Generator { - private final ShellConfig shellConfig; - private final Suo5Config suo5Config; +public class Suo5Generator extends ByteBuddyShellGenerator { public Suo5Generator(ShellConfig shellConfig, Suo5Config suo5Config) { - this.shellConfig = shellConfig; - this.suo5Config = suo5Config; + super(shellConfig, suo5Config); } - public DynamicType.Builder getBuilder() { - DynamicType.Builder builder = new ByteBuddy() - .redefine(suo5Config.getShellClass()) - .name(suo5Config.getShellClassName()) - .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); - - if (shellConfig.isJakarta()) { - builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); - } - - if (shellConfig.isDebugOff()) { - builder = LogRemoveMethodVisitor.extend(builder); - } - + @Override + protected DynamicType.Builder build(DynamicType.Builder builder) { return builder - .field(named("headerName")).value(suo5Config.getHeaderName()) - .field(named("headerValue")).value(suo5Config.getHeaderValue()); - } - - public byte[] getBytes() { - DynamicType.Builder builder = getBuilder(); - try (DynamicType.Unloaded make = builder.make()) { - return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink()); - } + .field(named("headerName")).value(shellToolConfig.getHeaderName()) + .field(named("headerValue")).value(shellToolConfig.getHeaderValue()); } } diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/generator/GodzillaGeneratorTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/generator/GodzillaGeneratorTest.java index 3b593d83..1efdf049 100644 --- a/generator/src/test/java/com/reajason/javaweb/memshell/generator/GodzillaGeneratorTest.java +++ b/generator/src/test/java/com/reajason/javaweb/memshell/generator/GodzillaGeneratorTest.java @@ -7,6 +7,7 @@ import com.reajason.javaweb.memshell.config.GodzillaConfig; import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaServlet; import com.reajason.javaweb.memshell.utils.CommonUtil; +import com.reajason.javaweb.util.ClassDefiner; import com.reajason.javaweb.util.ClassUtils; import lombok.SneakyThrows; import net.bytebuddy.dynamic.DynamicType; @@ -38,8 +39,8 @@ class GodzillaGeneratorTest { .key("key") .headerName("User-Agent") .headerValue("test").build(); - DynamicType.Builder builder = new GodzillaGenerator(shellConfig, godzillaConfig).getBuilder(); - Class loaded = builder.make().load(this.getClass().getClassLoader()).getLoaded(); + byte[] bytes = new GodzillaGenerator(shellConfig, godzillaConfig).getBytes(); + Class loaded = ClassDefiner.defineClass(bytes); Object o = loaded.getDeclaredConstructor().newInstance(); assertEquals(godzillaConfig.getPass(), ClassUtils.getFieldValue(o, "pass")); assertEquals(godzillaConfig.getHeaderName(), ClassUtils.getFieldValue(o, "headerName"));